diff --git a/bindings/javascript/__test__/better-sqlite3.spec.mjs b/bindings/javascript/__test__/better-sqlite3.spec.mjs index 74a694708..c88290b53 100644 --- a/bindings/javascript/__test__/better-sqlite3.spec.mjs +++ b/bindings/javascript/__test__/better-sqlite3.spec.mjs @@ -66,9 +66,7 @@ inMemoryTest.both("Statement.get() returns undefined when no data", async (t) => t.is(result, undefined); }); -inMemoryTest.onlySqlitePasses("Statement.run() returns correct result object", async (t) => { - // run() isn't 100% compatible with better-sqlite3 - // it should return a result object, not a row object +inMemoryTest.both("Statement.run() returns correct result object", async (t) => { const db = t.context.db; db.prepare("CREATE TABLE users (name TEXT)").run(); const rows = db.prepare("INSERT INTO users (name) VALUES (?)").run("Alice"); diff --git a/bindings/javascript/__test__/sync.spec.mjs b/bindings/javascript/__test__/sync.spec.mjs index 87fe1d7d4..693388951 100644 --- a/bindings/javascript/__test__/sync.spec.mjs +++ b/bindings/javascript/__test__/sync.spec.mjs @@ -36,7 +36,7 @@ dualTest.onlySqlitePasses("Statement.prepare() error", async (t) => { }); }); -dualTest.onlySqlitePasses("Statement.run() returning rows", async (t) => { +dualTest.both("Statement.run() returning rows", async (t) => { const db = t.context.db; const stmt = db.prepare("SELECT 1"); @@ -44,7 +44,7 @@ dualTest.onlySqlitePasses("Statement.run() returning rows", async (t) => { t.is(info.changes, 0); }); -dualTest.onlySqlitePasses("Statement.run() [positional]", async (t) => { +dualTest.both("Statement.run() [positional]", async (t) => { const db = t.context.db; const stmt = db.prepare("INSERT INTO users(name, email) VALUES (?, ?)"); diff --git a/bindings/javascript/index.d.ts b/bindings/javascript/index.d.ts index 37041f67a..a57984b28 100644 --- a/bindings/javascript/index.d.ts +++ b/bindings/javascript/index.d.ts @@ -11,6 +11,10 @@ export interface OpenDatabaseOptions { export interface PragmaOptions { simple: boolean } +export interface RunResult { + changes: number + lastInsertRowid: number +} export declare class Database { memory: boolean readonly: boolean @@ -31,7 +35,7 @@ export declare class Database { export declare class Statement { source: string get(args?: Array | undefined | null): unknown - run(args?: Array | undefined | null): unknown + run(args?: Array | undefined | null): RunResult iterate(args?: Array | undefined | null): IteratorStatement all(args?: Array | undefined | null): unknown pluck(pluck?: boolean | undefined | null): void diff --git a/bindings/javascript/src/lib.rs b/bindings/javascript/src/lib.rs index a81fa93ed..ed18b5411 100644 --- a/bindings/javascript/src/lib.rs +++ b/bindings/javascript/src/lib.rs @@ -31,6 +31,12 @@ pub struct PragmaOptions { pub simple: bool, } +#[napi(object)] +pub struct RunResult { + pub changes: i64, + pub last_insert_rowid: i64, +} + #[napi(custom_finalize)] #[derive(Clone)] pub struct Database { @@ -135,7 +141,7 @@ impl Database { } } } - _ => stmt.run(env, None), + _ => stmt.run_internal(env, None), } } @@ -319,14 +325,38 @@ impl Statement { } } - // TODO: Return Info object (https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md#runbindparameters---object) #[napi] - pub fn run(&self, env: Env, args: Option>) -> napi::Result { + pub fn run(&self, env: Env, args: Option>) -> napi::Result { + self.run_and_build_info_object(|| self.run_internal(env, args)) + } + + fn run_internal(&self, env: Env, args: Option>) -> napi::Result { let stmt = self.check_and_bind(env, args)?; self.internal_all(env, stmt) } + fn run_and_build_info_object( + &self, + query_fn: impl FnOnce() -> Result, + ) -> Result { + let total_changes_before = self.database.conn.total_changes(); + + query_fn()?; + + let last_insert_rowid = self.database.conn.last_insert_rowid(); + let changes = if self.database.conn.total_changes() == total_changes_before { + 0 + } else { + self.database.conn.changes() + }; + + Ok(RunResult { + changes, + last_insert_rowid, + }) + } + #[napi] pub fn iterate( &self, diff --git a/core/lib.rs b/core/lib.rs index 7f9b8a04f..7926d1773 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -790,6 +790,10 @@ impl Connection { self.total_changes.set(prev_total_changes + nchange); } + pub fn changes(&self) -> i64 { + self.last_change.get() + } + pub fn total_changes(&self) -> i64 { self.total_changes.get() }