Skip to content

Commit

Permalink
Merge pull request #194 from OP-Engineering/oscar/sync-execute
Browse files Browse the repository at this point in the history
Add a sync execute function
  • Loading branch information
ospfranco authored Dec 1, 2024
2 parents 01756ed + 4299476 commit 3e839fd
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 113 deletions.
130 changes: 36 additions & 94 deletions cpp/DBHostObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ namespace jsi = facebook::jsi;
namespace react = facebook::react;

#ifdef OP_SQLITE_USE_LIBSQL
void DBHostObject::flush_pending_reactive_queries(std::shared_ptr<jsi::Value> resolve) {
invoker->invokeAsync(
[this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
void DBHostObject::flush_pending_reactive_queries(
std::shared_ptr<jsi::Value> resolve) {
invoker->invokeAsync(
[this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
}
#else
void DBHostObject::flush_pending_reactive_queries(std::shared_ptr<jsi::Value> resolve) {
void DBHostObject::flush_pending_reactive_queries(
std::shared_ptr<jsi::Value> resolve) {
for (const auto &query_ptr : pending_reactive_queries) {
auto query = query_ptr.get();

Expand Down Expand Up @@ -51,9 +53,9 @@ void DBHostObject::flush_pending_reactive_queries(std::shared_ptr<jsi::Value> re
});
}
}
pending_reactive_queries.clear();

pending_reactive_queries.clear();

invoker->invokeAsync(
[this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
}
Expand Down Expand Up @@ -365,6 +367,26 @@ void DBHostObject::create_jsi_functions() {
return promise;
});

auto execute_sync = HOSTFN("executeSync") {

std::string query = args[0].asString(rt).utf8(rt);
std::vector<JSVariant> params;

if (count == 2) {
params = to_variant_vec(rt, args[1]);
}
#ifdef OP_SQLITE_USE_LIBSQL
auto status = opsqlite_libsql_execute(db_name, query, &params);
#else
auto status = opsqlite_execute(db_name, query, &params);
#endif

if (status.type != SQLiteOk) {
throw std::runtime_error(status.message);
}
return create_js_rows(rt, status);
});

auto execute = HOSTFN("execute") {
std::string query = args[0].asString(rt).utf8(rt);
std::vector<JSVariant> params;
Expand Down Expand Up @@ -835,6 +857,7 @@ void DBHostObject::create_jsi_functions() {
function_map["detach"] = std::move(detach);
function_map["close"] = std::move(close);
function_map["execute"] = std::move(execute);
function_map["executeSync"] = std::move(execute_sync);
function_map["executeRaw"] = std::move(execute_raw);
function_map["executeWithHostObjects"] = std::move(execute_with_host_objects);
function_map["delete"] = std::move(remove);
Expand Down Expand Up @@ -863,97 +886,16 @@ std::vector<jsi::PropNameID> DBHostObject::getPropertyNames(jsi::Runtime &rt) {

jsi::Value DBHostObject::get(jsi::Runtime &rt,
const jsi::PropNameID &propNameID) {

auto name = propNameID.utf8(rt);
if (name == "execute") {
return jsi::Value(rt, function_map["execute"]);
}
if (name == "flushPendingReactiveQueries") {
return jsi::Value(rt, function_map["flushPendingReactiveQueries"]);
}
if (name == "attach") {
return jsi::Value(rt, function_map["attach"]);
}
if (name == "detach") {
return jsi::Value(rt, function_map["detach"]);
}
if (name == "close") {
return jsi::Value(rt, function_map["close"]);
}
if (name == "executeRaw") {
return jsi::Value(rt, function_map["executeRaw"]);
}
if (name == "executeWithHostObjects") {
return jsi::Value(rt, function_map["executeWithHostObjects"]);
}
if (name == "delete") {
return jsi::Value(rt, function_map["delete"]);
}
if (name == "executeBatch") {
return jsi::Value(rt, function_map["executeBatch"]);
}
if (name == "prepareStatement") {
return jsi::Value(rt, function_map["prepareStatement"]);
}
if (name == "getDbPath") {
return jsi::Value(rt, function_map["getDbPath"]);
}
if (name == "sync") {
return jsi::Value(rt, function_map["sync"]);
}
#ifdef OP_SQLITE_USE_LIBSQL
if (name == "loadFile") {
return HOSTFN("loadFile") {
throw std::runtime_error("[op-sqlite] Load file not implemented");
});
}
if (name == "updateHook") {
return HOSTFN("updateHook") {
throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
});
}
if (name == "commitHook") {
return HOSTFN("commitHook") {
throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
});
}
if (name == "rollbackHook") {
return HOSTFN("rollbackHook") {
throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
});
}
if (name == "loadExtension") {
return HOSTFN("loadExtension") {
throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
});
}
if (name == "reactiveExecute") {
return HOSTFN("reactiveExecute") {
throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
if (function_map.count(name) != 1) {
return HOSTFN(name.c_str()) {
throw std::runtime_error(
"[op-sqlite] Function " + name +
" not implemented for current backend (libsql or sqlcipher)");
});
}
#else
if (name == "loadFile") {
return jsi::Value(rt, function_map["loadFile"]);
}
if (name == "updateHook") {
return jsi::Value(rt, function_map["updateHook"]);
}
if (name == "commitHook") {
return jsi::Value(rt, function_map["commitHook"]);
}
if (name == "rollbackHook") {
return jsi::Value(rt, function_map["rollbackHook"]);
}
if (name == "loadExtension") {
return jsi::Value(rt, function_map["loadExtension"]);
}
if (name == "reactiveExecute") {
return jsi::Value(rt, function_map["reactiveExecute"]);
}
#endif

return {};
return jsi::Value(rt, function_map[name]);
}

void DBHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
Expand Down
14 changes: 12 additions & 2 deletions example/ios/OPSQLiteExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
55C40F8AA9DF83E899E3CDAC /* libPods-OPSQLiteExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9241EC58491DCDC9B61B00F /* libPods-OPSQLiteExample.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
92B54B8E74B0B43081C567EF /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 2C08DBE2BF8FD676ED5D600B /* PrivacyInfo.xcprivacy */; };
AC1DF06E9759460CAA51B7B1 /* sample2.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 9218E48CFB1F478CAC374D68 /* sample2.sqlite */; };
Expand All @@ -29,6 +30,7 @@
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = OPSQLiteExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
9218E48CFB1F478CAC374D68 /* sample2.sqlite */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = sample2.sqlite; path = ../assets/sqlite/sample2.sqlite; sourceTree = "<group>"; };
96FD9FD0FC4F4540AC7A9CE6 /* sample.sqlite */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = sample.sqlite; path = ../assets/sample.sqlite; sourceTree = "<group>"; };
D9241EC58491DCDC9B61B00F /* libPods-OPSQLiteExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OPSQLiteExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand All @@ -37,6 +39,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
55C40F8AA9DF83E899E3CDAC /* libPods-OPSQLiteExample.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -61,6 +64,7 @@
isa = PBXGroup;
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
D9241EC58491DCDC9B61B00F /* libPods-OPSQLiteExample.a */,
);
name = Frameworks;
sourceTree = "<group>";
Expand Down Expand Up @@ -432,7 +436,10 @@
);
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited) ";
OTHER_CFLAGS = (
"$(inherited)",
" ",
);
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
Expand Down Expand Up @@ -519,7 +526,10 @@
"\"$(inherited)\"",
);
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_CFLAGS = "$(inherited) ";
OTHER_CFLAGS = (
"$(inherited)",
" ",
);
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
Expand Down
12 changes: 6 additions & 6 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ PODS:
- hermes-engine (0.76.1):
- hermes-engine/Pre-built (= 0.76.1)
- hermes-engine/Pre-built (0.76.1)
- op-sqlite (10.1.0):
- op-sqlite (0.0.0):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -1779,14 +1779,14 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: 1dca942403ed9342f98334bf4c3621f011aa7946
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385
FBLazyVector: 7075bb12898bc3998fd60f4b7ca422496cc2cdf7
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
fmt: 10c6e61f4be25dc963c36bd73fc7b1705fe975be
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a
hermes-engine: 46f1ffbf0297f4298862068dd4c274d4ac17a1fd
op-sqlite: 09176c1312198acd6da5847bc0003ce641b4c8f0
RCT-Folly: 045d6ecaa59d826c5736dfba0b2f4083ff8d79df
op-sqlite: 9917e5a5747fc813e42487c0cbdd2d35eaa687bb
RCT-Folly: bf5c0376ffe4dd2cf438dcf86db385df9fdce648
RCTDeprecation: fde92935b3caa6cb65cbff9fbb7d3a9867ffb259
RCTRequired: 75c6cee42d21c1530a6f204ba32ff57335d19007
RCTTypeSafety: 7e6fe47bfb693c50d4669db1a480ca5331795f5b
Expand Down
19 changes: 19 additions & 0 deletions example/src/tests/queries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,25 @@ export function queriesTests() {
// });
// }

it('executeSync', () => {
const res = db.executeSync('SELECT 1');
expect(res.rowsAffected).to.equal(0);

const id = chance.integer();
const name = chance.name();
const age = chance.integer();
const networth = chance.floating();
const res2 = db.executeSync(
'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)',
[id, name, age, networth],
);

expect(res2.rowsAffected).to.equal(1);
expect(res2.insertId).to.equal(1);
expect(res2.rows).to.eql([]);
expect(res2.rows?.length).to.equal(0);
});

it('Insert', async () => {
const id = chance.integer();
const name = chance.name();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@op-engineering/op-sqlite",
"version": "11.0.2",
"version": "0.0.0",
"description": "Next generation SQLite for React Native",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-ios.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash

yarn turbo run run:ios --cache-dir=.turbo/ios
yarn run run:ios
echo "Polling in-app server..."
node ./scripts/poll-in-app-server.js
49 changes: 44 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const {
? NativeModules.OPSQLite.getConstants()
: NativeModules.OPSQLite;

type Scalar = string | number | boolean | null | ArrayBuffer | ArrayBufferView;

/**
* Object returned by SQL Query executions {
* insertId: Represent the auto-generated row id if applicable
Expand All @@ -59,9 +61,9 @@ export type QueryResult = {
insertId?: number;
rowsAffected: number;
res?: any[];
rows: Array<Record<string, string | number | boolean | ArrayBufferLike>>;
rows: Array<Record<string, Scalar>>;
// An array of intermediate results, just values without column names
rawRows?: any[];
rawRows?: Scalar[][];
columnNames?: string[];
/**
* Query metadata, available only for select query results
Expand Down Expand Up @@ -112,7 +114,7 @@ export interface FileLoadResult extends BatchQueryResult {

export interface Transaction {
commit: () => Promise<QueryResult>;
execute: (query: string, params?: any[]) => Promise<QueryResult>;
execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
rollback: () => Promise<QueryResult>;
}

Expand Down Expand Up @@ -145,6 +147,7 @@ export type DB = {
) => void;
detach: (mainDbName: string, alias: string) => void;
transaction: (fn: (tx: Transaction) => Promise<void>) => Promise<void>;
executeSync: (query: string, params?: any[]) => QueryResult;
execute: (query: string, params?: any[]) => Promise<QueryResult>;
executeWithHostObjects: (
query: string,
Expand Down Expand Up @@ -273,9 +276,44 @@ function enhanceDB(db: DB, options: any): DB {

return result;
},
executeSync: (
query: string,
params?: Scalar[] | undefined
): QueryResult => {
const sanitizedParams = params?.map((p) => {
if (ArrayBuffer.isView(p)) {
return p.buffer;
}

return p;
});

let intermediateResult = db.executeSync(query, sanitizedParams);
let rows: any[] = [];
for (let i = 0; i < (intermediateResult.rawRows?.length ?? 0); i++) {
let row: Record<string, Scalar> = {};
let rawRow = intermediateResult.rawRows![i]!;
for (let j = 0; j < intermediateResult.columnNames!.length; j++) {
let columnName = intermediateResult.columnNames![j]!;
let value = rawRow[j]!;

row[columnName] = value;
}
rows.push(row);
}

let res = {
...intermediateResult,
rows,
};

delete res.rawRows;

return res;
},
execute: async (
query: string,
params?: any[] | undefined
params?: Scalar[] | undefined
): Promise<QueryResult> => {
const sanitizedParams = params?.map((p) => {
if (ArrayBuffer.isView(p)) {
Expand All @@ -290,9 +328,10 @@ function enhanceDB(db: DB, options: any): DB {
let rows: any[] = [];
for (let i = 0; i < (intermediateResult.rawRows?.length ?? 0); i++) {
let row: any = {};
let rawRow = intermediateResult.rawRows![i]!;
for (let j = 0; j < intermediateResult.columnNames!.length; j++) {
let columnName = intermediateResult.columnNames![j]!;
let value = intermediateResult.rawRows![i][j];
let value = rawRow[j]!;

row[columnName] = value;
}
Expand Down
Loading

0 comments on commit 3e839fd

Please sign in to comment.