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]

Reply via email to