Skip to content

Commit

Permalink
Support transaction modes
Browse files Browse the repository at this point in the history
Refs #99
  • Loading branch information
nene committed Dec 2, 2024
1 parent 1b3c1f2 commit b984abe
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 5 deletions.
43 changes: 41 additions & 2 deletions src/cst/Transaction.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { BaseNode, Keyword } from "./Base";
import { Identifier } from "./Expr";
import { Identifier, ListExpr } from "./Expr";

export type AllTransactionNodes =
| AllTransactionStatements
| RollbackToSavepoint
| TransactionChainClause
| TransactionNoChainClause;
| TransactionNoChainClause
| TransactionMode;

export type AllTransactionStatements =
| StartTransactionStmt
Expand All @@ -19,6 +20,44 @@ export interface StartTransactionStmt extends BaseNode {
startKw: Keyword<"START" | "BEGIN">;
behaviorKw?: Keyword<"DEFERRED" | "IMMEDIATE" | "EXCLUSIVE">;
transactionKw?: Keyword<"TRANSACTION" | "WORK">;
modes?: ListExpr<TransactionMode>;
}

type TransactionMode =
| TransactionModeDeferrable
| TransactionModeNotDeferrable
| TransactionModeReadWrite
| TransactionModeReadOnly
| TransactionModeIsolationLevel;

export interface TransactionModeDeferrable extends BaseNode {
type: "transaction_mode_deferrable";
deferrableKw: Keyword<"DEFERRABLE">;
}

export interface TransactionModeNotDeferrable extends BaseNode {
type: "transaction_mode_not_deferrable";
notDeferrableKw: [Keyword<"NOT">, Keyword<"DEFERRABLE">];
}

export interface TransactionModeReadWrite extends BaseNode {
type: "transaction_mode_read_write";
readWriteKw: [Keyword<"READ">, Keyword<"WRITE">];
}

export interface TransactionModeReadOnly extends BaseNode {
type: "transaction_mode_read_only";
readOnlyKw: [Keyword<"READ">, Keyword<"ONLY">];
}

export interface TransactionModeIsolationLevel extends BaseNode {
type: "transaction_mode_isolation_level";
isolationLevelKw: [Keyword<"ISOLATION">, Keyword<"LEVEL">];
levelKw:
| Keyword<"SERIALIZABLE">
| [Keyword<"REPEATABLE">, Keyword<"READ">]
| [Keyword<"READ">, Keyword<"COMMITTED">]
| [Keyword<"READ">, Keyword<"UNCOMMITTED">];
}

export interface CommitTransactionStmt extends BaseNode {
Expand Down
53 changes: 51 additions & 2 deletions src/parser.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -4688,11 +4688,12 @@ start_transaction_stmt
transactionKw: read(tKw),
});
}
/ &postgres kw:BEGIN tKw:(__ (TRANSACTION / WORK))? {
/ &postgres kw:BEGIN tKw:(__ (TRANSACTION / WORK))? modes:(__ list$transaction_mode)? {
return loc({
type: "start_transaction_stmt",
startKw: kw,
transactionKw: read(tKw),
modes: read(modes),
});
}
/ &mysql kw:BEGIN tKw:(__ WORK)? {
Expand All @@ -4702,14 +4703,57 @@ start_transaction_stmt
transactionKw: read(tKw),
});
}
/ (&mysql / &postgres) kw:START tKw:(__ TRANSACTION) {
/ (&mysql / &postgres) kw:START tKw:(__ TRANSACTION) modes:(__ list$transaction_mode)? {
return loc({
type: "start_transaction_stmt",
startKw: kw,
transactionKw: read(tKw),
modes: read(modes),
});
}

transaction_mode
= transaction_mode_deferrable
/ transaction_mode_not_deferrable
/ transaction_mode_read_write
/ transaction_mode_read_only
/ transaction_mode_isolation_level

transaction_mode_deferrable
= kw:(DEFERRABLE) {
return loc({ type: "transaction_mode_deferrable", deferrableKw: kw });
}

transaction_mode_not_deferrable
= kw:(NOT __ DEFERRABLE) {
return loc({ type: "transaction_mode_not_deferrable", notDeferrableKw: read(kw) });
}

transaction_mode_read_write
= kw:(READ __ WRITE) {
return loc({ type: "transaction_mode_read_write", readWriteKw: read(kw) });
}

transaction_mode_read_only
= kw:(READ __ ONLY) {
return loc({ type: "transaction_mode_read_only", readOnlyKw: read(kw) });
}

transaction_mode_isolation_level
= kw:(ISOLATION __ LEVEL __) levelKw:isolation_level_kw {
return loc({
type: "transaction_mode_isolation_level",
isolationLevelKw: read(kw),
levelKw: read(levelKw),
});
}

isolation_level_kw
= SERIALIZABLE
/ REPEATABLE __ READ
/ READ __ COMMITTED
/ READ __ UNCOMMITTED

commit_transaction_stmt
= kw:commit_kw tKw:(__ transaction_kw)? chain:(__ transaction_chain_clause)? {
return loc({
Expand Down Expand Up @@ -7616,6 +7660,7 @@ list$string_literal = .
list$table_func_call = .
list$table_option_postgresql = .
list$tablesample_arg = .
list$transaction_mode = .
list$transform_type = .
list$trigger_transition = .
list$type_param = .
Expand Down Expand Up @@ -8629,6 +8674,7 @@ COLUMNS = kw:"COLUMNS"i !ident_part { return loc(createK
COMMENT = kw:"COMMENT"i !ident_part { return loc(createKeyword(kw)); }
COMMENTS = kw:"COMMENTS"i !ident_part { return loc(createKeyword(kw)); }
COMMIT = kw:"COMMIT"i !ident_part { return loc(createKeyword(kw)); }
COMMITTED = kw:"COMMITTED"i !ident_part { return loc(createKeyword(kw)); }
COMPACT = kw:"COMPACT"i !ident_part { return loc(createKeyword(kw)); }
COMPRESSED = kw:"COMPRESSED"i !ident_part { return loc(createKeyword(kw)); }
COMPRESSION = kw:"COMPRESSION"i !ident_part { return loc(createKeyword(kw)); }
Expand Down Expand Up @@ -8813,6 +8859,7 @@ INVOKER = kw:"INVOKER"i !ident_part { return loc(createK
IS = kw:"IS"i !ident_part { return loc(createKeyword(kw)); }
ISNULL = kw:"ISNULL" !ident_part { return loc(createKeyword(kw)); }
ISODOW = kw:"ISODOW"i !ident_part { return loc(createKeyword(kw)); }
ISOLATION = kw:"ISOLATION"i !ident_part { return loc(createKeyword(kw)); }
ISOWEEK = kw:"ISOWEEK"i !ident_part { return loc(createKeyword(kw)); }
ISOYEAR = kw:"ISOYEAR"i !ident_part { return loc(createKeyword(kw)); }
ITERATE = kw:"ITERATE"i !ident_part { return loc(createKeyword(kw)); }
Expand Down Expand Up @@ -9028,6 +9075,7 @@ SECURITY = kw:"SECURITY"i !ident_part { return loc(createK
SELECT = kw:"SELECT"i !ident_part { return loc(createKeyword(kw)); }
SEQUENCE = kw:"SEQUENCE"i !ident_part { return loc(createKeyword(kw)); }
SEQUENCES = kw:"SEQUENCES"i !ident_part { return loc(createKeyword(kw)); }
SERIALIZABLE = kw:"SERIALIZABLE"i !ident_part { return loc(createKeyword(kw)); }
SERVER = kw:"SERVER"i !ident_part { return loc(createKeyword(kw)); }
SESSION = kw:"SESSION"i !ident_part { return loc(createKeyword(kw)); }
SESSION_USER = kw:"SESSION_USER"i !ident_part { return loc(createKeyword(kw)); }
Expand Down Expand Up @@ -9107,6 +9155,7 @@ TUESDAY = kw:"TUESDAY"i !ident_part { return loc(createK
TYPE = kw:"TYPE"i !ident_part { return loc(createKeyword(kw)); }
UESCAPE = kw:"UESCAPE"i !ident_part { return loc(createKeyword(kw)); }
UNBOUNDED = kw:"UNBOUNDED"i !ident_part { return loc(createKeyword(kw)); }
UNCOMMITTED = kw:"UNCOMMITTED"i !ident_part { return loc(createKeyword(kw)); }
UNDEFINED = kw:"UNDEFINED"i !ident_part { return loc(createKeyword(kw)); }
UNION = kw:"UNION"i !ident_part { return loc(createKeyword(kw)); }
UNIQUE = kw:"UNIQUE"i !ident_part { return loc(createKeyword(kw)); }
Expand Down
8 changes: 7 additions & 1 deletion src/showNode/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FullTransformMap } from "../cstTransformer";

export const transactionMap: FullTransformMap<string, AllTransactionNodes> = {
start_transaction_stmt: (node) =>
show([node.startKw, node.behaviorKw, node.transactionKw]),
show([node.startKw, node.behaviorKw, node.transactionKw, node.modes]),
commit_transaction_stmt: (node) =>
show([node.commitKw, node.transactionKw, node.chain]),
rollback_transaction_stmt: (node) =>
Expand All @@ -16,4 +16,10 @@ export const transactionMap: FullTransformMap<string, AllTransactionNodes> = {
show([node.releaseKw, node.savepointKw, node.savepoint]),
transaction_chain_clause: (node) => show([node.andChainKw]),
transaction_no_chain_clause: (node) => show([node.andNoChainKw]),
transaction_mode_deferrable: (node) => show([node.deferrableKw]),
transaction_mode_not_deferrable: (node) => show([node.notDeferrableKw]),
transaction_mode_read_write: (node) => show([node.readWriteKw]),
transaction_mode_read_only: (node) => show([node.readOnlyKw]),
transaction_mode_isolation_level: (node) =>
show([node.isolationLevelKw, node.levelKw]),
};
23 changes: 23 additions & 0 deletions test/transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ describe("transactions", () => {
testWc("BEGIN WORK");
});
});

dialect("postgresql", () => {
it("supports [NOT] DEFERRABLE", () => {
testWc("BEGIN NOT DEFERRABLE");
testWc("BEGIN DEFERRABLE");
});

it("supports READ {WRITE | ONLY}", () => {
testWc("BEGIN READ WRITE");
testWc("BEGIN READ ONLY");
});

it("supports ISOLATION LEVEL", () => {
testWc("BEGIN ISOLATION LEVEL SERIALIZABLE");
testWc("BEGIN ISOLATION LEVEL REPEATABLE READ");
testWc("BEGIN ISOLATION LEVEL READ COMMITTED");
testWc("BEGIN ISOLATION LEVEL READ UNCOMMITTED");
});

it("supports multiple transaction modes", () => {
testWc("BEGIN READ ONLY, ISOLATION LEVEL SERIALIZABLE, DEFERRABLE");
});
});
});

describe("committing transaction", () => {
Expand Down

0 comments on commit b984abe

Please sign in to comment.