Skip to content

Commit 961f222

Browse files
committed
Add support for SET TRANSACTION statements.
1 parent 3f88e57 commit 961f222

File tree

6 files changed

+118
-1
lines changed

6 files changed

+118
-1
lines changed

src/ast-mapper.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export interface IAstPartialMapper {
8787
createSequence?(seq: a.CreateSequenceStatement): a.Statement | nil
8888
alterSequence?(seq: a.AlterSequenceStatement): a.Statement | nil
8989
begin?(begin: a.BeginStatement): a.Statement | nil
90+
setTransactionSnapshot?(snapshot: a.SetTransactionSnapshot): a.Statement | nil
91+
setTransaction?(transaction: a.SetTransactionMode): a.Statement | nil
92+
setSession?(session: a.SetTransactionMode): a.Statement | nil
9093
}
9194

9295
export type IAstFullMapper = {
@@ -247,6 +250,12 @@ export class AstDefaultMapper implements IAstMapper {
247250
return this.setGlobal(val);
248251
case 'set timezone':
249252
return this.setTimezone(val);
253+
case 'set transaction snapshot':
254+
return this.setTransactionSnapshot(val);
255+
case 'set transaction':
256+
return this.setTransaction(val);
257+
case 'set session characteristics as transaction':
258+
return this.setSession(val);
250259
case 'create sequence':
251260
return this.createSequence(val);
252261
case 'alter sequence':
@@ -437,6 +446,17 @@ export class AstDefaultMapper implements IAstMapper {
437446
return val;
438447
}
439448

449+
setTransactionSnapshot?(snapshot: a.SetTransactionSnapshot): a.Statement | nil {
450+
return snapshot;
451+
}
452+
453+
setTransaction?(transaction: a.SetTransactionMode): a.Statement | nil {
454+
return transaction;
455+
}
456+
457+
setSession?(session: a.SetTransactionMode): a.Statement | nil {
458+
return session;
459+
}
440460

441461
update(val: a.UpdateStatement): a.Statement | nil {
442462
if (!val) {

src/syntax/ast.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ export interface BeginStatement extends PGNode {
6262
deferrable?: boolean;
6363
}
6464

65+
export interface SetTransactionSnapshot extends PGNode {
66+
type: 'set transaction snapshot';
67+
snapshotId: Name;
68+
}
69+
70+
export interface SetTransactionMode extends PGNode {
71+
type: 'set transaction' | 'set session characteristics as transaction';
72+
isolationLevel: 'serializable' | 'repeatable read' | 'read committed' | 'read uncommitted';
73+
writeable?: 'read write' | 'read only';
74+
deferrable?: boolean;
75+
}
76+
6577
export interface DoStatement extends PGNode {
6678
type: 'do';
6779
language?: Name;

src/syntax/base.ne

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ kw_filter -> %word {% notReservedKw('filter') %}
144144
kw_commit -> %word {% notReservedKw('commit') %}
145145
kw_tablespace -> %word {% notReservedKw('tablespace') %}
146146
kw_transaction -> %word {% notReservedKw('transaction') %}
147+
kw_snapshot -> %word {% notReservedKw('snapshot') %}
148+
kw_session -> %word {% notReservedKw('session') %}
149+
kw_characteristics -> %word {% notReservedKw('characteristics') %}
147150
kw_work -> %word {% notReservedKw('work') %}
148151
kw_read -> %word {% notReservedKw('read') %}
149152
kw_write -> %word {% notReservedKw('write') %}

src/syntax/simple-statements.ne

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ simplestatements_tablespace -> kw_tablespace word {% x => track(x, {
3434
}) %}
3535

3636

37-
simplestatements_set -> kw_set (simplestatements_set_simple | simplestatements_set_timezone) {% last %}
37+
simplestatements_set -> kw_set (simplestatements_set_simple
38+
| simplestatements_set_timezone
39+
| simplestatements_set_session
40+
| simplestatements_set_transaction_snapshot
41+
| simplestatements_set_transaction) {% last %}
3842

3943
simplestatements_set_timezone -> kw_time kw_zone simplestatements_set_timezone_val {% x => track(x, { type: 'set timezone', to: x[2] }) %}
4044

@@ -65,6 +69,27 @@ simplestatements_set_val_raw
6569

6670
simplestatements_show -> kw_show ident {% x => track(x, { type: 'show', variable: asName(x[1]) }) %}
6771

72+
# https://www.postgresql.org/docs/current/sql-set-transaction.html
73+
simplestatements_set_transaction_snapshot
74+
-> kw_transaction kw_snapshot ident {% x => track(x, { type: 'set transaction snapshot', snapshotId: asName(x[2]) }) %}
75+
76+
simplestatements_set_session
77+
-> kw_session kw_characteristics %kw_as kw_transaction
78+
(simplestatements_begin_isol | simplestatements_begin_writ | simplestatements_begin_def):* {%
79+
x => track(x, {
80+
type: 'set session characteristics as transaction',
81+
...x[4].reduce((a: any, b: any) => ({...unwrap(a), ...unwrap(b)}), {}),
82+
})
83+
%}
84+
85+
simplestatements_set_transaction
86+
-> kw_transaction (simplestatements_begin_isol | simplestatements_begin_writ | simplestatements_begin_def):* {%
87+
x => track(x, {
88+
type: 'set transaction',
89+
...x[1].reduce((a: any, b: any) => ({...unwrap(a), ...unwrap(b)}), {}),
90+
})
91+
%}
92+
6893

6994
# https://www.postgresql.org/docs/current/sql-createschema.html
7095
create_schema -> (%kw_create kw_schema) kw_ifnotexists:? ident {% x => track(x, {

src/syntax/simple-statements.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,26 @@ describe('Simple statements', () => {
247247
})
248248

249249

250+
checkStatement(`set transaction SNAPSHOT mysnapshot`, {
251+
type: 'set transaction snapshot',
252+
snapshotId: { name: 'mysnapshot' },
253+
});
254+
255+
checkStatement(`set transaction isolation level repeatable read read only not deferrable`, {
256+
type: 'set transaction',
257+
isolationLevel: 'repeatable read',
258+
writeable: 'read only',
259+
deferrable: false,
260+
});
261+
262+
checkStatement(`set session characteristics as transaction isolation level read uncommitted deferrable read write`, {
263+
type: 'set session characteristics as transaction',
264+
isolationLevel: 'read uncommitted',
265+
writeable: 'read write',
266+
deferrable: true,
267+
});
268+
269+
250270
checkStatement(`select * from (select a from mytable) myalias(col_renamed)`, {
251271
type: 'select',
252272
columns: [{ expr: { type: 'ref', name: '*' } }],

src/to-sql.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,43 @@ const visitor = astVisitor<IAstFullVisitor>(m => ({
564564
}
565565
},
566566

567+
setTransactionSnapshot: s => {
568+
ret.push('SET TRANSACTION SNAPSHOT ');
569+
ret.push(name(s.snapshotId));
570+
},
571+
572+
setTransaction: tx => {
573+
ret.push('SET TRANSACTION ');
574+
if (tx.isolationLevel) {
575+
ret.push('ISOLATION LEVEL ', tx.isolationLevel.toUpperCase(), ' ');
576+
}
577+
if (tx.writeable) {
578+
ret.push(tx.writeable.toUpperCase(), ' ');
579+
}
580+
if (typeof tx.deferrable === 'boolean') {
581+
if (!tx.deferrable) {
582+
ret.push('NOT ');
583+
}
584+
ret.push('DEFERRABLE ');
585+
}
586+
},
587+
588+
setSession: s => {
589+
ret.push('SET SESSION CHARACTERISTICS AS TRANSACTION ');
590+
if (s.isolationLevel) {
591+
ret.push('ISOLATION LEVEL ', s.isolationLevel.toUpperCase(), ' ');
592+
}
593+
if (s.writeable) {
594+
ret.push(s.writeable.toUpperCase(), ' ');
595+
}
596+
if (typeof s.deferrable === 'boolean') {
597+
if (!s.deferrable) {
598+
ret.push('NOT ');
599+
}
600+
ret.push('DEFERRABLE ');
601+
}
602+
},
603+
567604
begin: beg => {
568605
ret.push('BEGIN ');
569606
if (beg.isolationLevel) {

0 commit comments

Comments
 (0)