haoyangeng-db commented on code in PR #56024:
URL: https://github.com/apache/spark/pull/56024#discussion_r3282614629
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala:
##########
@@ -1535,6 +1535,32 @@ class Analyzer(
}
def doApply(plan: LogicalPlan): LogicalPlan = plan.resolveOperatorsUp {
+ // `InsertIntoStatement.table` and `V2WriteCommand.table` are non-child
`LogicalPlan`
+ // slots (`child = query`), so the default `resolveOperatorsUp` +
`mapExpressions`
+ // traversal never resolves expressions placed inside them. For a
+ // `PlanWithUnresolvedIdentifier`, `identifierExpr` (e.g. an
`UnresolvedAttribute`
+ // referring to a SQL variable in `INSERT INTO IDENTIFIER(target_table)
...`) must
+ // be resolved here before `ResolveIdentifierClause` can materialize the
relation.
+ // Mirror the recursion that `BindParameters` and
`ResolveIdentifierClause` already
+ // do for the same shape (SPARK-46625). The `!identifierExpr.resolved`
guard makes
+ // the case idempotent under bottom-up traversal.
+ case i: InsertIntoStatement
+ if i.table.isInstanceOf[PlanWithUnresolvedIdentifier] &&
+
!i.table.asInstanceOf[PlanWithUnresolvedIdentifier].identifierExpr.resolved =>
+ val p = i.table.asInstanceOf[PlanWithUnresolvedIdentifier]
+ val resolvedExpr = resolveExpressionByPlanChildren(
+ p.identifierExpr, i, includeLastResort = true)
Review Comment:
Done.
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala:
##########
@@ -1535,6 +1535,32 @@ class Analyzer(
}
def doApply(plan: LogicalPlan): LogicalPlan = plan.resolveOperatorsUp {
+ // `InsertIntoStatement.table` and `V2WriteCommand.table` are non-child
`LogicalPlan`
+ // slots (`child = query`), so the default `resolveOperatorsUp` +
`mapExpressions`
+ // traversal never resolves expressions placed inside them. For a
+ // `PlanWithUnresolvedIdentifier`, `identifierExpr` (e.g. an
`UnresolvedAttribute`
+ // referring to a SQL variable in `INSERT INTO IDENTIFIER(target_table)
...`) must
+ // be resolved here before `ResolveIdentifierClause` can materialize the
relation.
+ // Mirror the recursion that `BindParameters` and
`ResolveIdentifierClause` already
+ // do for the same shape (SPARK-46625). The `!identifierExpr.resolved`
guard makes
+ // the case idempotent under bottom-up traversal.
+ case i: InsertIntoStatement
+ if i.table.isInstanceOf[PlanWithUnresolvedIdentifier] &&
+
!i.table.asInstanceOf[PlanWithUnresolvedIdentifier].identifierExpr.resolved =>
+ val p = i.table.asInstanceOf[PlanWithUnresolvedIdentifier]
+ val resolvedExpr = resolveExpressionByPlanChildren(
+ p.identifierExpr, i, includeLastResort = true)
+ resolveColumnDefaultInCommandInputQuery(
Review Comment:
Done.
##########
sql/core/src/test/scala/org/apache/spark/sql/ParametersSuite.scala:
##########
@@ -2586,6 +2586,28 @@ class ParametersSuite extends SharedSparkSession {
s"Expected :tname inside OverwriteByExpression.table to be bound,
got:\n$boundOverwrite")
}
+ // SPARK-46625 followup: `INSERT INTO IDENTIFIER(<sql-variable>) ...` places
a
+ // `PlanWithUnresolvedIdentifier` in `InsertIntoStatement.table`, whose
`identifierExpr`
+ // holds an `UnresolvedAttribute` for the variable name. That slot is a
non-child
+ // `LogicalPlan`, so the default `ResolveReferences` traversal never
resolves the
+ // attribute, `ResolveIdentifierClause` cannot fire (it waits on
`identifierExpr.resolved`),
+ // and analysis fails. Verify that the explicit `InsertIntoStatement` case
added to
+ // `ResolveReferences` rewrites the attribute to a `VariableReference` and
the insert
+ // completes end-to-end.
+ test("SPARK-46625: INSERT INTO IDENTIFIER(<sql-variable>) resolves variable
in table slot") {
+ withTable("t_var_insert") {
+ sql("CREATE TABLE t_var_insert (a INT) USING PARQUET")
+ sql("DECLARE OR REPLACE VARIABLE target_table STRING")
+ try {
+ sql("SET VAR target_table = 't_var_insert'")
+ sql("INSERT INTO IDENTIFIER(target_table) SELECT 42 AS a")
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]