Skip to content

Commit d3c008b

Browse files
authored
Support SKIP LOCKED and NOWAIT (#129)
* feat: updated syntax parser * feat: added keywords and tests * feat: updated to-sql * fix: renamed interface * feat: reverted keyword changes * cleanup keywords.ts * feat: cleanup eof in keywords.ts * removed eol line * reverting keywords.ts
1 parent 6df49a5 commit d3c008b

File tree

5 files changed

+43
-2
lines changed

5 files changed

+43
-2
lines changed

src/syntax/ast.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ export interface SelectFromStatement extends PGNode {
636636
orderBy?: OrderByStatement[] | nil;
637637
distinct?: 'all' | 'distinct' | Expr[] | nil;
638638
for?: ForStatement;
639+
skip?: SkipClause;
639640
}
640641

641642
export interface SelectFromUnion extends PGNode {
@@ -654,6 +655,10 @@ export interface ForStatement extends PGNode {
654655
type: 'update' | 'no key update' | 'share' | 'key share';
655656
}
656657

658+
export interface SkipClause extends PGNode {
659+
type: 'nowait' | 'skip locked'
660+
}
661+
657662
export interface LimitStatement extends PGNode {
658663
limit?: Expr | nil;
659664
offset?: Expr | nil;

src/syntax/base.ne

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ kw_raise -> %word {% notReservedKw('raise') %}
240240
kw_continue -> %word {% notReservedKw('continue') %}
241241
kw_share -> %word {% notReservedKw('share') %}
242242
kw_refresh -> %word {% notReservedKw('refresh') %}
243+
kw_nowait -> %word {% notReservedKw('nowait') %}
244+
kw_skip -> %word {% notReservedKw('skip') %}
245+
kw_locked -> %word {% notReservedKw('locked') %}
243246

244247

245248
# === Composite keywords

src/syntax/select.ne

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ array_of[EXP] -> $EXP (%comma $EXP {% last %}):* {% ([head, tail]) => {
1010
# https://www.postgresql.org/docs/12/sql-select.html
1111

1212
select_statement
13-
-> select_what select_from:? select_where:? (select_groupby select_having:?):? select_order_by:? select_limit_offset:? select_for:?
13+
-> select_what select_from:? select_where:? (select_groupby select_having:?):? select_order_by:? select_limit_offset:? (select_for select_skip:?):?
1414
{% x => {
15-
let [what, from, where, _groupBy, orderBy, limit, selectFor] = x;
15+
let [what, from, where, _groupBy, orderBy, limit, _selectFor] = x;
1616
from = unwrap(from);
1717
let groupBy = _groupBy && _groupBy[0];
1818
let having = _groupBy && _groupBy[1];
1919
groupBy = groupBy && (groupBy.length === 1 && groupBy[0].type === 'list' ? groupBy[0].expressions : groupBy);
2020
having = having && unwrap(having);
21+
let selectFor = _selectFor && _selectFor[0];
22+
let skip = _selectFor && _selectFor[1];
23+
skip = unwrap(skip);
2124
return track(x, {
2225
...what,
2326
...from ? { from: Array.isArray(from) ? from : [from] } : {},
@@ -27,6 +30,7 @@ select_statement
2730
...orderBy ? { orderBy } : {},
2831
...where ? { where } : {},
2932
...selectFor ? { for: selectFor[1] } : {},
33+
...skip ? { skip } : {},
3034
type: 'select',
3135
});
3236
} %}
@@ -201,6 +205,9 @@ select_for -> %kw_for (
201205
| kw_share {% x => track(x, {type: 'share'}) %}
202206
| kw_key kw_share {% x => track(x, {type: 'key share'}) %})
203207

208+
# [ NOWAIT | SKIP LOCKED ]
209+
select_skip -> (kw_nowait {% x => track(x, {type: 'nowait'}) %} | kw_skip kw_locked {% x => track(x, {type: 'skip locked'}) %})
210+
204211
select_order_by -> (%kw_order kw_by) select_order_by_expr (comma select_order_by_expr {%last%}):* {% ([_, head, tail]) => {
205212
return [head, ...(tail || [])];
206213
} %}

src/syntax/select.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,4 +920,27 @@ describe('Select statements', () => {
920920
type: 'key share',
921921
}
922922
});
923+
924+
checkSelect('select * from test for key share nowait', {
925+
type: 'select',
926+
from: [tbl('test')],
927+
columns: columns({ type: 'ref', name: '*' }),
928+
for: {
929+
type: 'key share',
930+
},
931+
skip: {
932+
type: 'nowait',
933+
}
934+
});
935+
checkSelect('select * from test for key share skip locked', {
936+
type: 'select',
937+
from: [tbl('test')],
938+
columns: columns({ type: 'ref', name: '*' }),
939+
for: {
940+
type: 'key share',
941+
},
942+
skip: {
943+
type: 'skip locked',
944+
}
945+
});
923946
});

src/to-sql.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,9 @@ const visitor = astVisitor<IAstFullVisitor>(m => ({
13561356

13571357
if (s.for) {
13581358
ret.push('FOR ', s.for.type.toUpperCase());
1359+
if (s.skip) {
1360+
ret.push(' ', s.skip.type.toUpperCase());
1361+
}
13591362
}
13601363
},
13611364

0 commit comments

Comments
 (0)