ganeshashree commented on code in PR #58034:
URL: https://github.com/apache/spark/pull/58034#discussion_r4048042024
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala:
##########
@@ -2210,3 +2243,347 @@ case class JsonTypeof(child: Expression)
override protected def withNewChildInternal(newChild: Expression):
JsonTypeof =
copy(child = newChild)
}
+
+/**
+ * The SQL:2016 `JSON_OBJECT` constructor function (feature T811): constructs
a JSON object from
+ * key-value pairs, written `key VALUE value`, `KEY key VALUE value`, `key :
value`, or the
+ * MySQL-style `key, value`.
+ *
+ * Keys must be non-null strings; a null key is an error. The `ON NULL` clause
controls whether
+ * null-valued pairs are included (NULL ON NULL, the standard default) or
omitted (ABSENT ON NULL).
+ *
+ * A value is spliced in raw (unquoted) only when it is a lexically nested
JSON constructor
+ * (implicit `FORMAT JSON`, tracked by `rawJson`). The standard's explicit
value-level `FORMAT JSON`
+ * clause (e.g. `JSON_OBJECT('a' VALUE '{"b":1}' FORMAT JSON)`) is deferred.
+ *
+ * Examples:
+ * JSON_OBJECT('id' VALUE 7, 'name' VALUE 'Ada') ->
'{"id":7,"name":"Ada"}'
+ * JSON_OBJECT('id': 7, 'v': NULL) -> '{"id":7,"v":null}'
+ * JSON_OBJECT('id': 7, 'v': NULL ABSENT ON NULL) -> '{"id":7}'
+ * JSON_OBJECT() -> '{}'
+ *
+ * A flat, clause-free call routes through function resolution and is rebuilt
by
+ * `JsonObjectExpressionBuilder` (so a same-named routine can shadow the
built-in `json_object`); a
+ * clause-bearing or nested form is built directly from the grammar (see
+ * `AstBuilder.visitJsonObject`). The user-facing reference lives in
+ * `docs/sql-ref-syntax-qry-select-json-object.md`.
+ */
+case class JsonObjectExpr(
+ members: Seq[(Expression, Expression)],
+ rawJson: Seq[Boolean],
+ nullBehavior: JsonConstructorNullBehavior =
JsonConstructorNullBehavior.Null,
+ returning: DataType = StringType,
+ timeZoneId: Option[String] = None)
+ extends Expression
+ with TimeZoneAwareExpression
+ with CodegenFallback
+ with QueryErrorsBase
+ // Default RETURNING is a plain STRING, so
`DefaultStringProducingExpression` lets
+ // `ApplyDefaultCollation` cast the result to a non-default collation; the
`dataType` override
+ // below stays authoritative when RETURNING is given explicitly.
+ with DefaultStringProducingExpression
+ with ImplicitlyFormattedAsJson {
+
+ // `rawJson(i)` marks member `i`'s value as already-JSON text to splice
verbatim, not quote; it is
+ // frozen at parse time (see `AstBuilder.visitJsonObject`,
[[ImplicitlyFormattedAsJson]]).
+ require(members.length == rawJson.length,
+ "JsonObjectExpr requires one rawJson flag per member")
+
+ @transient private lazy val memberArray: Array[(Expression, Expression)] =
+ members.toArray
+
+ @transient private lazy val rawJsonArray: Array[Boolean] =
+ rawJson.toArray
+
+ // Always throwable: a null key raises JSON_OBJECT_NULL_KEY at eval even
with non-throwable
+ // children, which keeps the optimizer from pushing it below a filtering
join. Left non-foldable
+ // (the default) so folding a constant call does not eagerly raise that
null-key error at
+ // optimization for rows a filter would later drop.
+ override lazy val throwable: Boolean = true
+
+ // The value is never null, but report nullable as `throwable` (like
JsonArray): `NullPropagation`
+ // keys off `nullable`, so a non-nullable constructor would let it fold `IS
[NOT] NULL` to a
+ // constant or `count(...)` to `count(1)`, skipping the eval that must raise
JSON_OBJECT_NULL_KEY.
+ override def nullable: Boolean = throwable
+
+ override def dataType: DataType = returning
+
+ override def children: Seq[Expression] =
+ memberArray.flatMap { case (k, v) => Seq(k, v) }.toImmutableArraySeq
Review Comment:
Done.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]