Repository navigation
feat: parse PostgreSQL two-phase commit and MySQL XA statements - #2904
Merged
manticore-projects merged 1 commit intoNov 9, 2026
Merged
manticore-projects merged 1 commit into
manticore-projects merged 1 commit into
Conversation
PostgreSQL PREPARE TRANSACTION, COMMIT PREPARED and ROLLBACK PREPARED and the MySQL XA statements failed to parse. Add TransactionId, one identifier model for MySQL's xid (gtrid [, bqual [, formatID]]) and the single string of PostgreSQL and of Oracle's ROLLBACK FORCE. Commit and RollbackStatement name a prepared transaction through TransactionCompletionStatement, with PREPARED or FORCE as the keyword; the legacy FORCE accessors derive from it. PREPARE TRANSACTION is a new PrepareTransactionStatement, dispatched before PREPARE name AS only when a string literal follows. The XA statements are one XaStatement with an Action and an Option. The PostgreSQL forms are read with that dialect or none and take a string constant; XA is read with the MySQL and MariaDB dialects or none and follows MySQL's xid grammar. XA stays usable as a name. Wire the statements into the deparser, visitors, table finder, feature analysis and validation, with new twoPhaseCommit and xa features. Signed-off-by: minleejae <mmj9808@gmail.com>
Contributor
|
Thank you! |
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.
Purpose
PostgreSQL's two-phase commit statements and MySQL's XA statements failed to parse:
PREPARE TRANSACTION 'foobar'failed at the string literal becausePREPAREalways readPREPARE name AS statement;COMMIT PREPAREDandROLLBACK PREPAREDfailed atPREPARED;and
XAwas not a statement start.Current design (As-is)
CommitandRollbackStatementshareTransactionCompletionStatement(feat: parse SET TRANSACTION, SET CONSTRAINTS, COMMIT RELEASE and PostgreSQL END and ABORT #2889) for[WORK | TRANSACTION],AND [NO] CHAINand[NO] RELEASE; neither can name a preparedtransaction.
ROLLBACK [WORK] FORCE 'id'is the only statement that names one. It is kept as theraw token text in
RollbackStatement.forceDistributedTransactionIdentifier, aString.PREPAREalways starts aPrepareStatement.Target design (To-be)
TransactionIdholds a global transaction identifierplus MySQL's optional branch qualifier and format ID (
gtrid [, bqual [, formatID]]). Theidentifier parts are the literals as written (
StringValue, or in MySQL alsoHexValueandbit values). PostgreSQL's identifier, MySQL's xid and Oracle's
FORCEidentifier all use it.TransactionCompletionStatementgainsgetPreparedTransactionKeyword()(PREPAREDorFORCE) andgetPreparedTransactionId().COMMIT PREPARED 'id'andROLLBACK PREPARED 'id'produce the existingCommitandRollbackStatement, so consumers keep one model per completion. Oracle'sROLLBACK FORCE 'id'moves to the same pair.
getForceDistributedTransactionIdentifier()and its setter remain,derived from that pair, and return and render the identifier exactly as before.
PrepareTransactionStatementis dispatched beforePREPARE name AS statement, only when a string literal followsTRANSACTION. SoPREPARE transaction AS SELECT 1still prepares a statement namedtransaction.XaStatementhas anAction(START,BEGIN,END,PREPARE,COMMIT,ROLLBACK,RECOVER), the xid as aTransactionId(null forRECOVER), and an optionalOption(JOIN,RESUME,SUSPEND,SUSPEND FOR MIGRATE,ONE PHASE,CONVERT XID).The model rejects an option that does not belong to the action.
must be a PostgreSQL string constant (
'…',E'…',U&'…', dollar-quoted), notN'…',B'…'orX'…'. The other spellings ofPREPARED(COMMIT WORK PREPARED,END/ABORT,AND CHAIN) are rejected.XAis not atoken, so it stays usable as a name.
xidrule, gtrid and bqual are string, hexadecimal (X'..'with wholebytes,
0x..) or bit-value literals.N'…',_charset'…', numbers and adjacent strings arerejected. formatID is an unsigned integer up to
LONG_MAX(MariaDB:INT32_MAX), the limitsof each server's grammar.
CONVERT XID.StatementDeParser(through the sharedappendTo),TablesNamesFinder(no tables), and feature analysis (XA RECOVERreturns a result set; therest is transaction control) all handle the new statements. Validation gets two new features:
twoPhaseCommitin the PostgreSQL capabilities andxain the MySQL and MariaDB capabilities.References: PostgreSQL PREPARE TRANSACTION,
COMMIT PREPARED,
ROLLBACK PREPARED,
MySQL 8.4 XA statements.
Not included:
XA RECOVER FORMAT = 'SQL'.to an integer.
0b…bit values.Validation
New
TwoPhaseTransactionTestwith 126 test cases. They cover parsing with and without eachdialect,
toString,StatementDeParser, reparse, AST fields, node spans, rejected forms,other dialects keeping their readings (
PREPARE transaction AS …,XAas a name), statementboundaries with and without semicolons (including opaque-statement mode), visitors,
TablesNamesFinder, feature analysis, validation and the model API.Updated tests:
ASTNodeCoverageTestwalks seven of the new forms.StatementValidatorTestreportstwoPhaseCommitandxa.TransactionStatementTestno longer listsCOMMIT PREPARED 'id'andROLLBACK PREPARED 'id'as rejected PostgreSQL syntax.These tests fail on
master, where none of the forms parse../gradlew spotlessApply check jar: 13054 tests, 25 skipped, 0 failures. Grammar ambiguitycheck, Checkstyle, PMD, SpotBugs and JaCoCo pass.
Compared with
master(a30a67920) on the non-DDL survey corpora, 12 cases are fixed:XA START,XA ENDandXA COMMIT … ONE PHASEin the MySQL dialect and without one, andPREPARE TRANSACTION,COMMIT PREPAREDandROLLBACK PREPAREDin the PostgreSQL dialect and withoutone. Nothing regressed or changed there, and the DDL/DCL survey corpora have 0 regressions.
PostgreSQL 18.6 accepts all 24 statements the tests accept for the PostgreSQL dialect, 14 of which
masterrejects. Some fail only when run, for exampleprepared transaction with identifier "x" does not existorSAVEPOINT can only be used in transaction blocks. It reports a syntax error for all 31 statements the tests reject, includingCOMMIT PREPARED 'x' AND CHAIN,END PREPARED 'x'and the XA forms.MySQL 8.4.11 accepts all 33 statements the tests accept for the MySQL dialect, 27 of which
masterrejects. Some fail only when run with an XA state error (XAER_NOTA,XAER_INVAL,XAER_RMFAIL). It reports a syntax error (1064) for all 51 statements the tests reject, includingXA START 'a', 'b', -1,XA START 'a', 'b', 9223372036854775808,XA START N'x',XA END 'x' FOR MIGRATEand the PostgreSQL forms.AI assistance: prepared with Claude Code.