Skip to content

Commit 5a11707

Browse files
authored
fix: distinguish delimiters in queries from SQL comments (#22)
* fix: distinguish double dashes in queries from SQL comments * test: add no backtick case
1 parent ca998a7 commit 5a11707

2 files changed

Lines changed: 92 additions & 0 deletions

File tree

src/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const CHARS_ESCAPE_MAP: Record<string, string> = {
2929

3030
const charCode = {
3131
singleQuote: 39,
32+
backtick: 96,
3233
backslash: 92,
3334
dash: 45,
3435
slash: 47,
@@ -110,6 +111,23 @@ const skipSqlContext = (sql: string, position: number): number => {
110111
return sql.length;
111112
}
112113

114+
if (currentChar === charCode.backtick) {
115+
const length = sql.length;
116+
117+
for (let cursor = position + 1; cursor < length; cursor++) {
118+
if (sql.charCodeAt(cursor) !== charCode.backtick) continue;
119+
120+
if (sql.charCodeAt(cursor + 1) === charCode.backtick) {
121+
cursor++;
122+
continue;
123+
}
124+
125+
return cursor + 1;
126+
}
127+
128+
return length;
129+
}
130+
113131
if (currentChar === charCode.dash && nextChar === charCode.dash) {
114132
const lineBreak = sql.indexOf('\n', position + 2);
115133
return lineBreak === -1 ? sql.length : lineBreak + 1;
@@ -132,6 +150,7 @@ const findNextPlaceholder = (sql: string, start: number): number => {
132150

133151
if (
134152
code === charCode.singleQuote ||
153+
code === charCode.backtick ||
135154
code === charCode.dash ||
136155
code === charCode.slash
137156
) {
@@ -153,6 +172,7 @@ const findSetKeyword = (sql: string, startFrom = 0): number => {
153172

154173
if (
155174
code === charCode.singleQuote ||
175+
code === charCode.backtick ||
156176
code === charCode.dash ||
157177
code === charCode.slash
158178
) {

test/everyday-queries.test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,3 +544,75 @@ describe('Nice to have: Boolean in various contexts', () => {
544544
assert.equal(sql, 'UPDATE t SET `active` = true, `archived` = false');
545545
});
546546
});
547+
548+
describe('Critical: Backtick-quoted identifiers with comment-like sequences', () => {
549+
test('database/table names with double dashes', () => {
550+
const sql = format(
551+
'INSERT INTO `db--name`.`table`(`a`, `b`) VALUES (?, ?)',
552+
[1, 'hello']
553+
);
554+
assert.equal(
555+
sql,
556+
"INSERT INTO `db--name`.`table`(`a`, `b`) VALUES (1, 'hello')"
557+
);
558+
});
559+
560+
test('column names with double dashes', () => {
561+
const sql = format(
562+
'INSERT INTO t (`col--1`, `col--2`) VALUES (?, ?)',
563+
[1, 2]
564+
);
565+
assert.equal(sql, 'INSERT INTO t (`col--1`, `col--2`) VALUES (1, 2)');
566+
});
567+
568+
test('backticks with block comment markers', () => {
569+
const sql = format('INSERT INTO `table/*name*/` VALUES (?)', [1]);
570+
assert.equal(sql, 'INSERT INTO `table/*name*/` VALUES (1)');
571+
});
572+
573+
test('escaped backticks inside identifiers', () => {
574+
const sql = format('INSERT INTO `table``name` VALUES (?)', [1]);
575+
assert.equal(sql, 'INSERT INTO `table``name` VALUES (1)');
576+
});
577+
578+
test('multiple backtick identifiers with mixed comment markers', () => {
579+
const sql = format(
580+
'SELECT * FROM `db--1`.`table/*test*/` WHERE `col--id` = ?',
581+
[42]
582+
);
583+
assert.equal(
584+
sql,
585+
'SELECT * FROM `db--1`.`table/*test*/` WHERE `col--id` = 42'
586+
);
587+
});
588+
589+
test('UPDATE with backtick identifiers containing dashes', () => {
590+
const sql = format('UPDATE `table--name` SET `col--1` = ? WHERE id = ?', [
591+
'value',
592+
1,
593+
]);
594+
assert.equal(
595+
sql,
596+
"UPDATE `table--name` SET `col--1` = 'value' WHERE id = 1"
597+
);
598+
});
599+
600+
test('SELECT with ?? and backtick-quoted values with dashes', () => {
601+
const sql = format('SELECT ?? FROM `users--table` WHERE id = ?', [
602+
['col--1', 'col--2'],
603+
1,
604+
]);
605+
assert.equal(
606+
sql,
607+
'SELECT `col--1`, `col--2` FROM `users--table` WHERE id = 1'
608+
);
609+
});
610+
611+
test('SELECT with ?? without any backticks in query', () => {
612+
const sql = format('SELECT ?? FROM users WHERE id = ?', [
613+
['id', 'name'],
614+
1,
615+
]);
616+
assert.equal(sql, 'SELECT `id`, `name` FROM users WHERE id = 1');
617+
});
618+
});

0 commit comments

Comments
 (0)