GeezerVison is showing github.com — sqlite: split up large test file · nodejs/node@7f1bf1c
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +157Lines changed: 157 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Flags: --experimental-sqlite | | 2 | +'use strict'; | | 3 | +require('../common'); | | 4 | +const tmpdir = require('../common/tmpdir'); | | 5 | +const { join } = require('node:path'); | | 6 | +const { DatabaseSync } = require('node:sqlite'); | | 7 | +const { suite, test } = require('node:test'); | | 8 | +let cnt = 0; | | 9 | + | | 10 | +tmpdir.refresh(); | | 11 | + | | 12 | +function nextDb() { | | 13 | + return join(tmpdir.path, `database-${cnt++}.db`); | | 14 | +} | | 15 | + | | 16 | +suite('data binding and mapping', () => { | | 17 | + test('supported data types', (t) => { | | 18 | + const u8a = new TextEncoder().encode('a☃b☃c'); | | 19 | + const db = new DatabaseSync(nextDb()); | | 20 | + t.after(() => { db.close(); }); | | 21 | + const setup = db.exec(` | | 22 | + CREATE TABLE types( | | 23 | + key INTEGER PRIMARY KEY, | | 24 | + int INTEGER, | | 25 | + double REAL, | | 26 | + text TEXT, | | 27 | + buf BLOB | | 28 | + ) STRICT; | | 29 | + `); | | 30 | + t.assert.strictEqual(setup, undefined); | | 31 | + const stmt = db.prepare('INSERT INTO types (key, int, double, text, buf) ' + | | 32 | + 'VALUES (?, ?, ?, ?, ?)'); | | 33 | + t.assert.deepStrictEqual( | | 34 | + stmt.run(1, 42, 3.14159, 'foo', u8a), | | 35 | + { changes: 1, lastInsertRowid: 1 }, | | 36 | + ); | | 37 | + t.assert.deepStrictEqual( | | 38 | + stmt.run(2, null, null, null, null), | | 39 | + { changes: 1, lastInsertRowid: 2 } | | 40 | + ); | | 41 | + t.assert.deepStrictEqual( | | 42 | + stmt.run(3, Number(8), Number(2.718), String('bar'), Buffer.from('x☃y☃')), | | 43 | + { changes: 1, lastInsertRowid: 3 }, | | 44 | + ); | | 45 | + t.assert.deepStrictEqual( | | 46 | + stmt.run(4, 99n, 0xf, '', new Uint8Array()), | | 47 | + { changes: 1, lastInsertRowid: 4 }, | | 48 | + ); | | 49 | + | | 50 | + const query = db.prepare('SELECT * FROM types WHERE key = ?'); | | 51 | + t.assert.deepStrictEqual(query.get(1), { | | 52 | + key: 1, | | 53 | + int: 42, | | 54 | + double: 3.14159, | | 55 | + text: 'foo', | | 56 | + buf: u8a, | | 57 | + }); | | 58 | + t.assert.deepStrictEqual(query.get(2), { | | 59 | + key: 2, | | 60 | + int: null, | | 61 | + double: null, | | 62 | + text: null, | | 63 | + buf: null, | | 64 | + }); | | 65 | + t.assert.deepStrictEqual(query.get(3), { | | 66 | + key: 3, | | 67 | + int: 8, | | 68 | + double: 2.718, | | 69 | + text: 'bar', | | 70 | + buf: new TextEncoder().encode('x☃y☃'), | | 71 | + }); | | 72 | + t.assert.deepStrictEqual(query.get(4), { | | 73 | + key: 4, | | 74 | + int: 99, | | 75 | + double: 0xf, | | 76 | + text: '', | | 77 | + buf: new Uint8Array(), | | 78 | + }); | | 79 | + }); | | 80 | + | | 81 | + test('unsupported data types', (t) => { | | 82 | + const db = new DatabaseSync(nextDb()); | | 83 | + t.after(() => { db.close(); }); | | 84 | + const setup = db.exec( | | 85 | + 'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;' | | 86 | + ); | | 87 | + t.assert.strictEqual(setup, undefined); | | 88 | + | | 89 | + [ | | 90 | + undefined, | | 91 | + () => {}, | | 92 | + Symbol(), | | 93 | + /foo/, | | 94 | + Promise.resolve(), | | 95 | + new Map(), | | 96 | + new Set(), | | 97 | + ].forEach((val) => { | | 98 | + t.assert.throws(() => { | | 99 | + db.prepare('INSERT INTO types (key, val) VALUES (?, ?)').run(1, val); | | 100 | + }, { | | 101 | + code: 'ERR_INVALID_ARG_TYPE', | | 102 | + message: /Provided value cannot be bound to SQLite parameter 2/, | | 103 | + }); | | 104 | + }); | | 105 | + | | 106 | + t.assert.throws(() => { | | 107 | + const stmt = db.prepare('INSERT INTO types (key, val) VALUES ($k, $v)'); | | 108 | + stmt.run({ $k: 1, $v: () => {} }); | | 109 | + }, { | | 110 | + code: 'ERR_INVALID_ARG_TYPE', | | 111 | + message: /Provided value cannot be bound to SQLite parameter 2/, | | 112 | + }); | | 113 | + }); | | 114 | + | | 115 | + test('throws when binding a BigInt that is too large', (t) => { | | 116 | + const max = 9223372036854775807n; // Largest 64-bit signed integer value. | | 117 | + const db = new DatabaseSync(nextDb()); | | 118 | + t.after(() => { db.close(); }); | | 119 | + const setup = db.exec( | | 120 | + 'CREATE TABLE types(key INTEGER PRIMARY KEY, val INTEGER) STRICT;' | | 121 | + ); | | 122 | + t.assert.strictEqual(setup, undefined); | | 123 | + const stmt = db.prepare('INSERT INTO types (key, val) VALUES (?, ?)'); | | 124 | + t.assert.deepStrictEqual( | | 125 | + stmt.run(1, max), | | 126 | + { changes: 1, lastInsertRowid: 1 }, | | 127 | + ); | | 128 | + t.assert.throws(() => { | | 129 | + stmt.run(1, max + 1n); | | 130 | + }, { | | 131 | + code: 'ERR_INVALID_ARG_VALUE', | | 132 | + message: /BigInt value is too large to bind/, | | 133 | + }); | | 134 | + }); | | 135 | + | | 136 | + test('statements are unbound on each call', (t) => { | | 137 | + const db = new DatabaseSync(nextDb()); | | 138 | + t.after(() => { db.close(); }); | | 139 | + const setup = db.exec( | | 140 | + 'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;' | | 141 | + ); | | 142 | + t.assert.strictEqual(setup, undefined); | | 143 | + const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)'); | | 144 | + t.assert.deepStrictEqual( | | 145 | + stmt.run(1, 5), | | 146 | + { changes: 1, lastInsertRowid: 1 }, | | 147 | + ); | | 148 | + t.assert.deepStrictEqual( | | 149 | + stmt.run(), | | 150 | + { changes: 1, lastInsertRowid: 2 }, | | 151 | + ); | | 152 | + t.assert.deepStrictEqual( | | 153 | + db.prepare('SELECT * FROM data ORDER BY key').all(), | | 154 | + [{ key: 1, val: 5 }, { key: 2, val: null }], | | 155 | + ); | | 156 | + }); | | 157 | +}); |
Collapse file Copy file name to clipboard +185Lines changed: 185 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Flags: --experimental-sqlite | | 2 | +'use strict'; | | 3 | +require('../common'); | | 4 | +const tmpdir = require('../common/tmpdir'); | | 5 | +const { existsSync } = require('node:fs'); | | 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('DatabaseSync() constructor', () => { | | 18 | + test('throws if called without new', (t) => { | | 19 | + t.assert.throws(() => { | | 20 | + DatabaseSync(); | | 21 | + }, { | | 22 | + code: 'ERR_CONSTRUCT_CALL_REQUIRED', | | 23 | + message: /Cannot call constructor without `new`/, | | 24 | + }); | | 25 | + }); | | 26 | + | | 27 | + test('throws if database path is not a string', (t) => { | | 28 | + t.assert.throws(() => { | | 29 | + new DatabaseSync(); | | 30 | + }, { | | 31 | + code: 'ERR_INVALID_ARG_TYPE', | | 32 | + message: /The "path" argument must be a string/, | | 33 | + }); | | 34 | + }); | | 35 | + | | 36 | + test('throws if options is provided but is not an object', (t) => { | | 37 | + t.assert.throws(() => { | | 38 | + new DatabaseSync('foo', null); | | 39 | + }, { | | 40 | + code: 'ERR_INVALID_ARG_TYPE', | | 41 | + message: /The "options" argument must be an object/, | | 42 | + }); | | 43 | + }); | | 44 | + | | 45 | + test('throws if options.open is provided but is not a boolean', (t) => { | | 46 | + t.assert.throws(() => { | | 47 | + new DatabaseSync('foo', { open: 5 }); | | 48 | + }, { | | 49 | + code: 'ERR_INVALID_ARG_TYPE', | | 50 | + message: /The "options\.open" argument must be a boolean/, | | 51 | + }); | | 52 | + }); | | 53 | +}); | | 54 | + | | 55 | +suite('DatabaseSync.prototype.open()', () => { | | 56 | + test('opens a database connection', (t) => { | | 57 | + const dbPath = nextDb(); | | 58 | + const db = new DatabaseSync(dbPath, { open: false }); | | 59 | + t.after(() => { db.close(); }); | | 60 | + | | 61 | + t.assert.strictEqual(existsSync(dbPath), false); | | 62 | + t.assert.strictEqual(db.open(), undefined); | | 63 | + t.assert.strictEqual(existsSync(dbPath), true); | | 64 | + }); | | 65 | + | | 66 | + test('throws if database is already open', (t) => { | | 67 | + const db = new DatabaseSync(nextDb(), { open: false }); | | 68 | + t.after(() => { db.close(); }); | | 69 | + | | 70 | + db.open(); | | 71 | + t.assert.throws(() => { | | 72 | + db.open(); | | 73 | + }, { | | 74 | + code: 'ERR_INVALID_STATE', | | 75 | + message: /database is already open/, | | 76 | + }); | | 77 | + }); | | 78 | +}); | | 79 | + | | 80 | +suite('DatabaseSync.prototype.close()', () => { | | 81 | + test('closes an open database connection', (t) => { | | 82 | + const db = new DatabaseSync(nextDb()); | | 83 | + | | 84 | + t.assert.strictEqual(db.close(), undefined); | | 85 | + }); | | 86 | + | | 87 | + test('throws if database is not open', (t) => { | | 88 | + const db = new DatabaseSync(nextDb(), { open: false }); | | 89 | + | | 90 | + t.assert.throws(() => { | | 91 | + db.close(); | | 92 | + }, { | | 93 | + code: 'ERR_INVALID_STATE', | | 94 | + message: /database is not open/, | | 95 | + }); | | 96 | + }); | | 97 | +}); | | 98 | + | | 99 | +suite('DatabaseSync.prototype.prepare()', () => { | | 100 | + test('returns a prepared statement', (t) => { | | 101 | + const db = new DatabaseSync(nextDb()); | | 102 | + t.after(() => { db.close(); }); | | 103 | + const stmt = db.prepare('CREATE TABLE webstorage(key TEXT)'); | | 104 | + t.assert.ok(stmt instanceof StatementSync); | | 105 | + }); | | 106 | + | | 107 | + test('throws if database is not open', (t) => { | | 108 | + const db = new DatabaseSync(nextDb(), { open: false }); | | 109 | + | | 110 | + t.assert.throws(() => { | | 111 | + db.prepare(); | | 112 | + }, { | | 113 | + code: 'ERR_INVALID_STATE', | | 114 | + message: /database is not open/, | | 115 | + }); | | 116 | + }); | | 117 | + | | 118 | + test('throws if sql is not a string', (t) => { | | 119 | + const db = new DatabaseSync(nextDb()); | | 120 | + t.after(() => { db.close(); }); | | 121 | + | | 122 | + t.assert.throws(() => { | | 123 | + db.prepare(); | | 124 | + }, { | | 125 | + code: 'ERR_INVALID_ARG_TYPE', | | 126 | + message: /The "sql" argument must be a string/, | | 127 | + }); | | 128 | + }); | | 129 | +}); | | 130 | + | | 131 | +suite('DatabaseSync.prototype.exec()', () => { | | 132 | + test('executes SQL', (t) => { | | 133 | + const db = new DatabaseSync(nextDb()); | | 134 | + t.after(() => { db.close(); }); | | 135 | + const result = db.exec(` | | 136 | + CREATE TABLE data( | | 137 | + key INTEGER PRIMARY KEY, | | 138 | + val INTEGER | | 139 | + ) STRICT; | | 140 | + INSERT INTO data (key, val) VALUES (1, 2); | | 141 | + INSERT INTO data (key, val) VALUES (8, 9); | | 142 | + `); | | 143 | + t.assert.strictEqual(result, undefined); | | 144 | + const stmt = db.prepare('SELECT * FROM data ORDER BY key'); | | 145 | + t.assert.deepStrictEqual(stmt.all(), [ | | 146 | + { key: 1, val: 2 }, | | 147 | + { key: 8, val: 9 }, | | 148 | + ]); | | 149 | + }); | | 150 | + | | 151 | + test('reports errors from SQLite', (t) => { | | 152 | + const db = new DatabaseSync(nextDb()); | | 153 | + t.after(() => { db.close(); }); | | 154 | + | | 155 | + t.assert.throws(() => { | | 156 | + db.exec('CREATE TABLEEEE'); | | 157 | + }, { | | 158 | + code: 'ERR_SQLITE_ERROR', | | 159 | + message: /syntax error/, | | 160 | + }); | | 161 | + }); | | 162 | + | | 163 | + test('throws if database is not open', (t) => { | | 164 | + const db = new DatabaseSync(nextDb(), { open: false }); | | 165 | + | | 166 | + t.assert.throws(() => { | | 167 | + db.exec(); | | 168 | + }, { | | 169 | + code: 'ERR_INVALID_STATE', | | 170 | + message: /database is not open/, | | 171 | + }); | | 172 | + }); | | 173 | + | | 174 | + test('throws if sql is not a string', (t) => { | | 175 | + const db = new DatabaseSync(nextDb()); | | 176 | + t.after(() => { db.close(); }); | | 177 | + | | 178 | + t.assert.throws(() => { | | 179 | + db.exec(); | | 180 | + }, { | | 181 | + code: 'ERR_INVALID_ARG_TYPE', | | 182 | + message: /The "sql" argument must be a string/, | | 183 | + }); | | 184 | + }); | | 185 | +}); |
|