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]