mirror of
https://github.com/nodejs/node.git
synced 2025-04-29 22:40:57 +00:00

This commit allows the node:sqlite module to be used without starting Node with a CLI flag. The module is still experimental. Fixes: https://github.com/nodejs/node/issues/55854 PR-URL: https://github.com/nodejs/node/pull/55890 Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
161 lines
4.5 KiB
JavaScript
161 lines
4.5 KiB
JavaScript
'use strict';
|
|
require('../common');
|
|
const tmpdir = require('../common/tmpdir');
|
|
const { join } = require('node:path');
|
|
const { DatabaseSync } = require('node:sqlite');
|
|
const { suite, test } = require('node:test');
|
|
let cnt = 0;
|
|
|
|
tmpdir.refresh();
|
|
|
|
function nextDb() {
|
|
return join(tmpdir.path, `database-${cnt++}.db`);
|
|
}
|
|
|
|
suite('data binding and mapping', () => {
|
|
test('supported data types', (t) => {
|
|
const u8a = new TextEncoder().encode('a☃b☃c');
|
|
const db = new DatabaseSync(nextDb());
|
|
t.after(() => { db.close(); });
|
|
const setup = db.exec(`
|
|
CREATE TABLE types(
|
|
key INTEGER PRIMARY KEY,
|
|
int INTEGER,
|
|
double REAL,
|
|
text TEXT,
|
|
buf BLOB
|
|
) STRICT;
|
|
`);
|
|
t.assert.strictEqual(setup, undefined);
|
|
const stmt = db.prepare('INSERT INTO types (key, int, double, text, buf) ' +
|
|
'VALUES (?, ?, ?, ?, ?)');
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(1, 42, 3.14159, 'foo', u8a),
|
|
{ changes: 1, lastInsertRowid: 1 },
|
|
);
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(2, null, null, null, null),
|
|
{ changes: 1, lastInsertRowid: 2 }
|
|
);
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(3, Number(8), Number(2.718), String('bar'), Buffer.from('x☃y☃')),
|
|
{ changes: 1, lastInsertRowid: 3 },
|
|
);
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(4, 99n, 0xf, '', new Uint8Array()),
|
|
{ changes: 1, lastInsertRowid: 4 },
|
|
);
|
|
|
|
const query = db.prepare('SELECT * FROM types WHERE key = ?');
|
|
t.assert.deepStrictEqual(query.get(1), {
|
|
__proto__: null,
|
|
key: 1,
|
|
int: 42,
|
|
double: 3.14159,
|
|
text: 'foo',
|
|
buf: u8a,
|
|
});
|
|
t.assert.deepStrictEqual(query.get(2), {
|
|
__proto__: null,
|
|
key: 2,
|
|
int: null,
|
|
double: null,
|
|
text: null,
|
|
buf: null,
|
|
});
|
|
t.assert.deepStrictEqual(query.get(3), {
|
|
__proto__: null,
|
|
key: 3,
|
|
int: 8,
|
|
double: 2.718,
|
|
text: 'bar',
|
|
buf: new TextEncoder().encode('x☃y☃'),
|
|
});
|
|
t.assert.deepStrictEqual(query.get(4), {
|
|
__proto__: null,
|
|
key: 4,
|
|
int: 99,
|
|
double: 0xf,
|
|
text: '',
|
|
buf: new Uint8Array(),
|
|
});
|
|
});
|
|
|
|
test('unsupported data types', (t) => {
|
|
const db = new DatabaseSync(nextDb());
|
|
t.after(() => { db.close(); });
|
|
const setup = db.exec(
|
|
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
|
|
);
|
|
t.assert.strictEqual(setup, undefined);
|
|
|
|
[
|
|
undefined,
|
|
() => {},
|
|
Symbol(),
|
|
/foo/,
|
|
Promise.resolve(),
|
|
new Map(),
|
|
new Set(),
|
|
].forEach((val) => {
|
|
t.assert.throws(() => {
|
|
db.prepare('INSERT INTO types (key, val) VALUES (?, ?)').run(1, val);
|
|
}, {
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: /Provided value cannot be bound to SQLite parameter 2/,
|
|
});
|
|
});
|
|
|
|
t.assert.throws(() => {
|
|
const stmt = db.prepare('INSERT INTO types (key, val) VALUES ($k, $v)');
|
|
stmt.run({ $k: 1, $v: () => {} });
|
|
}, {
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: /Provided value cannot be bound to SQLite parameter 2/,
|
|
});
|
|
});
|
|
|
|
test('throws when binding a BigInt that is too large', (t) => {
|
|
const max = 9223372036854775807n; // Largest 64-bit signed integer value.
|
|
const db = new DatabaseSync(nextDb());
|
|
t.after(() => { db.close(); });
|
|
const setup = db.exec(
|
|
'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
|
|
);
|
|
t.assert.strictEqual(setup, undefined);
|
|
const stmt = db.prepare('INSERT INTO types (key, val) VALUES (?, ?)');
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(1, max),
|
|
{ changes: 1, lastInsertRowid: 1 },
|
|
);
|
|
t.assert.throws(() => {
|
|
stmt.run(1, max + 1n);
|
|
}, {
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: /BigInt value is too large to bind/,
|
|
});
|
|
});
|
|
|
|
test('statements are unbound on each call', (t) => {
|
|
const db = new DatabaseSync(nextDb());
|
|
t.after(() => { db.close(); });
|
|
const setup = db.exec(
|
|
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
|
|
);
|
|
t.assert.strictEqual(setup, undefined);
|
|
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(1, 5),
|
|
{ changes: 1, lastInsertRowid: 1 },
|
|
);
|
|
t.assert.deepStrictEqual(
|
|
stmt.run(),
|
|
{ changes: 1, lastInsertRowid: 2 },
|
|
);
|
|
t.assert.deepStrictEqual(
|
|
db.prepare('SELECT * FROM data ORDER BY key').all(),
|
|
[{ __proto__: null, key: 1, val: 5 }, { __proto__: null, key: 2, val: null }],
|
|
);
|
|
});
|
|
});
|