Skip to content

Commit dbf9d40

Browse files
committed
wip
1 parent ed659be commit dbf9d40

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/node_sqlite.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2342,7 +2342,7 @@ void Statement::Run(const FunctionCallbackInfo<Value>& args) {
23422342
if (sqlite_status != SQLITE_OK) {
23432343
Isolate* isolate = env->isolate();
23442344
Local<Object> e;
2345-
if (!CreateSQLiteError(isolate, sqlite_status).ToLocal(&e)) {
2345+
if (!CreateSQLiteError(isolate, stmt->db_->Connection()).ToLocal(&e)) {
23462346
return;
23472347
}
23482348
resolver->Reject(env->context(), e);
@@ -2890,6 +2890,7 @@ void DefineAsyncInterface(Isolate* isolate,
28902890
Database::kInternalFieldCount);
28912891

28922892
SetProtoMethod(isolate, db_async_tmpl, "close", Database::Close);
2893+
SetProtoMethod(isolate, db_async_tmpl, "prepare", Database::Prepare);
28932894
SetProtoMethod(isolate, db_async_tmpl, "exec", Database::Exec);
28942895
SetConstructorFunction(context, target, "Database", db_async_tmpl);
28952896
}

test/parallel/test-sqlite-statement-async.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,72 @@ suite('Statement() constructor', () => {
2424
});
2525
});
2626
});
27+
28+
suite('Statement.prototype.run()', () => {
29+
test('executes a query and returns change metadata', async (t) => {
30+
const db = new Database(nextDb());
31+
t.after(() => { db.close(); });
32+
const setup = await db.exec(`
33+
CREATE TABLE storage(key TEXT, val TEXT);
34+
INSERT INTO storage (key, val) VALUES ('foo', 'bar');
35+
`);
36+
t.assert.strictEqual(setup, undefined);
37+
const stmt = db.prepare('SELECT * FROM storage');
38+
const r = await stmt.run();
39+
t.assert.deepStrictEqual(r, { changes: 1, lastInsertRowid: 1 });
40+
});
41+
42+
test('SQLite throws when trying to bind too many parameters', async (t) => {
43+
const db = new Database(nextDb());
44+
t.after(() => { db.close(); });
45+
const setup = await db.exec(
46+
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
47+
);
48+
t.assert.strictEqual(setup, undefined);
49+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
50+
t.assert.rejects(async () => {
51+
await stmt.run(1, 2, 3);
52+
}, {
53+
code: 'ERR_SQLITE_ERROR',
54+
message: 'column index out of range',
55+
errcode: 25,
56+
errstr: 'column index out of range',
57+
});
58+
});
59+
60+
test('SQLite defaults to NULL for unbound parameters', async (t) => {
61+
const db = new Database(nextDb());
62+
t.after(() => { db.close(); });
63+
const setup = await db.exec(
64+
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
65+
);
66+
t.assert.strictEqual(setup, undefined);
67+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES (?, ?)');
68+
await t.assert.rejects(async () => {
69+
await stmt.run(1);
70+
}, {
71+
code: 'ERR_SQLITE_ERROR',
72+
message: 'NOT NULL constraint failed: data.val',
73+
errcode: 1299,
74+
errstr: 'constraint failed',
75+
});
76+
});
77+
78+
test('returns correct metadata when using RETURNING', async (t) => {
79+
const db = new Database(':memory:');
80+
const setup = await db.exec(
81+
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER NOT NULL) STRICT;'
82+
);
83+
t.assert.strictEqual(setup, undefined);
84+
const sql = 'INSERT INTO data (key, val) VALUES ($k, $v) RETURNING key';
85+
const stmt = db.prepare(sql);
86+
let r = await stmt.run({ k: 1, v: 10 });
87+
t.assert.deepStrictEqual(r, { changes: 1, lastInsertRowid: 1 });
88+
89+
r = await stmt.run({ k: 2, v: 20 });
90+
t.assert.deepStrictEqual(r, { changes: 1, lastInsertRowid: 2 });
91+
92+
r = await stmt.run({ k: 3, v: 30 });
93+
t.assert.deepStrictEqual(r, { changes: 1, lastInsertRowid: 3 });
94+
});
95+
});

0 commit comments

Comments
 (0)