Skip to content

feat(tidb): BATCH non-transactional DML grammar (Tier 4g)#157

Merged
vsai12 merged 2 commits into
mainfrom
feat/tidb-batch-stmt
May 28, 2026
Merged

feat(tidb): BATCH non-transactional DML grammar (Tier 4g)#157
vsai12 merged 2 commits into
mainfrom
feat/tidb-batch-stmt

Conversation

@vsai12
Copy link
Copy Markdown
Contributor

@vsai12 vsai12 commented May 28, 2026

Summary

Adds parsing for TiDB's non-transactional DML statement:

BATCH [ON <col>] LIMIT <n> [DRY RUN [QUERY]] {DELETE | UPDATE | INSERT | REPLACE}

mirroring pingcap's NonTransactionalDMLStmt production ("BATCH" OptionalShardColumn "LIMIT" NUM DryRunOptions ShardableStmt).

Changes

  • ASTBatchStmt node + BatchDryRunMode enum. Numeric values mirror pingcap (None=0, Query=1, SplitDML=2); locked by test.
  • LexerBATCH/DRY/RUN keyword tokens, classified TiDBKeyword (unreserved upstream) and added to keywordCategories as kwCatUnambiguous so they remain usable as identifiers/labels/roles/lvalues.
  • ParserparseBatchStmt + dispatch case; BATCH added as a top-level completion candidate. LIMIT parses a bare NUM (not an expression), so LIMIT (1+1), LIMIT ?, and LIMIT -100 are rejected. The ON shard column must be a (qualified) column name — wildcard forms (t.*, db.t.*) are rejected, matching TiDB.
  • Walker / outfuncsBatchStmt walks ShardColumn + DML; writeBatchStmt prints all fields.
  • REPLACE surfaces as *InsertStmt with IsReplace=true (omni's existing INSERT/REPLACE unification).
  • Drive-by: fixed a stale for MySQL package comment in tidb/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 unification
  • TestBatchDryRunEnumValues — locks None=0/Query=1/SplitDML=2
  • TestBatchKeywordsStillIdentifiers — 9 keyword-as-identifier regression cases (no regression from the new tokens)
  • TestBatchSerialize — outfuncs coverage for both DRY RUN variants + REPLACE
  • TestBatchTiDBOracle23/23 grammar lockstep against pingcap/tidb:v8.5.5 (skips under -short)

omni has no statement-level (DML) deparse — only expression + SELECT — so parse→NodeToString→inspect is the round-trip analog used here.

Notes

  • tidb/parser/{lexer,name}.go and tidb/ast/parsenodes.go are not gofmt-clean at HEAD (pre-existing). Added lines hand-match the existing alignment; these files were intentionally not gofmt -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

vsai12 and others added 2 commits May 27, 2026 22:57
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>
@vsai12 vsai12 requested a review from rebelice May 28, 2026 06:19
@vsai12 vsai12 merged commit 20ea338 into main May 28, 2026
2 checks passed
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.

1 participant