Skip to content

Latest commit

Β 

History

History
611 lines (551 loc) Β· 20.1 KB

File metadata and controls

611 lines (551 loc) Β· 20.1 KB
Β 
May 2, 2025
May 2, 2025
1
// Flags: --expose-gc
Aug 12, 2024
Aug 12, 2024
2
'use strict';
May 16, 2025
May 16, 2025
3
const { skipIfSQLiteMissing } = require('../common');
4
skipIfSQLiteMissing();
Aug 12, 2024
Aug 12, 2024
5
const tmpdir = require('../common/tmpdir');
6
const { join } = require('node:path');
7
const { DatabaseSync, StatementSync } = require('node:sqlite');
8
const { suite, test } = require('node:test');
9
let cnt = 0;
10
11
tmpdir.refresh();
12
13
function nextDb() {
14
return join(tmpdir.path, `database-${cnt++}.db`);
15
}
16
17
suite('StatementSync() constructor', () => {
18
test('StatementSync cannot be constructed directly', (t) => {
19
t.assert.throws(() => {
20
new StatementSync();
21
}, {
22
code: 'ERR_ILLEGAL_CONSTRUCTOR',
23
message: /Illegal constructor/,
24
});
25
});
26
});
27
28
suite('StatementSync.prototype.get()', () => {
29
test('executes a query and returns undefined on no results', (t) => {
30
const db = new DatabaseSync(nextDb());
31
t.after(() => { db.close(); });
32
let stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
33
t.assert.strictEqual(stmt.get(), undefined);
34
stmt = db.prepare('SELECT * FROM storage');
35
t.assert.strictEqual(stmt.get(), undefined);
36
});
37
38
test('executes a query and returns the first result', (t) => {
39
const db = new DatabaseSync(nextDb());
40
t.after(() => { db.close(); });
41
let stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
42
t.assert.strictEqual(stmt.get(), undefined);
43
stmt = db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)');
44
t.assert.strictEqual(stmt.get('key1', 'val1'), undefined);
45
t.assert.strictEqual(stmt.get('key2', 'val2'), undefined);
46
stmt = db.prepare('SELECT * FROM storage ORDER BY key');
Aug 25, 2024
Aug 25, 2024
47
t.assert.deepStrictEqual(stmt.get(), { __proto__: null, key: 'key1', val: 'val1' });
48
});
49
50
test('executes a query that returns special columns', (t) => {
51
const db = new DatabaseSync(nextDb());
52
t.after(() => { db.close(); });
53
const stmt = db.prepare('SELECT 1 as __proto__, 2 as constructor, 3 as toString');
54
t.assert.deepStrictEqual(stmt.get(), { __proto__: null, ['__proto__']: 1, constructor: 2, toString: 3 });
Aug 12, 2024
Aug 12, 2024
55
});
56
});
57
58
suite('StatementSync.prototype.all()', () => {
59
test('executes a query and returns an empty array on no results', (t) => {
60
const db = new DatabaseSync(nextDb());
61
t.after(() => { db.close(); });
62
const stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
63
t.assert.deepStrictEqual(stmt.all(), []);
64
});
65
66
test('executes a query and returns all results', (t) => {
67
const db = new DatabaseSync(nextDb());
68
t.after(() => { db.close(); });
69
let stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
70
t.assert.deepStrictEqual(stmt.run(), { changes: 0, lastInsertRowid: 0 });
71
stmt = db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)');
72
t.assert.deepStrictEqual(
73
stmt.run('key1', 'val1'),
74
{ changes: 1, lastInsertRowid: 1 },
75
);
76
t.assert.deepStrictEqual(
77
stmt.run('key2', 'val2'),
78
{ changes: 1, lastInsertRowid: 2 },
79
);
80
stmt = db.prepare('SELECT * FROM storage ORDER BY key');
81
t.assert.deepStrictEqual(stmt.all(), [
Aug 25, 2024
Aug 25, 2024
82
{ __proto__: null, key: 'key1', val: 'val1' },
83
{ __proto__: null, key: 'key2', val: 'val2' },
Aug 12, 2024
Aug 12, 2024
84
]);
85
});
86
});
87
Nov 22, 2024
Nov 22, 2024
88
suite('StatementSync.prototype.iterate()', () => {
89
test('executes a query and returns an empty iterator on no results', (t) => {
90
const db = new DatabaseSync(nextDb());
Feb 5, 2025
Feb 5, 2025
91
t.after(() => { db.close(); });
Nov 22, 2024
Nov 22, 2024
92
const stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
May 2, 2025
May 2, 2025
93
const iter = stmt.iterate();
94
t.assert.strictEqual(iter instanceof globalThis.Iterator, true);
95
t.assert.ok(iter[Symbol.iterator]);
96
t.assert.deepStrictEqual(iter.toArray(), []);
Nov 22, 2024
Nov 22, 2024
97
});
98
99
test('executes a query and returns all results', (t) => {
100
const db = new DatabaseSync(nextDb());
Feb 5, 2025
Feb 5, 2025
101
t.after(() => { db.close(); });
Nov 22, 2024
Nov 22, 2024
102
let stmt = db.prepare('CREATE TABLE storage(key TEXT, val TEXT)');
103
t.assert.deepStrictEqual(stmt.run(), { changes: 0, lastInsertRowid: 0 });
104
stmt = db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)');
105
t.assert.deepStrictEqual(
106
stmt.run('key1', 'val1'),
107
{ changes: 1, lastInsertRowid: 1 },
108
);
109
t.assert.deepStrictEqual(
110
stmt.run('key2', 'val2'),
111
{ changes: 1, lastInsertRowid: 2 },
112
);
113
114
const items = [
115
{ __proto__: null, key: 'key1', val: 'val1' },
116
{ __proto__: null, key: 'key2', val: 'val2' },
117
];
118
119
stmt = db.prepare('SELECT * FROM storage ORDER BY key');
120
t.assert.deepStrictEqual(stmt.iterate().toArray(), items);
121
122
const itemsLoop = items.slice();
123
for (const item of stmt.iterate()) {
124
t.assert.deepStrictEqual(item, itemsLoop.shift());
125
}
126
});
May 2, 2025
May 2, 2025
127
128
test('iterator keeps the prepared statement from being collected', (t) => {
129
const db = new DatabaseSync(':memory:');
130
db.exec(`
131
CREATE TABLE test(key TEXT, val TEXT);
132
INSERT INTO test (key, val) VALUES ('key1', 'val1');
133
INSERT INTO test (key, val) VALUES ('key2', 'val2');
134
`);
135
// Do not keep an explicit reference to the prepared statement.
136
const iterator = db.prepare('SELECT * FROM test').iterate();
137
const results = [];
138
139
global.gc();
140
141
for (const item of iterator) {
142
results.push(item);
143
}
144
145
t.assert.deepStrictEqual(results, [
146
{ __proto__: null, key: 'key1', val: 'val1' },
147
{ __proto__: null, key: 'key2', val: 'val2' },
148
]);
149
});
150
151
test('iterator can be exited early', (t) => {
152
const db = new DatabaseSync(':memory:');
153
db.exec(`
154
CREATE TABLE test(key TEXT, val TEXT);
155
INSERT INTO test (key, val) VALUES ('key1', 'val1');
156
INSERT INTO test (key, val) VALUES ('key2', 'val2');
157
`);
158
const iterator = db.prepare('SELECT * FROM test').iterate();
159
const results = [];
160
161
for (const item of iterator) {
162
results.push(item);
163
break;
164
}
165
166
t.assert.deepStrictEqual(results, [
167
{ __proto__: null, key: 'key1', val: 'val1' },
168
]);
169
t.assert.deepStrictEqual(
170
iterator.next(),
171
{ __proto__: null, done: true, value: null },
172
);
173
});
Nov 22, 2024
Nov 22, 2024
174
});
175
Aug 12, 2024
Aug 12, 2024
176
suite('StatementSync.prototype.run()', () => {
177
test('executes a query and returns change metadata', (t) => {
178
const db = new DatabaseSync(nextDb());
179
t.after(() => { db.close(); });
180
const setup = db.exec(`
181
CREATE TABLE storage(key TEXT, val TEXT);
182
INSERT INTO storage (key, val) VALUES ('foo', 'bar');
183
`);
184
t.assert.strictEqual(setup, undefined);
185
const stmt = db.prepare('SELECT * FROM storage');
186
t.assert.deepStrictEqual(stmt.run(), { changes: 1, lastInsertRowid: 1 });
187
});
188
189
test('SQLite throws when trying to bind too many parameters', (t) => {
190
const db = new DatabaseSync(nextDb());
191
t.after(() => { db.close(); });
192
const setup = db.exec(
193
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
194
);
195
t.assert.strictEqual(setup, undefined);
196
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
197
t.assert.throws(() => {
198
stmt.run(1, 2, 3);
199
}, {
200
code: 'ERR_SQLITE_ERROR',
201
message: 'column index out of range',
202
errcode: 25,
203
errstr: 'column index out of range',
204
});
205
});
206
207
test('SQLite defaults to NULL for unbound parameters', (t) => {
208
const db = new DatabaseSync(nextDb());
209
t.after(() => { db.close(); });
210
const setup = db.exec(
211
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
212
);
213
t.assert.strictEqual(setup, undefined);
214
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
215
t.assert.throws(() => {
216
stmt.run(1);
217
}, {
218
code: 'ERR_SQLITE_ERROR',
219
message: 'NOT NULL constraint failed: data.val',
220
errcode: 1299,
221
errstr: 'constraint failed',
222
});
223
});
May 2, 2025
May 2, 2025
224
225
test('returns correct metadata when using RETURNING', (t) => {
226
const db = new DatabaseSync(':memory:');
227
const setup = db.exec(
228
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
229
);
230
t.assert.strictEqual(setup, undefined);
231
const sql = 'INSERT INTO data (key, val) VALUES ($k, $v) RETURNING key';
232
const stmt = db.prepare(sql);
233
t.assert.deepStrictEqual(
234
stmt.run({ k: 1, v: 10 }), { changes: 1, lastInsertRowid: 1 }
235
);
236
t.assert.deepStrictEqual(
237
stmt.run({ k: 2, v: 20 }), { changes: 1, lastInsertRowid: 2 }
238
);
239
t.assert.deepStrictEqual(
240
stmt.run({ k: 3, v: 30 }), { changes: 1, lastInsertRowid: 3 }
241
);
242
});
Aug 24, 2025
Aug 24, 2025
243
244
test('SQLite defaults unbound ?NNN parameters', (t) => {
245
const db = new DatabaseSync(nextDb());
246
t.after(() => { db.close(); });
247
const setup = db.exec(
248
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
249
);
250
t.assert.strictEqual(setup, undefined);
251
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?1, ?3)');
252
253
t.assert.throws(() => {
254
stmt.run(1);
255
}, {
256
code: 'ERR_SQLITE_ERROR',
257
message: 'NOT NULL constraint failed: data.val',
258
errcode: 1299,
259
errstr: 'constraint failed',
260
});
261
});
262
263
test('binds ?NNN params by position', (t) => {
264
const db = new DatabaseSync(nextDb());
265
t.after(() => { db.close(); });
266
const setup = db.exec(
267
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
268
);
269
t.assert.strictEqual(setup, undefined);
270
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?1, ?2)');
271
t.assert.deepStrictEqual(stmt.run(1, 2), { changes: 1, lastInsertRowid: 1 });
272
});
Aug 12, 2024
Aug 12, 2024
273
});
274
Oct 6, 2024
Oct 6, 2024
275
suite('StatementSync.prototype.sourceSQL', () => {
276
test('equals input SQL', (t) => {
Aug 12, 2024
Aug 12, 2024
277
const db = new DatabaseSync(nextDb());
278
t.after(() => { db.close(); });
279
const setup = db.exec(
280
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
281
);
282
t.assert.strictEqual(setup, undefined);
283
const sql = 'INSERT INTO types (key, val) VALUES ($k, $v)';
284
const stmt = db.prepare(sql);
Oct 6, 2024
Oct 6, 2024
285
t.assert.strictEqual(stmt.sourceSQL, sql);
Aug 12, 2024
Aug 12, 2024
286
});
287
});
288
Oct 6, 2024
Oct 6, 2024
289
suite('StatementSync.prototype.expandedSQL', () => {
290
test('equals expanded SQL', (t) => {
Aug 12, 2024
Aug 12, 2024
291
const db = new DatabaseSync(nextDb());
292
t.after(() => { db.close(); });
293
const setup = db.exec(
294
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
295
);
296
t.assert.strictEqual(setup, undefined);
297
const sql = 'INSERT INTO types (key, val) VALUES ($k, ?)';
298
const expanded = 'INSERT INTO types (key, val) VALUES (\'33\', \'42\')';
299
const stmt = db.prepare(sql);
300
t.assert.deepStrictEqual(
301
stmt.run({ $k: '33' }, '42'),
302
{ changes: 1, lastInsertRowid: 33 },
303
);
Oct 6, 2024
Oct 6, 2024
304
t.assert.strictEqual(stmt.expandedSQL, expanded);
Aug 12, 2024
Aug 12, 2024
305
});
306
});
307
308
suite('StatementSync.prototype.setReadBigInts()', () => {
309
test('BigInts support can be toggled', (t) => {
310
const db = new DatabaseSync(nextDb());
311
t.after(() => { db.close(); });
312
const setup = db.exec(`
313
CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;
314
INSERT INTO data (key, val) VALUES (1, 42);
315
`);
316
t.assert.strictEqual(setup, undefined);
317
318
const query = db.prepare('SELECT val FROM data');
Aug 25, 2024
Aug 25, 2024
319
t.assert.deepStrictEqual(query.get(), { __proto__: null, val: 42 });
Aug 12, 2024
Aug 12, 2024
320
t.assert.strictEqual(query.setReadBigInts(true), undefined);
Aug 25, 2024
Aug 25, 2024
321
t.assert.deepStrictEqual(query.get(), { __proto__: null, val: 42n });
Aug 12, 2024
Aug 12, 2024
322
t.assert.strictEqual(query.setReadBigInts(false), undefined);
Aug 25, 2024
Aug 25, 2024
323
t.assert.deepStrictEqual(query.get(), { __proto__: null, val: 42 });
Aug 12, 2024
Aug 12, 2024
324
325
const insert = db.prepare('INSERT INTO data (key) VALUES (?)');
326
t.assert.deepStrictEqual(
327
insert.run(10),
328
{ changes: 1, lastInsertRowid: 10 },
329
);
330
t.assert.strictEqual(insert.setReadBigInts(true), undefined);
331
t.assert.deepStrictEqual(
332
insert.run(20),
333
{ changes: 1n, lastInsertRowid: 20n },
334
);
335
t.assert.strictEqual(insert.setReadBigInts(false), undefined);
336
t.assert.deepStrictEqual(
337
insert.run(30),
338
{ changes: 1, lastInsertRowid: 30 },
339
);
340
});
341
342
test('throws when input is not a boolean', (t) => {
343
const db = new DatabaseSync(nextDb());
344
t.after(() => { db.close(); });
345
const setup = db.exec(
346
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
347
);
348
t.assert.strictEqual(setup, undefined);
349
const stmt = db.prepare('INSERT INTO types (key, val) VALUES ($k, $v)');
350
t.assert.throws(() => {
351
stmt.setReadBigInts();
352
}, {
353
code: 'ERR_INVALID_ARG_TYPE',
354
message: /The "readBigInts" argument must be a boolean/,
355
});
356
});
357
358
test('BigInt is required for reading large integers', (t) => {
359
const db = new DatabaseSync(nextDb());
360
t.after(() => { db.close(); });
361
const bad = db.prepare(`SELECT ${Number.MAX_SAFE_INTEGER} + 1`);
362
t.assert.throws(() => {
363
bad.get();
364
}, {
365
code: 'ERR_OUT_OF_RANGE',
May 2, 2025
May 2, 2025
366
message: /^Value is too large to be represented as a JavaScript number: 9007199254740992$/,
Aug 12, 2024
Aug 12, 2024
367
});
368
const good = db.prepare(`SELECT ${Number.MAX_SAFE_INTEGER} + 1`);
369
good.setReadBigInts(true);
370
t.assert.deepStrictEqual(good.get(), {
Aug 25, 2024
Aug 25, 2024
371
__proto__: null,
Aug 12, 2024
Aug 12, 2024
372
[`${Number.MAX_SAFE_INTEGER} + 1`]: 2n ** 53n,
373
});
374
});
375
});
376
May 2, 2025
May 2, 2025
377
suite('StatementSync.prototype.setReturnArrays()', () => {
378
test('throws when input is not a boolean', (t) => {
379
const db = new DatabaseSync(nextDb());
380
t.after(() => { db.close(); });
381
const setup = db.exec(
382
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
383
);
384
t.assert.strictEqual(setup, undefined);
385
const stmt = db.prepare('SELECT key, val FROM data');
386
t.assert.throws(() => {
387
stmt.setReturnArrays();
388
}, {
389
code: 'ERR_INVALID_ARG_TYPE',
390
message: /The "returnArrays" argument must be a boolean/,
391
});
392
});
393
});
394
395
suite('StatementSync.prototype.get() with array output', () => {
396
test('returns array row when setReturnArrays is true', (t) => {
397
const db = new DatabaseSync(nextDb());
398
t.after(() => { db.close(); });
399
const setup = db.exec(`
400
CREATE TABLE data(key INTEGER PRIMARY KEY, val TEXT) STRICT;
401
INSERT INTO data (key, val) VALUES (1, 'one');
402
`);
403
t.assert.strictEqual(setup, undefined);
404
405
const query = db.prepare('SELECT key, val FROM data WHERE key = 1');
406
t.assert.deepStrictEqual(query.get(), { __proto__: null, key: 1, val: 'one' });
407
408
query.setReturnArrays(true);
409
t.assert.deepStrictEqual(query.get(), [1, 'one']);
410
411
query.setReturnArrays(false);
412
t.assert.deepStrictEqual(query.get(), { __proto__: null, key: 1, val: 'one' });
413
});
414
415
test('returns array rows with BigInts when both flags are set', (t) => {
416
const expected = [1n, 9007199254740992n];
417
const db = new DatabaseSync(nextDb());
418
t.after(() => { db.close(); });
419
const setup = db.exec(`
420
CREATE TABLE big_data(id INTEGER, big_num INTEGER);
421
INSERT INTO big_data VALUES (1, 9007199254740992);
422
`);
423
t.assert.strictEqual(setup, undefined);
424
425
const query = db.prepare('SELECT id, big_num FROM big_data');
426
query.setReturnArrays(true);
427
query.setReadBigInts(true);
428
429
const row = query.get();
430
t.assert.deepStrictEqual(row, expected);
431
});
432
});
433
434
suite('StatementSync.prototype.all() with array output', () => {
435
test('returns array rows when setReturnArrays is true', (t) => {
436
const db = new DatabaseSync(nextDb());
437
t.after(() => { db.close(); });
438
const setup = db.exec(`
439
CREATE TABLE data(key INTEGER PRIMARY KEY, val TEXT) STRICT;
440
INSERT INTO data (key, val) VALUES (1, 'one');
441
INSERT INTO data (key, val) VALUES (2, 'two');
442
`);
443
t.assert.strictEqual(setup, undefined);
444
445
const query = db.prepare('SELECT key, val FROM data ORDER BY key');
446
t.assert.deepStrictEqual(query.all(), [
447
{ __proto__: null, key: 1, val: 'one' },
448
{ __proto__: null, key: 2, val: 'two' },
449
]);
450
451
query.setReturnArrays(true);
452
t.assert.deepStrictEqual(query.all(), [
453
[1, 'one'],
454
[2, 'two'],
455
]);
456
457
query.setReturnArrays(false);
458
t.assert.deepStrictEqual(query.all(), [
459
{ __proto__: null, key: 1, val: 'one' },
460
{ __proto__: null, key: 2, val: 'two' },
461
]);
462
});
463
464
test('handles array rows with many columns', (t) => {
465
const expected = [
466
1,
467
'text1',
468
1.1,
469
new Uint8Array([0xde, 0xad, 0xbe, 0xef]),
470
5,
471
'text2',
472
2.2,
473
new Uint8Array([0xbe, 0xef, 0xca, 0xfe]),
474
9,
475
'text3',
476
];
477
const db = new DatabaseSync(nextDb());
478
t.after(() => { db.close(); });
479
const setup = db.exec(`
480
CREATE TABLE wide_table(
481
col1 INTEGER, col2 TEXT, col3 REAL, col4 BLOB, col5 INTEGER,
482
col6 TEXT, col7 REAL, col8 BLOB, col9 INTEGER, col10 TEXT
483
);
484
INSERT INTO wide_table VALUES (
485
1, 'text1', 1.1, X'DEADBEEF', 5,
486
'text2', 2.2, X'BEEFCAFE', 9, 'text3'
487
);
488
`);
489
t.assert.strictEqual(setup, undefined);
490
491
const query = db.prepare('SELECT * FROM wide_table');
492
query.setReturnArrays(true);
493
494
const results = query.all();
495
t.assert.strictEqual(results.length, 1);
496
t.assert.deepStrictEqual(results[0], expected);
497
});
498
});
499
500
suite('StatementSync.prototype.iterate() with array output', () => {
501
test('iterates array rows when setReturnArrays is true', (t) => {
502
const db = new DatabaseSync(nextDb());
503
t.after(() => { db.close(); });
504
const setup = db.exec(`
505
CREATE TABLE data(key INTEGER PRIMARY KEY, val TEXT) STRICT;
506
INSERT INTO data (key, val) VALUES (1, 'one');
507
INSERT INTO data (key, val) VALUES (2, 'two');
508
`);
509
t.assert.strictEqual(setup, undefined);
510
511
const query = db.prepare('SELECT key, val FROM data ORDER BY key');
512
513
// Test with objects first
514
const objectRows = [];
515
for (const row of query.iterate()) {
516
objectRows.push(row);
517
}
518
t.assert.deepStrictEqual(objectRows, [
519
{ __proto__: null, key: 1, val: 'one' },
520
{ __proto__: null, key: 2, val: 'two' },
521
]);
522
523
// Test with arrays
524
query.setReturnArrays(true);
525
const arrayRows = [];
526
for (const row of query.iterate()) {
527
arrayRows.push(row);
528
}
529
t.assert.deepStrictEqual(arrayRows, [
530
[1, 'one'],
531
[2, 'two'],
532
]);
533
534
// Test toArray() method
535
t.assert.deepStrictEqual(query.iterate().toArray(), [
536
[1, 'one'],
537
[2, 'two'],
538
]);
539
});
540
541
test('iterator can be exited early with array rows', (t) => {
542
const db = new DatabaseSync(':memory:');
543
db.exec(`
544
CREATE TABLE test(key TEXT, val TEXT);
545
INSERT INTO test (key, val) VALUES ('key1', 'val1');
546
INSERT INTO test (key, val) VALUES ('key2', 'val2');
547
`);
548
const stmt = db.prepare('SELECT key, val FROM test');
549
stmt.setReturnArrays(true);
550
551
const iterator = stmt.iterate();
552
const results = [];
553
554
for (const item of iterator) {
555
results.push(item);
556
break;
557
}
558
559
t.assert.deepStrictEqual(results, [
560
['key1', 'val1'],
561
]);
562
t.assert.deepStrictEqual(
563
iterator.next(),
564
{ __proto__: null, done: true, value: null },
565
);
566
});
567
});
568
Aug 12, 2024
Aug 12, 2024
569
suite('StatementSync.prototype.setAllowBareNamedParameters()', () => {
570
test('bare named parameter support can be toggled', (t) => {
571
const db = new DatabaseSync(nextDb());
572
t.after(() => { db.close(); });
573
const setup = db.exec(
574
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
575
);
576
t.assert.strictEqual(setup, undefined);
577
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
578
t.assert.deepStrictEqual(
579
stmt.run({ k: 1, v: 2 }),
580
{ changes: 1, lastInsertRowid: 1 },
581
);
582
t.assert.strictEqual(stmt.setAllowBareNamedParameters(false), undefined);
583
t.assert.throws(() => {
584
stmt.run({ k: 2, v: 4 });
585
}, {
586
code: 'ERR_INVALID_STATE',
587
message: /Unknown named parameter 'k'/,
588
});
589
t.assert.strictEqual(stmt.setAllowBareNamedParameters(true), undefined);
590
t.assert.deepStrictEqual(
591
stmt.run({ k: 3, v: 6 }),
592
{ changes: 1, lastInsertRowid: 3 },
593
);
594
});
595
596
test('throws when input is not a boolean', (t) => {
597
const db = new DatabaseSync(nextDb());
598
t.after(() => { db.close(); });
599
const setup = db.exec(
600
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
601
);
602
t.assert.strictEqual(setup, undefined);
603
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
604
t.assert.throws(() => {
605
stmt.setAllowBareNamedParameters();
606
}, {
607
code: 'ERR_INVALID_ARG_TYPE',
608
message: /The "allowBareNamedParameters" argument must be a boolean/,
609
});
610
});
611
});