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


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala:
##########
@@ -1720,6 +1760,100 @@ object JsonArray {
   }
 }
 
+/**
+ * A parsed `JSON_ARRAY(...)` / `JSON_OBJECT(...)` whose splice flags are 
finalized after child
+ * resolution: parser flags keep explicit `FORMAT JSON` and lexical nested 
constructors, and the
+ * resolved children add qualified/routed nested constructors the parser 
cannot see.
+ *
+ * A clause-free call sets `routeThroughResolution` so a same-named routine 
(or an `injectFunction`
+ * replacement) can shadow it; it then resolves as a plain 
`prettyName(arguments...)` call. Other
+ * calls are owned by the stock built-in.
+ */
+trait UnresolvedJsonConstructor
+  extends Unevaluable
+  with DefaultStringProducingExpression

Review Comment:
   Done



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala:
##########
@@ -709,6 +709,7 @@ class Analyzer(
       ResolveAliases ::
       ResolveSubquery ::
       ResolveSubqueryColumnAliases ::
+      ResolveJsonConstructors ::

Review Comment:
   Done



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala:
##########
@@ -1314,6 +1314,57 @@ trait ImplicitlyFormattedAsJson extends Expression {
   def emitsImplicitJsonText: Boolean = true
 }
 
+object ImplicitlyFormattedAsJson {
+  /**
+   * Whether `e` lexically emits JSON text -- i.e. carries an implicit 
SQL/JSON `FORMAT JSON` and
+   * should be spliced raw rather than quoted (a nested JSON constructor, or 
`JSON_QUERY` under
+   * `KEEP QUOTES`; see [[ImplicitlyFormattedAsJson]]). Sees through a 
value-preserving `Collate`
+   * (a postfix `... COLLATE c` only annotates the collation of the JSON text, 
e.g.
+   * `JSON_ARRAY(JSON_ARRAY(1) COLLATE UTF8_LCASE)`), but deliberately NOT 
through a `Cast`:
+   * `AstBuilder`/`JsonArray.sql` use a `CAST(... AS STRING)` wrapper 
specifically to detach a value
+   * from implicit `FORMAT JSON`, so unwrapping it would defeat that 
neutralization. The routed/
+   * qualified builders use [[splicesThroughCollationCast]], which 
additionally sees through an
+   * analyzer collation `Cast`.
+   */
+  @scala.annotation.tailrec
+  def isImplicitlyJson(e: Expression): Boolean = e match {
+    case c: Collate => isImplicitlyJson(c.child)
+    case i: ImplicitlyFormattedAsJson => i.emitsImplicitJsonText
+    case _ => false
+  }
+
+  /**
+   * The routed/qualified splice decision made by `JsonArrayExpressionBuilder` 
/
+   * `JsonObjectExpressionBuilder` on a resolved argument. Like 
[[isImplicitlyJson]], but also sees
+   * through an analyzer-inserted collation `Cast`: under an object/view 
default collation,
+   * `ApplyDefaultCollation` wraps a nested producer in a `Cast` to the 
default `StringType` before
+   * the builder runs, which would otherwise hide the producer and quote it 
(unlike the direct
+   * grammar path, which freezes the decision at parse time). Only a genuine 
collation change is
+   * unwrapped (the cast recolors existing JSON text); a user `CAST(... AS 
STRING)` or the
+   * `string(...)` alias still detaches, so the explicit-cast quoting is 
preserved.
+   */
+  @scala.annotation.tailrec
+  def splicesThroughCollationCast(e: Expression): Boolean = e match {
+    case c: Cast if isAnalyzerCollationCast(c) => 
splicesThroughCollationCast(c.child)
+    case _ => isImplicitlyJson(e)

Review Comment:
   Done



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/ResolverGuard.scala:
##########
@@ -629,7 +629,8 @@ class ResolverGuard(
       // JSON
       case _: GetJsonObject | _: JsonTuple | _: JsonToStructs | _: 
StructsToJson |
           _: SchemaOfJson | _: JsonObjectKeys | _: LengthOfJsonArray | _: 
JsonArray |
-          _: JsonExists | _: JsonQuery | _: JsonValue | _: JsonObjectExpr =>
+          _: JsonExists | _: JsonQuery | _: JsonValue | _: JsonObjectExpr |
+          _: UnresolvedJsonConstructor =>

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