Skip to content

[SPARK-58933][SQL][4.2] Resolve expressions in INSERT target IDENTIFIER clauses - #58373

Closed
cloud-fan wants to merge 1 commit into
apache:branch-4.2from
cloud-fan:SPARK-58933-branch-4.2
Closed

[SPARK-58933][SQL][4.2] Resolve expressions in INSERT target IDENTIFIER clauses#58373
cloud-fan wants to merge 1 commit into
apache:branch-4.2from
cloud-fan:SPARK-58933-branch-4.2

Conversation

@cloud-fan

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

This backports #58204 (3bc29d9d0ae031dfe0e793886ba652ca98ae7f29) to branch-4.2.

It introduces a temporary binary UnresolvedInsert plan for INSERT statements whose target uses a
dynamic IDENTIFIER(...) expression. This lets normal analyzer traversal resolve parameters,
functions, and SQL variables in the target before lowering the plan to the existing write plan.

For branch-4.2, INSERT ... REPLACE WHERE is lowered to that branch's
OverwriteByExpression representation. The transactional regression test is also expressed using
the older transaction test harness. The parse-metadata changes from the original commit are omitted
because the corresponding ParseSqlResult and SqlStatementCodes infrastructure is not present on
branch-4.2.

Why are the changes needed?

InsertIntoStatement.table is not a logical-plan child, so analyzer rules do not normally visit a
dynamic target expression stored there. Nested functions, parameters, or SQL variables can
therefore remain unresolved.

Does this PR introduce any user-facing change?

Yes. INSERT statements on branch-4.2 can now resolve expressions inside a target IDENTIFIER
clause, matching the behavior fixed on master by #58204.

How was this patch tested?

The backported parser, analyzer, end-to-end, and transactional-catalog tests were included and
adapted to branch-4.2. The following checks passed locally with Java 17:

build/sbt -java-home /usr/lib/jvm/java-17-openjdk-amd64 \
  catalyst/Test/compile \
  'sql/testOnly org.apache.spark.sql.ParametersSuite' \
  'sql/testOnly org.apache.spark.sql.connector.AppendDataTransactionSuite' \
  pipelines/compile connect/compile

ParametersSuite: 161 tests passed. AppendDataTransactionSuite: 18 tests passed.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: OpenAI Codex (GPT-5)

…auses

### What changes were proposed in this pull request?

This PR introduces a temporary binary `UnresolvedInsert` plan for INSERT statements whose target
uses a dynamic `IDENTIFIER(...)` expression. Its target and input query are ordinary children, so
analyzer rules can resolve parameters, functions, and SQL variables in the target expression
through normal tree traversal.

After the expression is evaluated, its builder creates an `UnresolvedInsertTarget` containing the
raw multipart identifier, target options, and write privileges. The analyzer then converts this
marker to an `UnresolvedRelation` and lowers `UnresolvedInsert` to the existing unary
`InsertIntoStatement`. The target is subsequently qualified and resolved by the existing INSERT
analysis path.

`UnresolvedInsertTarget` is deliberately not a `NamedRelation`, so CTE substitution cannot treat
an INSERT target as a readable relation. Static table names and literal `IDENTIFIER` clauses still
parse directly to `InsertIntoStatement` and retain the existing behavior.

`QueryExecution` resolves only the dynamic target identifier before transaction detection. This
allows transactional INSERTs to be recognized without adding a separate target-resolution path or
changing the long-lived child contract of `InsertIntoStatement`.

`ResolveUnresolvedInsert` uses a dedicated tree pattern and rule ID, so the fixed-point Resolution
batch skips plans that cannot contain the temporary carrier.

### Why are the changes needed?

`InsertIntoStatement.table` is not a logical-plan child, so normal analyzer rules do not visit a
dynamic `IDENTIFIER` expression stored in that slot. Nested functions, parameters, or SQL variables
can therefore remain unresolved.

Making `InsertIntoStatement` permanently binary would affect analyzer, planner, lineage, and
command consumers that rely on its input query being its only child. The temporary
`UnresolvedInsert` node limits the binary shape to identifier-expression resolution, while
`UnresolvedInsertTarget` preserves the raw name until normal relation resolution. This also avoids
qualifying an already-resolved identifier a second time.

### Does this PR introduce _any_ user-facing change?

Yes. INSERT statements can now resolve expressions inside a target `IDENTIFIER` clause. For
example, the following statement now resolves and executes correctly:

```sql
INSERT INTO IDENTIFIER(
  lower(regexp_replace(:table_name, 'PLACEHOLDER', 'TBL')))
REPLACE WHERE id = 1
VALUES (1, 'updated')
```

### How was this patch tested?

Added parser, analyzer, end-to-end, parse-metadata lineage and classification, and
transactional-catalog coverage for dynamic INSERT targets, including parameters, nested functions,
SQL variables, qualified multipart names, query-source and select-list extraction, and a target
sharing its name with a CTE.

The following compile and test checks passed:

```bash
build/sbt catalyst/Test/compile
build/sbt 'sql/testOnly org.apache.spark.sql.ParametersSuite'
build/sbt 'sql/testOnly org.apache.spark.sql.catalyst.parser.ParseSqlResultSuite'
build/sbt 'sql/testOnly org.apache.spark.sql.connector.AppendDataTransactionSuite'
build/sbt pipelines/compile
build/sbt connect/compile
SPARK_GENERATE_GOLDEN_FILES=1 build/sbt \
  'sql/testOnly org.apache.spark.sql.SQLQueryTestSuite -- -z explain.sql'
SPARK_GENERATE_GOLDEN_FILES=1 build/sbt \
  'sql/testOnly org.apache.spark.sql.SQLQueryTestSuite -- -z explain-aqe.sql'
```

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: OpenAI Codex (GPT-5)

Closes apache#58204 from cloud-fan/fix-identifier-dml-table-resolution.

Authored-by: Wenchen Fan <wenchen@databricks.com>
Signed-off-by: Wenchen Fan <wenchen@databricks.com>
@cloud-fan

Copy link
Copy Markdown
Contributor Author

thanks for review, merging to 4.2!

cloud-fan added a commit that referenced this pull request Aug 28, 2026
…ER clauses

### What changes were proposed in this pull request?

This backports #58204 (`3bc29d9d0ae031dfe0e793886ba652ca98ae7f29`) to branch-4.2.

It introduces a temporary binary `UnresolvedInsert` plan for INSERT statements whose target uses a
dynamic `IDENTIFIER(...)` expression. This lets normal analyzer traversal resolve parameters,
functions, and SQL variables in the target before lowering the plan to the existing write plan.

For branch-4.2, `INSERT ... REPLACE WHERE` is lowered to that branch's
`OverwriteByExpression` representation. The transactional regression test is also expressed using
the older transaction test harness. The parse-metadata changes from the original commit are omitted
because the corresponding `ParseSqlResult` and `SqlStatementCodes` infrastructure is not present on
branch-4.2.

### Why are the changes needed?

`InsertIntoStatement.table` is not a logical-plan child, so analyzer rules do not normally visit a
dynamic target expression stored there. Nested functions, parameters, or SQL variables can
therefore remain unresolved.

### Does this PR introduce _any_ user-facing change?

Yes. INSERT statements on branch-4.2 can now resolve expressions inside a target `IDENTIFIER`
clause, matching the behavior fixed on master by #58204.

### How was this patch tested?

The backported parser, analyzer, end-to-end, and transactional-catalog tests were included and
adapted to branch-4.2. The following checks passed locally with Java 17:

```bash
build/sbt -java-home /usr/lib/jvm/java-17-openjdk-amd64 \
  catalyst/Test/compile \
  'sql/testOnly org.apache.spark.sql.ParametersSuite' \
  'sql/testOnly org.apache.spark.sql.connector.AppendDataTransactionSuite' \
  pipelines/compile connect/compile
```

`ParametersSuite`: 161 tests passed. `AppendDataTransactionSuite`: 18 tests passed.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: OpenAI Codex (GPT-5)

Closes #58373 from cloud-fan/SPARK-58933-branch-4.2.

Authored-by: Wenchen Fan <wenchen@databricks.com>
Signed-off-by: Wenchen Fan <wenchen@databricks.com>
@cloud-fan cloud-fan closed this Aug 28, 2026
@cloud-fan

Copy link
Copy Markdown
Contributor Author

Merge Summary:

Posted by merge_spark_pr.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants