Skip to content

Commit b984abe

Browse files
committed
Support transaction modes
Refs #99
1 parent 1b3c1f2 commit b984abe

File tree

4 files changed

+122
-5
lines changed

4 files changed

+122
-5
lines changed

src/cst/Transaction.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { BaseNode, Keyword } from "./Base";
2-
import { Identifier } from "./Expr";
2+
import { Identifier, ListExpr } from "./Expr";
33

44
export type AllTransactionNodes =
55
| AllTransactionStatements
66
| RollbackToSavepoint
77
| TransactionChainClause
8-
| TransactionNoChainClause;
8+
| TransactionNoChainClause
9+
| TransactionMode;
910

1011
export type AllTransactionStatements =
1112
| StartTransactionStmt
@@ -19,6 +20,44 @@ export interface StartTransactionStmt extends BaseNode {
1920
startKw: Keyword<"START" | "BEGIN">;
2021
behaviorKw?: Keyword<"DEFERRED" | "IMMEDIATE" | "EXCLUSIVE">;
2122
transactionKw?: Keyword<"TRANSACTION" | "WORK">;
23+
modes?: ListExpr<TransactionMode>;
24+
}
25+
26+
type TransactionMode =
27+
| TransactionModeDeferrable
28+
| TransactionModeNotDeferrable
29+
| TransactionModeReadWrite
30+
| TransactionModeReadOnly
31+
| TransactionModeIsolationLevel;
32+
33+
export interface TransactionModeDeferrable extends BaseNode {
34+
type: "transaction_mode_deferrable";
35+
deferrableKw: Keyword<"DEFERRABLE">;
36+
}
37+
38+
export interface TransactionModeNotDeferrable extends BaseNode {
39+
type: "transaction_mode_not_deferrable";
40+
notDeferrableKw: [Keyword<"NOT">, Keyword<"DEFERRABLE">];
41+
}
42+
43+
export interface TransactionModeReadWrite extends BaseNode {
44+
type: "transaction_mode_read_write";
45+
readWriteKw: [Keyword<"READ">, Keyword<"WRITE">];
46+
}
47+
48+
export interface TransactionModeReadOnly extends BaseNode {
49+
type: "transaction_mode_read_only";
50+
readOnlyKw: [Keyword<"READ">, Keyword<"ONLY">];
51+
}
52+
53+
export interface TransactionModeIsolationLevel extends BaseNode {
54+
type: "transaction_mode_isolation_level";
55+
isolationLevelKw: [Keyword<"ISOLATION">, Keyword<"LEVEL">];
56+
levelKw:
57+
| Keyword<"SERIALIZABLE">
58+
| [Keyword<"REPEATABLE">, Keyword<"READ">]
59+
| [Keyword<"READ">, Keyword<"COMMITTED">]
60+
| [Keyword<"READ">, Keyword<"UNCOMMITTED">];
2261
}
2362

2463
export interface CommitTransactionStmt extends BaseNode {

src/parser.pegjs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4688,11 +4688,12 @@ start_transaction_stmt
46884688
transactionKw: read(tKw),
46894689
});
46904690
}
4691-
/ &postgres kw:BEGIN tKw:(__ (TRANSACTION / WORK))? {
4691+
/ &postgres kw:BEGIN tKw:(__ (TRANSACTION / WORK))? modes:(__ list$transaction_mode)? {
46924692
return loc({
46934693
type: "start_transaction_stmt",
46944694
startKw: kw,
46954695
transactionKw: read(tKw),
4696+
modes: read(modes),
46964697
});
46974698
}
46984699
/ &mysql kw:BEGIN tKw:(__ WORK)? {
@@ -4702,14 +4703,57 @@ start_transaction_stmt
47024703
transactionKw: read(tKw),
47034704
});
47044705
}
4705-
/ (&mysql / &postgres) kw:START tKw:(__ TRANSACTION) {
4706+
/ (&mysql / &postgres) kw:START tKw:(__ TRANSACTION) modes:(__ list$transaction_mode)? {
47064707
return loc({
47074708
type: "start_transaction_stmt",
47084709
startKw: kw,
47094710
transactionKw: read(tKw),
4711+
modes: read(modes),
47104712
});
47114713
}
47124714

4715+
transaction_mode
4716+
= transaction_mode_deferrable
4717+
/ transaction_mode_not_deferrable
4718+
/ transaction_mode_read_write
4719+
/ transaction_mode_read_only
4720+
/ transaction_mode_isolation_level
4721+
4722+
transaction_mode_deferrable
4723+
= kw:(DEFERRABLE) {
4724+
return loc({ type: "transaction_mode_deferrable", deferrableKw: kw });
4725+
}
4726+
4727+
transaction_mode_not_deferrable
4728+
= kw:(NOT __ DEFERRABLE) {
4729+
return loc({ type: "transaction_mode_not_deferrable", notDeferrableKw: read(kw) });
4730+
}
4731+
4732+
transaction_mode_read_write
4733+
= kw:(READ __ WRITE) {
4734+
return loc({ type: "transaction_mode_read_write", readWriteKw: read(kw) });
4735+
}
4736+
4737+
transaction_mode_read_only
4738+
= kw:(READ __ ONLY) {
4739+
return loc({ type: "transaction_mode_read_only", readOnlyKw: read(kw) });
4740+
}
4741+
4742+
transaction_mode_isolation_level
4743+
= kw:(ISOLATION __ LEVEL __) levelKw:isolation_level_kw {
4744+
return loc({
4745+
type: "transaction_mode_isolation_level",
4746+
isolationLevelKw: read(kw),
4747+
levelKw: read(levelKw),
4748+
});
4749+
}
4750+
4751+
isolation_level_kw
4752+
= SERIALIZABLE
4753+
/ REPEATABLE __ READ
4754+
/ READ __ COMMITTED
4755+
/ READ __ UNCOMMITTED
4756+
47134757
commit_transaction_stmt
47144758
= kw:commit_kw tKw:(__ transaction_kw)? chain:(__ transaction_chain_clause)? {
47154759
return loc({
@@ -7616,6 +7660,7 @@ list$string_literal = .
76167660
list$table_func_call = .
76177661
list$table_option_postgresql = .
76187662
list$tablesample_arg = .
7663+
list$transaction_mode = .
76197664
list$transform_type = .
76207665
list$trigger_transition = .
76217666
list$type_param = .
@@ -8629,6 +8674,7 @@ COLUMNS = kw:"COLUMNS"i !ident_part { return loc(createK
86298674
COMMENT = kw:"COMMENT"i !ident_part { return loc(createKeyword(kw)); }
86308675
COMMENTS = kw:"COMMENTS"i !ident_part { return loc(createKeyword(kw)); }
86318676
COMMIT = kw:"COMMIT"i !ident_part { return loc(createKeyword(kw)); }
8677+
COMMITTED = kw:"COMMITTED"i !ident_part { return loc(createKeyword(kw)); }
86328678
COMPACT = kw:"COMPACT"i !ident_part { return loc(createKeyword(kw)); }
86338679
COMPRESSED = kw:"COMPRESSED"i !ident_part { return loc(createKeyword(kw)); }
86348680
COMPRESSION = kw:"COMPRESSION"i !ident_part { return loc(createKeyword(kw)); }
@@ -8813,6 +8859,7 @@ INVOKER = kw:"INVOKER"i !ident_part { return loc(createK
88138859
IS = kw:"IS"i !ident_part { return loc(createKeyword(kw)); }
88148860
ISNULL = kw:"ISNULL" !ident_part { return loc(createKeyword(kw)); }
88158861
ISODOW = kw:"ISODOW"i !ident_part { return loc(createKeyword(kw)); }
8862+
ISOLATION = kw:"ISOLATION"i !ident_part { return loc(createKeyword(kw)); }
88168863
ISOWEEK = kw:"ISOWEEK"i !ident_part { return loc(createKeyword(kw)); }
88178864
ISOYEAR = kw:"ISOYEAR"i !ident_part { return loc(createKeyword(kw)); }
88188865
ITERATE = kw:"ITERATE"i !ident_part { return loc(createKeyword(kw)); }
@@ -9028,6 +9075,7 @@ SECURITY = kw:"SECURITY"i !ident_part { return loc(createK
90289075
SELECT = kw:"SELECT"i !ident_part { return loc(createKeyword(kw)); }
90299076
SEQUENCE = kw:"SEQUENCE"i !ident_part { return loc(createKeyword(kw)); }
90309077
SEQUENCES = kw:"SEQUENCES"i !ident_part { return loc(createKeyword(kw)); }
9078+
SERIALIZABLE = kw:"SERIALIZABLE"i !ident_part { return loc(createKeyword(kw)); }
90319079
SERVER = kw:"SERVER"i !ident_part { return loc(createKeyword(kw)); }
90329080
SESSION = kw:"SESSION"i !ident_part { return loc(createKeyword(kw)); }
90339081
SESSION_USER = kw:"SESSION_USER"i !ident_part { return loc(createKeyword(kw)); }
@@ -9107,6 +9155,7 @@ TUESDAY = kw:"TUESDAY"i !ident_part { return loc(createK
91079155
TYPE = kw:"TYPE"i !ident_part { return loc(createKeyword(kw)); }
91089156
UESCAPE = kw:"UESCAPE"i !ident_part { return loc(createKeyword(kw)); }
91099157
UNBOUNDED = kw:"UNBOUNDED"i !ident_part { return loc(createKeyword(kw)); }
9158+
UNCOMMITTED = kw:"UNCOMMITTED"i !ident_part { return loc(createKeyword(kw)); }
91109159
UNDEFINED = kw:"UNDEFINED"i !ident_part { return loc(createKeyword(kw)); }
91119160
UNION = kw:"UNION"i !ident_part { return loc(createKeyword(kw)); }
91129161
UNIQUE = kw:"UNIQUE"i !ident_part { return loc(createKeyword(kw)); }

src/showNode/transaction.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FullTransformMap } from "../cstTransformer";
44

55
export const transactionMap: FullTransformMap<string, AllTransactionNodes> = {
66
start_transaction_stmt: (node) =>
7-
show([node.startKw, node.behaviorKw, node.transactionKw]),
7+
show([node.startKw, node.behaviorKw, node.transactionKw, node.modes]),
88
commit_transaction_stmt: (node) =>
99
show([node.commitKw, node.transactionKw, node.chain]),
1010
rollback_transaction_stmt: (node) =>
@@ -16,4 +16,10 @@ export const transactionMap: FullTransformMap<string, AllTransactionNodes> = {
1616
show([node.releaseKw, node.savepointKw, node.savepoint]),
1717
transaction_chain_clause: (node) => show([node.andChainKw]),
1818
transaction_no_chain_clause: (node) => show([node.andNoChainKw]),
19+
transaction_mode_deferrable: (node) => show([node.deferrableKw]),
20+
transaction_mode_not_deferrable: (node) => show([node.notDeferrableKw]),
21+
transaction_mode_read_write: (node) => show([node.readWriteKw]),
22+
transaction_mode_read_only: (node) => show([node.readOnlyKw]),
23+
transaction_mode_isolation_level: (node) =>
24+
show([node.isolationLevelKw, node.levelKw]),
1925
};

test/transactions.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ describe("transactions", () => {
3232
testWc("BEGIN WORK");
3333
});
3434
});
35+
36+
dialect("postgresql", () => {
37+
it("supports [NOT] DEFERRABLE", () => {
38+
testWc("BEGIN NOT DEFERRABLE");
39+
testWc("BEGIN DEFERRABLE");
40+
});
41+
42+
it("supports READ {WRITE | ONLY}", () => {
43+
testWc("BEGIN READ WRITE");
44+
testWc("BEGIN READ ONLY");
45+
});
46+
47+
it("supports ISOLATION LEVEL", () => {
48+
testWc("BEGIN ISOLATION LEVEL SERIALIZABLE");
49+
testWc("BEGIN ISOLATION LEVEL REPEATABLE READ");
50+
testWc("BEGIN ISOLATION LEVEL READ COMMITTED");
51+
testWc("BEGIN ISOLATION LEVEL READ UNCOMMITTED");
52+
});
53+
54+
it("supports multiple transaction modes", () => {
55+
testWc("BEGIN READ ONLY, ISOLATION LEVEL SERIALIZABLE, DEFERRABLE");
56+
});
57+
});
3558
});
3659

3760
describe("committing transaction", () => {

0 commit comments

Comments
 (0)