Skip to content

parser: support MySQL 8.0.19+ INSERT row alias syntax#67920

Open
paultyng wants to merge 2 commits intopingcap:masterfrom
paultyng:parser/insert-row-alias
Open

parser: support MySQL 8.0.19+ INSERT row alias syntax#67920
paultyng wants to merge 2 commits intopingcap:masterfrom
paultyng:parser/insert-row-alias

Conversation

@paultyng
Copy link
Copy Markdown

@paultyng paultyng commented Apr 20, 2026

What problem does this PR solve?

Issue Number: ref #51650, ref #29259

Problem Summary:

TiDB returns a syntax error on the MySQL 8.0.19+ INSERT ... VALUES (...) AS alias syntax. MySQL 8.0.20 deprecated VALUES() in favor of this syntax, so TiDB can't parse modern MySQL upserts.

What changed and how does it work?

Parser-only change — adds AS row_alias[(col_alias, ...)] to INSERT ... VALUES and INSERT ... SET.

  • Added RowAlias and ColumnAliases fields to InsertStmt AST node
  • Added InsertRowAliasOpt grammar rule inside VALUES/SET alternatives of InsertValues (not SELECT, matching MySQL spec)
  • Updated Restore() for round-trip fidelity, following the existing TableSource alias pattern

Planner/executor support for resolving alias references in ON DUPLICATE KEY UPDATE is not included.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

Support parsing MySQL 8.0.19+ `INSERT ... VALUES (...) AS alias(col1, col2)` and `INSERT ... SET ... AS alias(col1, col2)` row alias syntax. Execution support for resolving row aliases in `ON DUPLICATE KEY UPDATE` is not yet implemented.

Summary by CodeRabbit

  • New Features
    • Added support for MySQL 8.0.19+ row-alias syntax in INSERT statements: optional AS row_alias and AS row_alias(columns...), supported for both VALUES and SET forms and usable with ON DUPLICATE KEY UPDATE.
  • Bug Fixes
    • Explicitly disallow row-alias syntax for REPLACE statements.
  • Tests
    • Added coverage validating parsing/restoring of INSERT row-alias forms and rejecting them for REPLACE.

Add parsing support for the `AS row_alias[(col_alias, ...)]` clause
in INSERT ... VALUES and INSERT ... SET statements, as introduced in
MySQL 8.0.19 (WL pingcap#6312) and required since VALUES() was deprecated
in MySQL 8.0.20.

Examples:
  INSERT INTO t VALUES (1,2) AS new ON DUPLICATE KEY UPDATE b = new.b;
  INSERT INTO t VALUES (1,2) AS new(m,n) ON DUPLICATE KEY UPDATE b = m;
  INSERT INTO t SET a=1,b=2 AS new ON DUPLICATE KEY UPDATE b = new.a;

This is a parser-only change; planner/executor support for resolving
the alias references is not included.

Ref pingcap#51650, ref pingcap#29259
@ti-chi-bot ti-chi-bot bot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Apr 20, 2026
@pantheon-ai
Copy link
Copy Markdown

pantheon-ai bot commented Apr 20, 2026

@paultyng I've received your pull request and will start the review. I'll conduct a thorough review covering code quality, potential issues, and implementation details.

⏳ This process typically takes 10-30 minutes depending on the complexity of the changes.

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 20, 2026

Hi @paultyng. Thanks for your PR.

I'm waiting for a pingcap member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ti-chi-bot ti-chi-bot bot added contribution This PR is from a community contributor. needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Apr 20, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 20, 2026

Welcome @paultyng!

It looks like this is your first PR to pingcap/tidb 🎉.

I'm the bot to help you request reviewers, add labels and more, See available commands.

We want to make sure your contribution gets all the attention it needs!



Thank you, and welcome to pingcap/tidb. 😃

@ti-chi-bot ti-chi-bot bot added the first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. label Apr 20, 2026
@pingcap-cla-assistant
Copy link
Copy Markdown

pingcap-cla-assistant bot commented Apr 20, 2026

CLA assistant check
All committers have signed the CLA.

@tiprow
Copy link
Copy Markdown

tiprow bot commented Apr 20, 2026

Hi @paultyng. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cb29666f-8bef-4e5f-918b-4b8d47fb1d68

📥 Commits

Reviewing files that changed from the base of the PR and between e7af8a6 and 7c1f4e9.

📒 Files selected for processing (3)
  • pkg/parser/parser.go
  • pkg/parser/parser.y
  • pkg/parser/parser_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/parser/parser_test.go

📝 Walkthrough

Walkthrough

Adds MySQL 8.0.19+ row-alias support for INSERT by parsing and storing optional AS <row_alias> and AS <row_alias>(col1,col2,...) suffixes; AST InsertStmt gains RowAlias and ColumnAliases, and REPLACE now rejects row/column aliases. Tests updated accordingly.

Changes

Cohort / File(s) Summary
AST Structure
pkg/parser/ast/dml.go
Added exported fields RowAlias CIStr and ColumnAliases []CIStr to InsertStmt; Restore now conditionally emits AS <rowAlias> and optional (col,...) list before ON DUPLICATE KEY UPDATE.
Grammar / Parser
pkg/parser/parser.y
Added InsertRowAliasOpt production and insertRowAlias helper to parse optional AS row_alias / AS row_alias(column_aliases...) for INSERT (VALUES/SET) forms; populated ast.InsertStmt fields from parse actions; REPLACE INTO productions now validate and reject row/column aliases (emit ErrSyntax).
Tests
pkg/parser/parser_test.go
Extended TestDMLStmt with positive cases for INSERT ... AS <alias> and AS <alias>(cols...) (with and without ON DUPLICATE KEY UPDATE and for SET form), and negative cases ensuring REPLACE ... AS ... is rejected.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble new aliases into the tree,
AS new(a,b) hops where values be,
Parsers adjusted, tests all set,
A tiny patch — a tidy vignette. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding MySQL 8.0.19+ INSERT row alias syntax support to the parser, which is the primary focus of the changeset across AST, grammar, and test files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/parser/parser.y (1)

7908-7989: ⚠️ Potential issue | 🟠 Major

INSERT row aliases incorrectly accepted in REPLACE syntax due to InsertValues grammar reuse.

Line 8089 reuses InsertValues for REPLACE, which includes InsertRowAliasOpt rules. This allows syntactically invalid REPLACE statements like REPLACE INTO t VALUES (1) AS new and REPLACE INTO t SET a = 1 AS new to parse successfully. MySQL documents row aliases for INSERT values-list and SET forms (since 8.0.19), but not for REPLACE. The ReplaceIntoStmt action must reject any row aliases to comply with MySQL syntax.

Add a check in the ReplaceIntoStmt action to reject aliases:

ReplaceIntoStmt:
	"REPLACE" TableOptimizerHintsOpt PriorityOpt IntoOpt TableName PartitionNameListOpt InsertValues
	{
		x := $7.(*ast.InsertStmt)
+		if x.RowAlias.O != "" || len(x.ColumnAliases) > 0 {
+			yylex.AppendError(ErrSyntax)
+			return 1
+		}
		if $2 != nil {
			x.TableHints = $2.([]*ast.TableOptimizerHint)
		}

Add negative parser tests for both forms: REPLACE INTO ... VALUES (...) AS alias and REPLACE INTO ... SET ... AS alias.

🧹 Nitpick comments (1)
pkg/parser/parser_test.go (1)

920-929: Add a negative guard for unsupported INSERT ... SELECT ... AS row_alias forms.

Great positive coverage here. Please also add at least one negative case to lock the “VALUES/SET-only” contract from this PR.

✅ Suggested test additions
 		// row alias without ON DUPLICATE KEY UPDATE
 		{"INSERT INTO t VALUES (1,2) AS new;", true, "INSERT INTO `t` VALUES (1,2) AS `new`"},
 		{"INSERT INTO t VALUES (1,2) AS new(a,b);", true, "INSERT INTO `t` VALUES (1,2) AS `new`(`a`, `b`)"},
+		// row alias is not supported for INSERT ... SELECT
+		{"INSERT INTO t SELECT 1,2 AS new;", false, ""},
+		{"INSERT INTO t SELECT 1,2 AS new(a,b);", false, ""},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/parser/parser_test.go` around lines 920 - 929, Add a negative test case
alongside the existing row-alias entries in the SQL test table in parser_test.go
to assert that INSERT ... SELECT ... AS <row_alias> is rejected; specifically
add an entry mirroring the positive VALUES/SET cases but using an INSERT ...
SELECT ... AS form (e.g., an INSERT INTO t SELECT ... AS new) and mark it as
failing (ok=false) so the parser test ensures AS row_alias is only accepted for
VALUES/SET forms (update the test table near the existing "AS new" rows).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/parser/parser_test.go`:
- Around line 920-929: Add a negative test case alongside the existing row-alias
entries in the SQL test table in parser_test.go to assert that INSERT ... SELECT
... AS <row_alias> is rejected; specifically add an entry mirroring the positive
VALUES/SET cases but using an INSERT ... SELECT ... AS form (e.g., an INSERT
INTO t SELECT ... AS new) and mark it as failing (ok=false) so the parser test
ensures AS row_alias is only accepted for VALUES/SET forms (update the test
table near the existing "AS new" rows).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 003c0468-0502-4c47-88ed-b86fbb865229

📥 Commits

Reviewing files that changed from the base of the PR and between 7f3e45f and e7af8a6.

📒 Files selected for processing (4)
  • pkg/parser/ast/dml.go
  • pkg/parser/parser.go
  • pkg/parser/parser.y
  • pkg/parser/parser_test.go

REPLACE does not support the AS row_alias syntax in MySQL.
Since ReplaceIntoStmt reuses InsertValues, add a check to
reject any row alias parsed via that shared grammar rule.

Ref pingcap#51650
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 20, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign benjamin2037, yudongusa for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@paultyng
Copy link
Copy Markdown
Author

InsertRowAliasOpt is only added to the VALUES/SET alternatives of InsertValues, not the SELECT alternatives. INSERT INTO t SELECT 1,2 AS new parses fine because AS new is consumed as a column alias on 2 by the existing FieldAsNameOpt grammar — it never reaches row alias parsing.

@lance6716
Copy link
Copy Markdown
Contributor

/ok-to-test

@ti-chi-bot ti-chi-bot bot added ok-to-test Indicates a PR is ready to be tested. and removed needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. labels Apr 21, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.1559%. Comparing base (7f3e45f) to head (7c1f4e9).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #67920        +/-   ##
================================================
- Coverage   77.8055%   77.1559%   -0.6497%     
================================================
  Files          1983       1965        -18     
  Lines        549119     549122         +3     
================================================
- Hits         427245     423680      -3565     
- Misses       120954     125440      +4486     
+ Partials        920          2       -918     
Flag Coverage Δ
integration 40.8928% <ø> (+1.0956%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 61.5065% <ø> (ø)
parser ∅ <ø> (∅)
br 50.0681% <ø> (-13.0316%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 21, 2026

@paultyng: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
idc-jenkins-ci-tidb/mysql-test 7c1f4e9 link true /test mysql-test
idc-jenkins-ci-tidb/unit-test 7c1f4e9 link true /test unit-test

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

contribution This PR is from a community contributor. first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. ok-to-test Indicates a PR is ready to be tested. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants