Skip to content

Commit 1b927a9

Browse files
authored
fix(sql-escaper): resolve multi statement and expand object regressions (#4380)
* fix(sql-escaper): resolve multi statement and expand object regressions * ci: add integration tests * chore: "mute" benchmarks until #4146
1 parent 122dba8 commit 1b927a9

4 files changed

Lines changed: 98 additions & 15 deletions

File tree

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,4 @@ jobs:
7979
auto-push: false
8080
alert-threshold: '115%'
8181
github-token: ${{ secrets.GITHUB_TOKEN }}
82-
comment-on-alert: true
82+
comment-on-alert: false

package-lock.json

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"long": "^5.3.2",
6161
"lru.min": "^1.1.4",
6262
"named-placeholders": "^1.1.6",
63-
"sql-escaper": "^1.3.3"
63+
"sql-escaper": "^1.4.0"
6464
},
6565
"peerDependencies": {
6666
"@types/node": ">= 8"
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import type { ResultSetHeader, RowDataPacket } from '../../../index.js';
2+
import { describe, it, strict } from 'poku';
3+
import { createConnection, createPool } from '../../common.test.mjs';
4+
5+
type DomainRow = RowDataPacket & { id: number; domain: string };
6+
type DocRow = RowDataPacket & { id: number; foo: string; hasModified: number };
7+
8+
await describe('Regression #4126 — object placeholders expand in SET assignment lists', async () => {
9+
await describe('client-side formatting', async () => {
10+
const connection = createConnection();
11+
12+
it('should expand ?? and ? object inside SET STATEMENT ... FOR INSERT', () => {
13+
strict.equal(
14+
connection.format(
15+
'SET STATEMENT max_statement_time=15 FOR INSERT INTO ?? SET ?',
16+
['domains', { id: 1, domain: 'test.com' }]
17+
),
18+
"SET STATEMENT max_statement_time=15 FOR INSERT INTO `domains` SET `id` = 1, `domain` = 'test.com'"
19+
);
20+
});
21+
22+
it('should expand ? object after UTC_TIMESTAMP() in an UPDATE SET list', () => {
23+
strict.equal(
24+
connection.format(
25+
'UPDATE docs SET modified = UTC_TIMESTAMP(), ? WHERE id = ?',
26+
[{ foo: 'bar' }, 123]
27+
),
28+
"UPDATE docs SET modified = UTC_TIMESTAMP(), `foo` = 'bar' WHERE id = 123"
29+
);
30+
});
31+
32+
connection.end();
33+
});
34+
35+
await describe('end-to-end execution', async () => {
36+
const pool = createPool({ connectionLimit: 1 }).promise();
37+
38+
await it('should insert via object-form query with ??, ? object and timeout', async () => {
39+
await pool.query(
40+
'CREATE TEMPORARY TABLE domains (id INT PRIMARY KEY, domain VARCHAR(255))'
41+
);
42+
43+
const [result] = await pool.query<ResultSetHeader>({
44+
sql: 'INSERT INTO ?? SET ?',
45+
values: ['domains', { id: 1, domain: 'test.com' }],
46+
timeout: 16000,
47+
});
48+
49+
strict.equal(result.affectedRows, 1);
50+
51+
const [rows] = await pool.query<DomainRow[]>(
52+
'SELECT id, domain FROM domains'
53+
);
54+
strict.equal(rows.length, 1);
55+
strict.equal(rows[0].id, 1);
56+
strict.equal(rows[0].domain, 'test.com');
57+
});
58+
59+
await it('should update via ? object mixed with UTC_TIMESTAMP()', async () => {
60+
await pool.query(
61+
'CREATE TEMPORARY TABLE docs (id INT PRIMARY KEY, foo VARCHAR(50), modified DATETIME)'
62+
);
63+
await pool.query('INSERT INTO docs (id, foo) VALUES (123, ?)', ['old']);
64+
65+
const [result] = await pool.query<ResultSetHeader>(
66+
'UPDATE docs SET modified = UTC_TIMESTAMP(), ? WHERE id = ?',
67+
[{ foo: 'bar' }, 123]
68+
);
69+
70+
strict.equal(result.affectedRows, 1);
71+
72+
const [rows] = await pool.query<DocRow[]>(
73+
'SELECT id, foo, modified IS NOT NULL AS hasModified FROM docs'
74+
);
75+
76+
strict.equal(rows.length, 1);
77+
strict.equal(rows[0].foo, 'bar');
78+
strict.equal(rows[0].hasModified, 1);
79+
});
80+
81+
await pool.end();
82+
});
83+
});

0 commit comments

Comments
 (0)