Skip to content

Commit abceb90

Browse files
committed
Make Statement.run() async
1 parent 36fdc2a commit abceb90

File tree

7 files changed

+59
-25
lines changed

7 files changed

+59
-25
lines changed

index.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export declare function databasePrepareSync(db: Database, sql: string): Statemen
2727
export declare function databaseSyncSync(db: Database): SyncResult
2828
/** Executes SQL in blocking mode. */
2929
export declare function databaseExecSync(db: Database, sql: string): void
30+
/** Runs a statement in blocking mode. */
31+
export declare function statementRunSync(stmt: Statement, params?: unknown | undefined | null): RunResult
3032
export declare function statementIterateSync(stmt: Statement, params?: unknown | undefined | null): RowsIterator
3133
/** SQLite `run()` result object */
3234
export interface RunResult {
@@ -148,7 +150,7 @@ export declare class Statement {
148150
*
149151
* * `params` - The parameters to bind to the statement.
150152
*/
151-
run(params?: unknown | undefined | null): RunResult
153+
run(params?: unknown | undefined | null): object
152154
/**
153155
* Executes a SQL statement and returns the first row.
154156
*

index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,14 @@ if (!nativeBinding) {
310310
throw new Error(`Failed to load native binding`)
311311
}
312312

313-
const { Database, databasePrepareSync, databaseSyncSync, databaseExecSync, Statement, statementIterateSync, RowsIterator, iteratorNextSync, Record } = nativeBinding
313+
const { Database, databasePrepareSync, databaseSyncSync, databaseExecSync, Statement, statementRunSync, statementIterateSync, RowsIterator, iteratorNextSync, Record } = nativeBinding
314314

315315
module.exports.Database = Database
316316
module.exports.databasePrepareSync = databasePrepareSync
317317
module.exports.databaseSyncSync = databaseSyncSync
318318
module.exports.databaseExecSync = databaseExecSync
319319
module.exports.Statement = Statement
320+
module.exports.statementRunSync = statementRunSync
320321
module.exports.statementIterateSync = statementIterateSync
321322
module.exports.RowsIterator = RowsIterator
322323
module.exports.iteratorNextSync = iteratorNextSync

integration-tests/tests/async.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ test.serial("Statement.run() [positional]", async (t) => {
4747
const db = t.context.db;
4848

4949
const stmt = await db.prepare("INSERT INTO users(name, email) VALUES (?, ?)");
50-
const info = stmt.run(["Carol", "carol@example.net"]);
50+
const info = await stmt.run(["Carol", "carol@example.net"]);
5151
t.is(info.changes, 1);
5252
t.is(info.lastInsertRowid, 3);
5353

@@ -253,9 +253,9 @@ test.serial("Database.transaction()", async (t) => {
253253
"INSERT INTO users(name, email) VALUES (:name, :email)"
254254
);
255255

256-
const insertMany = db.transaction((users) => {
256+
const insertMany = db.transaction(async (users) => {
257257
t.is(db.inTransaction, true);
258-
for (const user of users) insert.run(user);
258+
for (const user of users) await insert.run(user);
259259
});
260260

261261
t.is(db.inTransaction, false);
@@ -277,9 +277,9 @@ test.serial("Database.transaction().immediate()", async (t) => {
277277
const insert = await db.prepare(
278278
"INSERT INTO users(name, email) VALUES (:name, :email)"
279279
);
280-
const insertMany = db.transaction((users) => {
280+
const insertMany = db.transaction(async (users) => {
281281
t.is(db.inTransaction, true);
282-
for (const user of users) insert.run(user);
282+
for (const user of users) await insert.run(user);
283283
});
284284
t.is(db.inTransaction, false);
285285
await insertMany.immediate([

integration-tests/tests/concurrency.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ test("Concurrent writes", async (t) => {
6363

6464
const promises = [];
6565
for (let i = 0; i < 50; i++) {
66-
promises.push(stmt.run({
66+
promises.push(await stmt.run({
6767
id: generateUUID(),
6868
name: `User${i}`,
6969
email: `user${i}@example.com`
@@ -103,7 +103,7 @@ test("Concurrent reads and writes", async (t) => {
103103
const promises = [];
104104
for (let i = 0; i < 20; i++) {
105105
promises.push(readStmt.get(aliceId));
106-
writeStmt.run({
106+
await writeStmt.run({
107107
id: generateUUID(),
108108
name: `User${i}`,
109109
email: `user${i}@example.com`

promise.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ class Statement {
257257
/**
258258
* Executes the SQL statement and returns an info object.
259259
*/
260-
run(...bindParameters) {
260+
async run(...bindParameters) {
261261
try {
262-
return this.stmt.run(...bindParameters);
262+
return await this.stmt.run(...bindParameters);
263263
} catch (err) {
264264
throw convertError(err);
265265
}

src/lib.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -653,27 +653,32 @@ impl Statement {
653653
///
654654
/// * `params` - The parameters to bind to the statement.
655655
#[napi]
656-
pub fn run(&self, params: Option<napi::JsUnknown>) -> Result<RunResult> {
657-
let rt = runtime()?;
658-
rt.block_on(async move {
659-
let total_changes_before = self.conn.total_changes();
660-
let start = std::time::Instant::now();
661-
662-
let params = map_params(&self.stmt, params)?;
663-
self.stmt.run(params).await.map_err(Error::from)?;
664-
let changes = if self.conn.total_changes() == total_changes_before {
656+
pub fn run(&self, env: Env, params: Option<napi::JsUnknown>) -> Result<napi::JsObject> {
657+
self.stmt.reset();
658+
let params = map_params(&self.stmt, params)?;
659+
let total_changes_before = self.conn.total_changes();
660+
let start = std::time::Instant::now();
661+
let stmt = self.stmt.clone();
662+
let conn = self.conn.clone();
663+
664+
let future = async move {
665+
stmt.run(params).await.map_err(Error::from)?;
666+
let changes = if conn.total_changes() == total_changes_before {
665667
0
666668
} else {
667-
self.conn.changes()
669+
conn.changes()
668670
};
669-
let last_insert_row_id = self.conn.last_insert_rowid();
671+
let last_insert_row_id = conn.last_insert_rowid();
670672
let duration = start.elapsed().as_secs_f64();
671-
self.stmt.reset();
672673
Ok(RunResult {
673674
changes: changes as f64,
674675
duration,
675676
lastInsertRowid: last_insert_row_id,
676677
})
678+
};
679+
680+
env.execute_tokio_future(future, move |&mut _env, result| {
681+
Ok(result)
677682
})
678683
}
679684

@@ -866,6 +871,32 @@ impl Statement {
866871
}
867872
}
868873

874+
/// Runs a statement in blocking mode.
875+
#[napi]
876+
pub fn statement_run_sync(stmt: &Statement, params: Option<napi::JsUnknown>) -> Result<RunResult> {
877+
stmt.stmt.reset();
878+
let rt = runtime()?;
879+
rt.block_on(async move {
880+
let params = map_params(&stmt.stmt, params)?;
881+
let total_changes_before = stmt.conn.total_changes();
882+
let start = std::time::Instant::now();
883+
884+
stmt.stmt.run(params).await.map_err(Error::from)?;
885+
let changes = if stmt.conn.total_changes() == total_changes_before {
886+
0
887+
} else {
888+
stmt.conn.changes()
889+
};
890+
let last_insert_row_id = stmt.conn.last_insert_rowid();
891+
let duration = start.elapsed().as_secs_f64();
892+
Ok(RunResult {
893+
changes: changes as f64,
894+
duration,
895+
lastInsertRowid: last_insert_row_id,
896+
})
897+
})
898+
}
899+
869900
#[napi]
870901
pub fn statement_iterate_sync(
871902
stmt: &Statement,

wrapper.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
const { Database: NativeDb, databasePrepareSync, databaseSyncSync, databaseExecSync, statementIterateSync, iteratorNextSync } = require("./index.js");
3+
const { Database: NativeDb, databasePrepareSync, databaseSyncSync, databaseExecSync, statementRunSync, statementIterateSync, iteratorNextSync } = require("./index.js");
44
const SqliteError = require("./sqlite-error.js");
55
const Authorization = require("./auth");
66

@@ -263,7 +263,7 @@ class Statement {
263263
*/
264264
run(...bindParameters) {
265265
try {
266-
return this.stmt.run(...bindParameters);
266+
return statementRunSync(this.stmt, ...bindParameters);
267267
} catch (err) {
268268
throw convertError(err);
269269
}

0 commit comments

Comments
 (0)