Skip to content

Commit

Permalink
sql: add parser support for XA transactions
Browse files Browse the repository at this point in the history
Informs #22329.

This commit adds new syntax for `PREPARE TRANSACTION <gid>`,
`COMMIT PREPARED <gid>`, and `ROLLBACK PREPARED <gid>`, for
parity with Postgres support.

Handling of the syntax is currently unimplemented.

Release note: None
  • Loading branch information
nvanbenschoten committed Dec 12, 2024
1 parent 34373ea commit c66a374
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docs/generated/sql/bnf/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ FILES = [
"col_qualification",
"column_table_def",
"comment",
"commit_prepared_stmt",
"commit_transaction",
"copy_stmt",
"copy_to_stmt",
Expand Down Expand Up @@ -183,6 +184,7 @@ FILES = [
"pause_stmt",
"preparable_stmt",
"prepare_stmt",
"prepare_transaction_stmt",
"primary_key_column_level",
"primary_key_table_level",
"reassign_owned_by_stmt",
Expand All @@ -204,6 +206,7 @@ FILES = [
"resume_schedule",
"resume_stmt",
"revoke_stmt",
"rollback_prepared_stmt",
"rollback_transaction",
"routine_body_stmt",
"routine_return_stmt",
Expand Down
2 changes: 2 additions & 0 deletions docs/generated/sql/bnf/commit_prepared_stmt.bnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
commit_prepared_stmt ::=
'COMMIT' 'PREPARED' 'SCONST'
2 changes: 2 additions & 0 deletions docs/generated/sql/bnf/prepare_transaction_stmt.bnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prepare_transaction_stmt ::=
'PREPARE' 'TRANSACTION' 'SCONST'
2 changes: 2 additions & 0 deletions docs/generated/sql/bnf/rollback_prepared_stmt.bnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rollback_prepared_stmt ::=
'ROLLBACK' 'PREPARED' 'SCONST'
14 changes: 14 additions & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ transaction_stmt ::=
| commit_stmt
| rollback_stmt
| abort_stmt
| prepare_transaction_stmt
| commit_prepared_stmt
| rollback_prepared_stmt

close_cursor_stmt ::=
'CLOSE' 'ALL'
Expand Down Expand Up @@ -470,6 +473,15 @@ rollback_stmt ::=
abort_stmt ::=
'ABORT' opt_abort_mod

prepare_transaction_stmt ::=
'PREPARE' 'TRANSACTION' 'SCONST'

commit_prepared_stmt ::=
'COMMIT' 'PREPARED' 'SCONST'

rollback_prepared_stmt ::=
'ROLLBACK' 'PREPARED' 'SCONST'

cursor_name ::=
name

Expand Down Expand Up @@ -1337,6 +1349,7 @@ unreserved_keyword ::=
| 'POLYGONZM'
| 'PRECEDING'
| 'PREPARE'
| 'PREPARED'
| 'PRESERVE'
| 'PRIOR'
| 'PRIORITY'
Expand Down Expand Up @@ -4074,6 +4087,7 @@ bare_label_keywords ::=
| 'POSITION'
| 'PRECEDING'
| 'PREPARE'
| 'PREPARED'
| 'PRESERVE'
| 'PRIMARY'
| 'PRIOR'
Expand Down
3 changes: 3 additions & 0 deletions docs/generated/sql/bnf/transaction_stmt.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ transaction_stmt ::=
| commit_stmt
| rollback_stmt
| abort_stmt
| prepare_transaction_stmt
| commit_prepared_stmt
| rollback_prepared_stmt
3 changes: 3 additions & 0 deletions pkg/gen/bnf.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ BNF_SRCS = [
"//docs/generated/sql/bnf:col_qualification.bnf",
"//docs/generated/sql/bnf:column_table_def.bnf",
"//docs/generated/sql/bnf:comment.bnf",
"//docs/generated/sql/bnf:commit_prepared_stmt.bnf",
"//docs/generated/sql/bnf:commit_transaction.bnf",
"//docs/generated/sql/bnf:copy_stmt.bnf",
"//docs/generated/sql/bnf:copy_to_stmt.bnf",
Expand Down Expand Up @@ -183,6 +184,7 @@ BNF_SRCS = [
"//docs/generated/sql/bnf:pause_stmt.bnf",
"//docs/generated/sql/bnf:preparable_stmt.bnf",
"//docs/generated/sql/bnf:prepare_stmt.bnf",
"//docs/generated/sql/bnf:prepare_transaction_stmt.bnf",
"//docs/generated/sql/bnf:primary_key_column_level.bnf",
"//docs/generated/sql/bnf:primary_key_table_level.bnf",
"//docs/generated/sql/bnf:reassign_owned_by_stmt.bnf",
Expand All @@ -204,6 +206,7 @@ BNF_SRCS = [
"//docs/generated/sql/bnf:resume_schedule.bnf",
"//docs/generated/sql/bnf:resume_stmt.bnf",
"//docs/generated/sql/bnf:revoke_stmt.bnf",
"//docs/generated/sql/bnf:rollback_prepared_stmt.bnf",
"//docs/generated/sql/bnf:rollback_transaction.bnf",
"//docs/generated/sql/bnf:routine_body_stmt.bnf",
"//docs/generated/sql/bnf:routine_return_stmt.bnf",
Expand Down
3 changes: 3 additions & 0 deletions pkg/gen/diagrams.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ DIAGRAMS_SRCS = [
"//docs/generated/sql/bnf:col_qualification.html",
"//docs/generated/sql/bnf:column_table_def.html",
"//docs/generated/sql/bnf:comment.html",
"//docs/generated/sql/bnf:commit_prepared.html",
"//docs/generated/sql/bnf:commit_transaction.html",
"//docs/generated/sql/bnf:copy.html",
"//docs/generated/sql/bnf:copy_to.html",
Expand Down Expand Up @@ -183,6 +184,7 @@ DIAGRAMS_SRCS = [
"//docs/generated/sql/bnf:pause_schedule.html",
"//docs/generated/sql/bnf:preparable.html",
"//docs/generated/sql/bnf:prepare.html",
"//docs/generated/sql/bnf:prepare_transaction.html",
"//docs/generated/sql/bnf:primary_key_column_level.html",
"//docs/generated/sql/bnf:primary_key_table_level.html",
"//docs/generated/sql/bnf:reassign_owned_by.html",
Expand All @@ -204,6 +206,7 @@ DIAGRAMS_SRCS = [
"//docs/generated/sql/bnf:resume_job.html",
"//docs/generated/sql/bnf:resume_schedule.html",
"//docs/generated/sql/bnf:revoke.html",
"//docs/generated/sql/bnf:rollback_prepared.html",
"//docs/generated/sql/bnf:rollback_transaction.html",
"//docs/generated/sql/bnf:routine_body.html",
"//docs/generated/sql/bnf:routine_return.html",
Expand Down
3 changes: 3 additions & 0 deletions pkg/gen/docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ DOCS_SRCS = [
"//docs/generated/sql/bnf:col_qualification.bnf",
"//docs/generated/sql/bnf:column_table_def.bnf",
"//docs/generated/sql/bnf:comment.bnf",
"//docs/generated/sql/bnf:commit_prepared_stmt.bnf",
"//docs/generated/sql/bnf:commit_transaction.bnf",
"//docs/generated/sql/bnf:copy_stmt.bnf",
"//docs/generated/sql/bnf:copy_to_stmt.bnf",
Expand Down Expand Up @@ -196,6 +197,7 @@ DOCS_SRCS = [
"//docs/generated/sql/bnf:pause_stmt.bnf",
"//docs/generated/sql/bnf:preparable_stmt.bnf",
"//docs/generated/sql/bnf:prepare_stmt.bnf",
"//docs/generated/sql/bnf:prepare_transaction_stmt.bnf",
"//docs/generated/sql/bnf:primary_key_column_level.bnf",
"//docs/generated/sql/bnf:primary_key_table_level.bnf",
"//docs/generated/sql/bnf:reassign_owned_by_stmt.bnf",
Expand All @@ -217,6 +219,7 @@ DOCS_SRCS = [
"//docs/generated/sql/bnf:resume_schedule.bnf",
"//docs/generated/sql/bnf:resume_stmt.bnf",
"//docs/generated/sql/bnf:revoke_stmt.bnf",
"//docs/generated/sql/bnf:rollback_prepared_stmt.bnf",
"//docs/generated/sql/bnf:rollback_transaction.bnf",
"//docs/generated/sql/bnf:routine_body_stmt.bnf",
"//docs/generated/sql/bnf:routine_return_stmt.bnf",
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/parser/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ func TestContextualHelp(t *testing.T) {
{`CANCEL SESSIONS IF EXISTS ??`, `CANCEL SESSIONS`},
{`CANCEL ALL ??`, `CANCEL ALL JOBS`},

{`COMMIT PREPARED 'foo' ??`, `COMMIT PREPARED`},

{`CREATE UNIQUE ??`, `CREATE`},
{`CREATE UNIQUE INDEX ??`, `CREATE INDEX`},
{`CREATE INDEX IF NOT ??`, `CREATE INDEX`},
Expand Down Expand Up @@ -274,6 +276,8 @@ func TestContextualHelp(t *testing.T) {
{`PREPARE foo AS DELETE FROM xx ??`, `DELETE`},
{`PREPARE foo AS UPDATE xx SET x = y ??`, `UPDATE`},

{`PREPARE TRANSACTION 'foo' ??`, `PREPARE TRANSACTION`},

{`EXECUTE foo ??`, `EXECUTE`},
{`EXECUTE foo (??`, `EXECUTE`},

Expand Down Expand Up @@ -340,6 +344,8 @@ func TestContextualHelp(t *testing.T) {
{`REVOKE ALL ON foo FROM ??`, `REVOKE`},
{`REVOKE ALL ON foo FROM bar ??`, `REVOKE`},

{`ROLLBACK PREPARED 'foo' ??`, `ROLLBACK PREPARED`},

{`SELECT * FROM ??`, `<SOURCE>`},
{`SELECT * FROM (??`, `<SOURCE>`}, // not <selectclause>! joins are allowed.
{`SELECT * FROM [SHOW ??`, `SHOW`},
Expand Down
50 changes: 44 additions & 6 deletions pkg/sql/parser/sql.y
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ func (u *sqlSymUnion) triggerForEach() tree.TriggerForEach {

%token <str> PARALLEL PARENT PARTIAL PARTITION PARTITIONS PASSWORD PAUSE PAUSED PER PHYSICAL PLACEMENT PLACING
%token <str> PLAN PLANS POINT POINTM POINTZ POINTZM POLYGON POLYGONM POLYGONZ POLYGONZM
%token <str> POSITION PRECEDING PRECISION PREPARE PRESERVE PRIMARY PRIOR PRIORITY PRIVILEGES
%token <str> POSITION PRECEDING PRECISION PREPARE PREPARED PRESERVE PRIMARY PRIOR PRIORITY PRIVILEGES
%token <str> PROCEDURAL PROCEDURE PROCEDURES PUBLIC PUBLICATION

%token <str> QUERIES QUERY QUOTE
Expand Down Expand Up @@ -1293,6 +1293,9 @@ func (u *sqlSymUnion) triggerForEach() tree.TriggerForEach {
%type <tree.Statement> abort_stmt
%type <tree.Statement> rollback_stmt
%type <tree.Statement> savepoint_stmt
%type <tree.Statement> prepare_transaction_stmt
%type <tree.Statement> commit_prepared_stmt
%type <tree.Statement> rollback_prepared_stmt

%type <tree.Statement> preparable_set_stmt nonpreparable_set_stmt
%type <tree.Statement> set_local_stmt
Expand Down Expand Up @@ -12501,12 +12504,15 @@ savepoint_stmt:
}
| SAVEPOINT error // SHOW HELP: SAVEPOINT

// BEGIN / START / COMMIT / END / ROLLBACK / ...
// BEGIN / START / COMMIT / END / ROLLBACK / PREPARE TRANSACTION / COMMIT PREPARED / ROLLBACK PREPARED / ...
transaction_stmt:
begin_stmt // EXTEND WITH HELP: BEGIN
| commit_stmt // EXTEND WITH HELP: COMMIT
| rollback_stmt // EXTEND WITH HELP: ROLLBACK
| abort_stmt /* SKIP DOC */
begin_stmt // EXTEND WITH HELP: BEGIN
| commit_stmt // EXTEND WITH HELP: COMMIT
| rollback_stmt // EXTEND WITH HELP: ROLLBACK
| abort_stmt /* SKIP DOC */
| prepare_transaction_stmt // EXTEND WITH HELP: PREPARE TRANSACTION
| commit_prepared_stmt // EXTEND WITH HELP: COMMIT PREPARED
| rollback_prepared_stmt // EXTEND WITH HELP: ROLLBACK PREPARED

// %Help: BEGIN - start a transaction
// %Category: Txn
Expand Down Expand Up @@ -12692,6 +12698,36 @@ transaction_deferrable_mode:
$$.val = tree.NotDeferrable
}

// %Help: PREPARE TRANSACTION - prepare the current transaction for two-phase commit
// %Category: Txn
// %Text: PREPARE TRANSACTION <transaction-id>
// %SeeAlso: COMMIT PREPARED, ROLLBACK PREPARED
prepare_transaction_stmt:
PREPARE TRANSACTION SCONST
{
$$.val = &tree.PrepareTransaction{Transaction: tree.NewStrVal($3)}
}

// %Help: COMMIT PREPARED - commit the named transaction as part of two-phase commit
// %Category: Txn
// %Text: COMMIT PREPARED <transaction-id>
// %SeeAlso: PREPARE TRANSACTION, ROLLBACK PREPARED
commit_prepared_stmt:
COMMIT PREPARED SCONST
{
$$.val = &tree.CommitPrepared{Transaction: tree.NewStrVal($3)}
}

// %Help: ROLLBACK PREPARED - rollback the named transaction as part of two-phase commit
// %Category: Txn
// %Text: ROLLBACK PREPARED <transaction-id>
// %SeeAlso: PREPARE TRANSACTION, COMMIT PREPARED
rollback_prepared_stmt:
ROLLBACK PREPARED SCONST
{
$$.val = &tree.RollbackPrepared{Transaction: tree.NewStrVal($3)}
}

// %Help: CREATE DATABASE - create a new database
// %Category: DDL
// %Text: CREATE DATABASE [IF NOT EXISTS] <name>
Expand Down Expand Up @@ -17763,6 +17799,7 @@ unreserved_keyword:
| POLYGONZM
| PRECEDING
| PREPARE
| PREPARED
| PRESERVE
| PRIOR
| PRIORITY
Expand Down Expand Up @@ -18333,6 +18370,7 @@ bare_label_keywords:
| POSITION
| PRECEDING
| PREPARE
| PREPARED
| PRESERVE
| PRIMARY
| PRIOR
Expand Down
23 changes: 23 additions & 0 deletions pkg/sql/parser/testdata/two_phase_commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
parse
PREPARE TRANSACTION 'id'
----
PREPARE TRANSACTION 'id'
PREPARE TRANSACTION ('id') -- fully parenthesized
PREPARE TRANSACTION '_' -- literals removed
PREPARE TRANSACTION 'id' -- identifiers removed

parse
COMMIT PREPARED 'id'
----
COMMIT PREPARED 'id'
COMMIT PREPARED ('id') -- fully parenthesized
COMMIT PREPARED '_' -- literals removed
COMMIT PREPARED 'id' -- identifiers removed

parse
ROLLBACK PREPARED 'id'
----
ROLLBACK PREPARED 'id'
ROLLBACK PREPARED ('id') -- fully parenthesized
ROLLBACK PREPARED '_' -- literals removed
ROLLBACK PREPARED 'id' -- identifiers removed
30 changes: 30 additions & 0 deletions pkg/sql/sem/tree/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,15 @@ func (*CommentOnType) StatementType() StatementType { return TypeDDL }
// StatementTag returns a short string identifying the type of statement.
func (*CommentOnType) StatementTag() string { return CommentOnTypeTag }

// StatementReturnType implements the Statement interface.
func (*CommitPrepared) StatementReturnType() StatementReturnType { return Ack }

// StatementType implements the Statement interface.
func (*CommitPrepared) StatementType() StatementType { return TypeTCL }

// StatementTag returns a short string identifying the type of statement.
func (*CommitPrepared) StatementTag() string { return "COMMIT PREPARED" }

// StatementReturnType implements the Statement interface.
func (*CommitTransaction) StatementReturnType() StatementReturnType { return Ack }

Expand Down Expand Up @@ -1290,6 +1299,15 @@ func (*Prepare) StatementType() StatementType { return TypeTCL }
// StatementTag returns a short string identifying the type of statement.
func (*Prepare) StatementTag() string { return "PREPARE" }

// StatementReturnType implements the Statement interface.
func (*PrepareTransaction) StatementReturnType() StatementReturnType { return Ack }

// StatementType implements the Statement interface.
func (*PrepareTransaction) StatementType() StatementType { return TypeTCL }

// StatementTag returns a short string identifying the type of statement.
func (*PrepareTransaction) StatementTag() string { return "PREPARE TRANSACTION" }

// StatementReturnType implements the Statement interface.
func (*ReassignOwnedBy) StatementReturnType() StatementReturnType { return DDL }

Expand Down Expand Up @@ -1438,6 +1456,15 @@ func (*RevokeRole) StatementType() StatementType { return TypeDCL }
// StatementTag returns a short string identifying the type of statement.
func (*RevokeRole) StatementTag() string { return "REVOKE" }

// StatementReturnType implements the Statement interface.
func (*RollbackPrepared) StatementReturnType() StatementReturnType { return Ack }

// StatementType implements the Statement interface.
func (*RollbackPrepared) StatementType() StatementType { return TypeTCL }

// StatementTag returns a short string identifying the type of statement.
func (*RollbackPrepared) StatementTag() string { return "ROLLBACK PREPARED" }

// StatementReturnType implements the Statement interface.
func (*RollbackToSavepoint) StatementReturnType() StatementReturnType { return Ack }

Expand Down Expand Up @@ -2399,6 +2426,7 @@ func (n *CommentOnSchema) String() string { return AsString(
func (n *CommentOnIndex) String() string { return AsString(n) }
func (n *CommentOnTable) String() string { return AsString(n) }
func (n *CommentOnType) String() string { return AsString(n) }
func (n *CommitPrepared) String() string { return AsString(n) }
func (n *CommitTransaction) String() string { return AsString(n) }
func (n *CopyFrom) String() string { return AsString(n) }
func (n *CopyTo) String() string { return AsString(n) }
Expand Down Expand Up @@ -2447,6 +2475,7 @@ func (n *Import) String() string { return AsString(
func (n *LiteralValuesClause) String() string { return AsString(n) }
func (n *ParenSelect) String() string { return AsString(n) }
func (n *Prepare) String() string { return AsString(n) }
func (n *PrepareTransaction) String() string { return AsString(n) }
func (n *ReassignOwnedBy) String() string { return AsString(n) }
func (n *ReleaseSavepoint) String() string { return AsString(n) }
func (n *Relocate) String() string { return AsString(n) }
Expand All @@ -2461,6 +2490,7 @@ func (n *Restore) String() string { return AsString(
func (n *RoutineReturn) String() string { return AsString(n) }
func (n *Revoke) String() string { return AsString(n) }
func (n *RevokeRole) String() string { return AsString(n) }
func (n *RollbackPrepared) String() string { return AsString(n) }
func (n *RollbackToSavepoint) String() string { return AsString(n) }
func (n *RollbackTransaction) String() string { return AsString(n) }
func (n *Savepoint) String() string { return AsString(n) }
Expand Down
Loading

0 comments on commit c66a374

Please sign in to comment.