ganeshashree commented on code in PR #59828:
URL: https://github.com/apache/spark/pull/59828#discussion_r4439672034


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala:
##########
@@ -1314,6 +1311,46 @@ trait ImplicitlyFormattedAsJson extends Expression {
   def emitsImplicitJsonText: Boolean = true
 }
 
+object ImplicitlyFormattedAsJson {
+  /**
+   * Whether `e` emits JSON text, so a JSON constructor splices it instead of 
quoting it. Sees
+   * through `Collate`, which only changes the collation, but not `Cast`: 
`CAST(... AS STRING)` is
+   * how a user (and `JsonArray.sql`) asks for the value to be quoted.
+   */
+  @scala.annotation.tailrec
+  def isImplicitlyJson(e: Expression): Boolean = e match {
+    case c: Collate => isImplicitlyJson(c.child)
+    case i: ImplicitlyFormattedAsJson => i.emitsImplicitJsonText
+    case _ => false
+  }
+
+  /**
+   * The splice decision for a resolved argument, used by the builders and by 
the parser wrappers
+   * when they finalize their flags. Like [[isImplicitlyJson]], but also sees 
through the collation
+   * `Cast` that the analyzer adds under an object or view default collation 
(mixed with `Collate`
+   * in any order). A user cast, including `string(...)`, still makes the 
value quoted.

Review Comment:
   Done.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala:
##########
@@ -4501,7 +4497,7 @@ class AstBuilder extends DataTypeAstBuilder
       // JSON_OBJECT defaults to NULL ON NULL per the standard (emits keys 
with null values).
       val nullBehavior = Option(body.nullBehavior)
         
.map(buildJsonConstructorNullBehavior).getOrElse(JsonConstructorNullBehavior.Null)
-      JsonObjectExpr(members, rawJson, needsValidation, nullBehavior, 
returning)
+      UnresolvedJsonObject(members, rawJson, needsValidation, nullBehavior, 
returning)

Review Comment:
   Done.



##########
sql/core/src/test/scala/org/apache/spark/sql/analysis/resolver/ResolverGuardSuite.scala:
##########
@@ -143,17 +143,21 @@ class ResolverGuardSuite extends ResolverGuardSuiteBase {
   test("SQL JSON constructor and path functions") {
     checkResolverGuard("""SELECT JSON_ARRAY(1, 'x', true)""")
     checkResolverGuard("""SELECT JSON_ARRAY('[1]' FORMAT JSON)""")
+    // Nested clause-free JSON_ARRAY routes as UnresolvedRoutedJsonArray 
before resolution; the
+    // guard gives it the flat call's owner check and admits the unshadowed 
built-in.
+    checkResolverGuard("""SELECT JSON_ARRAY(JSON_ARRAY(1))""")
     checkResolverGuard("""SELECT JSON_VALUE('{"a":1}', '$.a')""")
     checkResolverGuard("""SELECT JSON_VALUE('{"a":1}', '$.a' RETURNING INT)""")
     checkResolverGuard("""SELECT JSON_QUERY('{"a":[1]}', '$.a')""")
     checkResolverGuard("""SELECT JSON_QUERY('{"a":[1]}', '$.a' WITH ARRAY 
WRAPPER)""")
     checkResolverGuard("""SELECT JSON_EXISTS('{"a":1}', '$.a')""")
     checkResolverGuard("""SELECT JSON_EXISTS('{"a":1}', '$.a' TRUE ON 
ERROR)""")
-    // A clause-free JSON_OBJECT routes as an UnresolvedFunction unless a 
VALUE/colon member is raw;
-    // such a call, or a clause-bearing one, is built directly as a 
JsonObjectExpr. Assert the guard
-    // admits that direct form (removing its allowlist arm would fail here).
+    // Clause-bearing and explicit FORMAT JSON forms parse to a stock-owned 
UnresolvedJsonObject;

Review Comment:
   Added a guard case over an analyzed plan holding a resolved `JsonArray` and 
`JsonObjectExpr`. Removing either arm still cannot fail it, though: both are 
`TimeZoneAwareExpression`s, which the earlier `TimeZoneAwareExpression` arm 
already admits (also on master).



-- 
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