Skip to content

Commit 995291c

Browse files
committed
fix(sqlite): support Tcl-style $param(...) syntax (#944)
2 parents a66b900 + 37b69ee commit 995291c

3 files changed

Lines changed: 54 additions & 2 deletions

File tree

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Sasha Aliashkevich <olsender@gmail.com>
6060
Sean Song <mail@seansong.dev>
6161
Sebastian Lyng Johansen <seblyng98@gmail.com>
6262
Sergei Egorov <sergei.egorov@zeroturnaround.com>
63+
Sai Asish Y <say.apm35@gmail.com>
6364
Shub <shub1493biswas@gmail.com>
6465
Stanislav Germanovskii <s.germanovskiy@tinkoff.ru>
6566
Steven Yung <stevenyung@fastmail.com>

src/languages/sqlite/sqlite.formatter.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,19 @@ export const sqlite: DialectOptions = {
9090
],
9191
identTypes: [`""-qq`, '``', '[]'],
9292
// https://www.sqlite.org/lang_expr.html#parameters
93-
paramTypes: { positional: true, numbered: ['?'], named: [':', '@', '$'] },
93+
// Note: the $-prefixed form follows Tcl variable syntax and may include
94+
// one or more "::"-separated suffixes and an optional "(...)" trailer.
95+
paramTypes: {
96+
positional: true,
97+
numbered: ['?'],
98+
named: [':', '@'],
99+
custom: [
100+
{
101+
regex: String.raw`\$[a-zA-Z_][a-zA-Z0-9_]*(?:::[a-zA-Z_][a-zA-Z0-9_]*)*(?:\([^)]*\))?`,
102+
key: v => v.slice(1),
103+
},
104+
],
105+
},
94106
operators: ['%', '~', '&', '|', '<<', '>>', '==', '->', '->>', '||'],
95107
},
96108
formatOptions: {

test/sqlite.test.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,46 @@ describe('SqliteFormatter', () => {
5555
supportsJoin(format);
5656
supportsSetOperations(format, ['UNION', 'UNION ALL', 'EXCEPT', 'INTERSECT']);
5757
supportsOperators(format, ['%', '~', '&', '|', '<<', '>>', '==', '->', '->>', '||']);
58-
supportsParams(format, { positional: true, numbered: ['?'], named: [':', '$', '@'] });
58+
supportsParams(format, { positional: true, numbered: ['?'], named: [':', '@'] });
59+
60+
// SQLite has its own Tcl-style $-parameter syntax that is handled as a custom
61+
// param type rather than the default named-param prefix. See sqlite.formatter.ts.
62+
describe('supports SQLite $-style (Tcl) named placeholders', () => {
63+
it('recognizes $name placeholders', () => {
64+
expect(format('SELECT $foo, $bar, $baz;')).toBe(dedent`
65+
SELECT
66+
$foo,
67+
$bar,
68+
$baz;
69+
`);
70+
});
71+
72+
it('recognizes $name(...) placeholders without inserting a space', () => {
73+
expect(format('select $p(x=y);')).toBe(dedent`
74+
select
75+
$p(x=y);
76+
`);
77+
});
78+
79+
it('recognizes $name with :: suffix and (...) trailer', () => {
80+
expect(format('SELECT $foo::bar(extra);')).toBe(dedent`
81+
SELECT
82+
$foo::bar(extra);
83+
`);
84+
});
85+
86+
it('replaces $name placeholders with param values', () => {
87+
expect(
88+
format(`WHERE name = $name AND age > $current_age;`, {
89+
params: { name: "'John'", current_age: '10' },
90+
})
91+
).toBe(dedent`
92+
WHERE
93+
name = 'John'
94+
AND age > 10;
95+
`);
96+
});
97+
});
5998
supportsWindow(format);
6099
supportsLimiting(format, { limit: true, offset: true });
61100
supportsDataTypeCase(format);

0 commit comments

Comments
 (0)