From 751615db68723e8d145a90a2048669a2887983ca Mon Sep 17 00:00:00 2001 From: Oscar Franco Date: Sun, 18 May 2025 14:32:19 +0200 Subject: [PATCH 1/2] Add sync bind --- cpp/PreparedStatementHostObject.cpp | 21 ++++++++++++++++++++ example/src/tests/preparedStatements.spec.ts | 15 ++++++++++++++ src/index.ts | 16 +++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/cpp/PreparedStatementHostObject.cpp b/cpp/PreparedStatementHostObject.cpp index 4c744c0d..d1c06060 100644 --- a/cpp/PreparedStatementHostObject.cpp +++ b/cpp/PreparedStatementHostObject.cpp @@ -74,6 +74,27 @@ jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt, }); } + if (name == "bindSync") { + if (_stmt == nullptr) { + throw std::runtime_error("statement has been freed"); + } + + const jsi::Value &js_params = args[0]; + std::vector params = to_variant_vec(rt, js_params); + try { +#ifdef OP_SQLITE_USE_LIBSQL + opsqlite_libsql_bind_statement(_stmt, ¶ms); +#else + opsqlite_bind_statement(_stmt, ¶ms); +#endif + } catch (const std::runtime_error &e) { + throw std::runtime_error(e.what()); + } catch (const std::exception &e) { + throw std::runtime_error(e.what()); + } + return {}; + } + if (name == "execute") { return HOSTFN("execute") { if (_stmt == nullptr) { diff --git a/example/src/tests/preparedStatements.spec.ts b/example/src/tests/preparedStatements.spec.ts index be066fe3..04e053fd 100644 --- a/example/src/tests/preparedStatements.spec.ts +++ b/example/src/tests/preparedStatements.spec.ts @@ -82,5 +82,20 @@ export function preparedStatementsTests() { await statement.bind([5, 'Pedro']); await statement.execute(); }); + + it('prepared statementm, bindsync', async () => { + const statement = db.prepareStatement( + 'INSERT INTO "User" (id, name) VALUES(?,?);', + ); + statement.bindSync([4, 'Juan']); + await statement.execute(); + + statement.bind([5, 'Pedro']); + await statement.execute(); + + const selectStatement = db.prepareStatement('SELECT * FROM User;'); + let results = await selectStatement.execute(); + expect(results.rows.length).to.equal(5); + }); }); } diff --git a/src/index.ts b/src/index.ts index 263f4d5f..9f50fc00 100644 --- a/src/index.ts +++ b/src/index.ts @@ -97,6 +97,7 @@ type PendingTransaction = { export type PreparedStatement = { bind: (params: any[]) => Promise; + bindSync: (params: any[]) => void; execute: () => Promise; }; @@ -517,16 +518,15 @@ function enhanceDB(db: InternalDB, options: DBParams): DB { const stmt = db.prepareStatement(query); return { - bind: async (params: Scalar[]) => { - const sanitizedParams = params.map((p) => { - if (ArrayBuffer.isView(p)) { - return p.buffer; - } + bindSync: (params: Scalar[]) => { + const sanitizedParams = sanitizeArrayBuffersInArray(params); - return p; - }); + stmt.bindSync(sanitizedParams!); + }, + bind: async (params: Scalar[]) => { + const sanitizedParams = sanitizeArrayBuffersInArray(params); - await stmt.bind(sanitizedParams); + await stmt.bind(sanitizedParams!); }, execute: stmt.execute, }; From c843f2bb8bee9b61740b7e8eb16f14c28c1b8101 Mon Sep 17 00:00:00 2001 From: Oscar Franco Date: Sun, 18 May 2025 14:43:36 +0200 Subject: [PATCH 2/2] Fix missing HOSTFN --- cpp/PreparedStatementHostObject.cpp | 14 ++++++++------ docs/docs/api.md | 2 ++ example/ios/Podfile.lock | 2 +- example/package.json | 2 +- example/src/tests/preparedStatements.spec.ts | 3 ++- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cpp/PreparedStatementHostObject.cpp b/cpp/PreparedStatementHostObject.cpp index d1c06060..e797f167 100644 --- a/cpp/PreparedStatementHostObject.cpp +++ b/cpp/PreparedStatementHostObject.cpp @@ -75,24 +75,26 @@ jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt, } if (name == "bindSync") { + return HOSTFN("bindSync") { if (_stmt == nullptr) { - throw std::runtime_error("statement has been freed"); + throw std::runtime_error("statement has been freed"); } - + const jsi::Value &js_params = args[0]; std::vector params = to_variant_vec(rt, js_params); try { #ifdef OP_SQLITE_USE_LIBSQL - opsqlite_libsql_bind_statement(_stmt, ¶ms); + opsqlite_libsql_bind_statement(_stmt, ¶ms); #else - opsqlite_bind_statement(_stmt, ¶ms); + opsqlite_bind_statement(_stmt, ¶ms); #endif } catch (const std::runtime_error &e) { - throw std::runtime_error(e.what()); + throw std::runtime_error(e.what()); } catch (const std::exception &e) { - throw std::runtime_error(e.what()); + throw std::runtime_error(e.what()); } return {}; + }); } if (name == "execute") { diff --git a/docs/docs/api.md b/docs/docs/api.md index 1b7c1656..ea189334 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -70,6 +70,8 @@ const statement = db.prepareStatement('SELECT * FROM User WHERE name = ?;'); // bind the variables in the order they appear await statement.bind(['Oscar']); +// Or use the bindsync version +statement.bindSync(['Luis']); let results1 = await statement.execute(); await statement.bind(['Carlos']); diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 187bb1e2..ac9975a6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1785,7 +1785,7 @@ SPEC CHECKSUMS: GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4 glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 06a9c6900587420b90accc394199527c64259db4 - op-sqlite: 94ed545f045bdcc18e9daeda43467fe30a5835fe + op-sqlite: e775e8b295b1371840bf8abaa8b634fce73cf0bd RCT-Folly: bf5c0376ffe4dd2cf438dcf86db385df9fdce648 RCTDeprecation: fb7d408617e25d7f537940000d766d60149c5fea RCTRequired: 9aaf0ffcc1f41f0c671af863970ef25c422a9920 diff --git a/example/package.json b/example/package.json index a9a463e5..a9df2493 100644 --- a/example/package.json +++ b/example/package.json @@ -66,7 +66,7 @@ "node": ">=18" }, "op-sqlite": { - "libsql": true, + "libsql": false, "sqlcipher": false, "iosSqlite": false, "fts5": true, diff --git a/example/src/tests/preparedStatements.spec.ts b/example/src/tests/preparedStatements.spec.ts index 04e053fd..a4efe23f 100644 --- a/example/src/tests/preparedStatements.spec.ts +++ b/example/src/tests/preparedStatements.spec.ts @@ -83,10 +83,11 @@ export function preparedStatementsTests() { await statement.execute(); }); - it('prepared statementm, bindsync', async () => { + it('prepared statement, bindsync', async () => { const statement = db.prepareStatement( 'INSERT INTO "User" (id, name) VALUES(?,?);', ); + statement.bindSync([4, 'Juan']); await statement.execute();