feat(tidb): BATCH non-transactional DML grammar (Tier 4g)#157
Merged
Conversation
Parse TiDB's BATCH [ON col] LIMIT n [DRY RUN [QUERY]] {DELETE|UPDATE|
INSERT|REPLACE} non-transactional DML statement, mirroring pingcap's
NonTransactionalDMLStmt production.
- BatchStmt AST node + BatchDryRunMode enum; numeric values mirror
pingcap (None=0, Query=1, SplitDML=2)
- BATCH/DRY/RUN keyword tokens classified TiDBKeyword (unreserved) so
they remain usable as identifiers (regression-tested)
- Parser dispatch + top-level completion candidate; walker + outfuncs
- LIMIT is a bare NUM, not an expression (rejects LIMIT (1+1)/?/-100)
- 20/20 grammar lockstep verified against pingcap/tidb:v8.5.5
Also fix a stale "for MySQL" package comment in tidb/completion.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
parseColumnRef accepts wildcard forms (t.* / db.t.*) that TiDB rejects in the BATCH ON shard-column position — upstream OptionalShardColumn is "ON ColumnName" with no star form. Reject col.Star after parsing and add the wildcard negatives to the shared parser + TiDB-oracle corpus (now 23/23 lockstep vs pingcap/tidb:v8.5.5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds parsing for TiDB's non-transactional DML statement:
mirroring pingcap's
NonTransactionalDMLStmtproduction ("BATCH" OptionalShardColumn "LIMIT" NUM DryRunOptions ShardableStmt).Changes
BatchStmtnode +BatchDryRunModeenum. Numeric values mirror pingcap (None=0,Query=1,SplitDML=2); locked by test.BATCH/DRY/RUNkeyword tokens, classifiedTiDBKeyword(unreserved upstream) and added tokeywordCategoriesaskwCatUnambiguousso they remain usable as identifiers/labels/roles/lvalues.parseBatchStmt+ dispatch case;BATCHadded as a top-level completion candidate.LIMITparses a bareNUM(not an expression), soLIMIT (1+1),LIMIT ?, andLIMIT -100are rejected. TheONshard column must be a (qualified) column name — wildcard forms (t.*,db.t.*) are rejected, matching TiDB.BatchStmtwalksShardColumn+DML;writeBatchStmtprints all fields.*InsertStmtwithIsReplace=true(omni's existing INSERT/REPLACE unification).for MySQLpackage comment intidb/completion.Testing
TestBatchParse— 9 positives + 14 sibling-arm negatives (per the grammar's decorator differential, incl. wildcard shard columns)TestBatchAST— locks dry-run mapping, shard-column shape, REPLACE unificationTestBatchDryRunEnumValues— locksNone=0/Query=1/SplitDML=2TestBatchKeywordsStillIdentifiers— 9 keyword-as-identifier regression cases (no regression from the new tokens)TestBatchSerialize— outfuncs coverage for both DRY RUN variants + REPLACETestBatchTiDBOracle— 23/23 grammar lockstep againstpingcap/tidb:v8.5.5(skips under-short)omni has no statement-level (DML) deparse — only expression + SELECT — so
parse→NodeToString→inspectis the round-trip analog used here.Notes
tidb/parser/{lexer,name}.goandtidb/ast/parsenodes.goare notgofmt-clean at HEAD (pre-existing). Added lines hand-match the existing alignment; these files were intentionally notgofmt -w'd to avoid ~900 lines of unrelated whitespace churn. Added lines are clean under Go 1.25 (CI) and 1.26.🤖 Generated with Claude Code