@op-engineering/op-sqlite 6.0.2-beta1 → 6.0.2-beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/android/CMakeLists.txt +26 -15
  2. package/android/build.gradle +10 -1
  3. package/android/cpp-adapter.cpp +4 -0
  4. package/android/jniLibs/arm64-v8a/libsql_experimental.a +0 -0
  5. package/android/jniLibs/armeabi-v7a/libsql_experimental.a +0 -0
  6. package/android/jniLibs/x86/libsql_experimental.a +0 -0
  7. package/android/jniLibs/x86_64/libsql_experimental.a +0 -0
  8. package/cpp/DBHostObject.cpp +208 -81
  9. package/cpp/DBHostObject.h +10 -5
  10. package/cpp/PreparedStatementHostObject.cpp +28 -14
  11. package/cpp/PreparedStatementHostObject.h +18 -14
  12. package/cpp/bindings.cpp +14 -12
  13. package/cpp/bindings.h +2 -0
  14. package/cpp/bridge.cpp +45 -0
  15. package/cpp/bridge.h +3 -0
  16. package/cpp/libsql/bridge.cpp +629 -0
  17. package/cpp/libsql/bridge.h +88 -0
  18. package/cpp/libsql/libsql.h +133 -0
  19. package/cpp/sqlite3.h +0 -1
  20. package/cpp/types.h +5 -0
  21. package/cpp/utils.cpp +45 -3
  22. package/cpp/utils.h +2 -3
  23. package/ios/libsql.xcframework/Info.plist +48 -0
  24. package/ios/libsql.xcframework/ios-arm64/Headers/libsql.h +133 -0
  25. package/ios/libsql.xcframework/ios-arm64/libsql_experimental.a +0 -0
  26. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/Headers/libsql.h +133 -0
  27. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/libsql_experimental.a +0 -0
  28. package/lib/commonjs/index.js +5 -2
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/module/index.js +3 -1
  31. package/lib/module/index.js.map +1 -1
  32. package/lib/typescript/src/index.d.ts +6 -2
  33. package/lib/typescript/src/index.d.ts.map +1 -1
  34. package/op-sqlite.podspec +20 -3
  35. package/package.json +1 -1
  36. package/src/index.ts +10 -3
  37. package/cpp/sqlbatchexecutor.cpp +0 -93
  38. package/cpp/sqlbatchexecutor.h +0 -30
@@ -9,6 +9,7 @@ set (BUILD_DIR ${CMAKE_SOURCE_DIR}/build)
9
9
  include_directories(
10
10
  ../cpp
11
11
  ../cpp/sqlcipher
12
+ ../cpp/libsql
12
13
  )
13
14
 
14
15
  add_definitions(
@@ -18,29 +19,18 @@ add_definitions(
18
19
  add_library(
19
20
  ${PACKAGE_NAME}
20
21
  SHARED
21
- ../cpp/bridge.cpp
22
- ../cpp/bridge.h
23
22
  ../cpp/bindings.cpp
24
- ../cpp/bindings.h
25
- ../cpp/utils.h
26
23
  ../cpp/utils.cpp
27
- ../cpp/ThreadPool.h
28
24
  ../cpp/ThreadPool.cpp
29
- ../cpp/sqlbatchexecutor.h
30
- ../cpp/sqlbatchexecutor.cpp
31
25
  ../cpp/SmartHostObject.cpp
32
- ../cpp/SmartHostObject.h
33
- ../cpp/PreparedStatementHostObject.h
34
26
  ../cpp/PreparedStatementHostObject.cpp
35
27
  ../cpp/DumbHostObject.cpp
36
- ../cpp/DumbHostObject.h
37
- ../cpp/macros.h
38
- ../cpp/types.h
28
+ ../cpp/DBHostObject.cpp
39
29
  cpp-adapter.cpp
40
30
  )
41
31
 
42
32
  if (USE_SQLCIPHER)
43
- target_sources(${PACKAGE_NAME} PRIVATE ../cpp/sqlcipher/sqlite3.h ../cpp/sqlcipher/sqlite3.c)
33
+ target_sources(${PACKAGE_NAME} PRIVATE ../cpp/sqlcipher/sqlite3.h ../cpp/sqlcipher/sqlite3.c ../cpp/bridge.cpp ../cpp/bridge.h)
44
34
 
45
35
  add_definitions(
46
36
  -DOP_SQLITE_USE_SQLCIPHER=1
@@ -49,8 +39,14 @@ if (USE_SQLCIPHER)
49
39
  )
50
40
 
51
41
  find_package(openssl REQUIRED CONFIG)
42
+ elseif (USE_LIBSQL)
43
+ target_sources(${PACKAGE_NAME} PRIVATE ../cpp/libsql/bridge.cpp)
44
+
45
+ add_definitions(
46
+ -DOP_SQLITE_USE_LIBSQL=1
47
+ )
52
48
  else()
53
- target_sources(${PACKAGE_NAME} PRIVATE ../cpp/sqlite3.h ../cpp/sqlite3.c)
49
+ target_sources(${PACKAGE_NAME} PRIVATE ../cpp/sqlite3.h ../cpp/sqlite3.c ../cpp/bridge.cpp ../cpp/bridge.h)
54
50
  endif()
55
51
 
56
52
  if (USE_CRSQLITE)
@@ -81,7 +77,22 @@ if (USE_SQLCIPHER)
81
77
  android
82
78
  openssl::crypto
83
79
  )
84
- else()
80
+ elseif (USE_LIBSQL)
81
+ cmake_path(SET LIBSQL ${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libsql_experimental.a NORMALIZE)
82
+ add_library(libsql STATIC IMPORTED)
83
+ set_target_properties(libsql PROPERTIES IMPORTED_LOCATION ${LIBSQL})
84
+
85
+ target_link_libraries(
86
+ ${PACKAGE_NAME}
87
+ ${LOG_LIB}
88
+ fbjni::fbjni
89
+ ReactAndroid::jsi
90
+ ReactAndroid::turbomodulejsijni
91
+ ReactAndroid::react_nativemodule_core
92
+ android
93
+ libsql
94
+ )
95
+ else ()
85
96
  target_link_libraries(
86
97
  ${PACKAGE_NAME}
87
98
  ${LOG_LIB}
@@ -28,6 +28,7 @@ def isNewArchitectureEnabled() {
28
28
  }
29
29
 
30
30
  def useSQLCipher = false
31
+ def useLibsql = false
31
32
  def useCRSQLite = false
32
33
  def performanceMode = "0"
33
34
  def sqliteFlags = ""
@@ -43,10 +44,13 @@ if(opsqliteConfig) {
43
44
  performanceMode = opsqliteConfig["performanceMode"] ? opsqliteConfig["performanceMode"] : ""
44
45
  sqliteFlags = opsqliteConfig["sqliteFlags"] ? opsqliteConfig["sqliteFlags"] : ""
45
46
  enableFTS5 = opsqliteConfig["fts5"]
47
+ useLibsql = opsqliteConfig["libsql"]
46
48
  }
47
49
 
48
50
  if(useSQLCipher) {
49
51
  println "[OP-SQLITE] using SQLCipher 🔒"
52
+ } else if(useLibsql) {
53
+ println "[OP-SQLITE] using libsql 📦"
50
54
  } else {
51
55
  println "[OP-SQLITE] using Vanilla SQLite"
52
56
  }
@@ -117,6 +121,10 @@ android {
117
121
  cFlags += "-DOP_SQLITE_USE_SQLCIPHER=1"
118
122
  cppFlags += "-DOP_SQLITE_USE_SQLCIPHER=1"
119
123
  }
124
+ if(useLibsql) {
125
+ cFlags += "-DOP_SQLITE_USE_LIBSQL=1"
126
+ cppFlags += "-DOP_SQLITE_USE_LIBSQL=1"
127
+ }
120
128
  if(useCRSQLite) {
121
129
  cFlags += "-DOP_SQLITE_USE_CRSQLITE=1"
122
130
  cppFlags += "-DOP_SQLITE_USE_CRSQLITE=1"
@@ -136,7 +144,8 @@ android {
136
144
  arguments "-DANDROID_STL=c++_shared",
137
145
  "-DSQLITE_FLAGS='$sqliteFlags'",
138
146
  "-DUSE_SQLCIPHER=${useSQLCipher ? 1 : 0}",
139
- "-DUSE_CRSQLITE=${useCRSQLite ? 1 : 0}"
147
+ "-DUSE_CRSQLITE=${useCRSQLite ? 1 : 0}",
148
+ "-DUSE_LIBSQL=${useLibsql ? 1 : 0}"
140
149
  abiFilters (*reactNativeArchitectures())
141
150
  }
142
151
  }
@@ -6,6 +6,10 @@
6
6
  #include <jsi/jsi.h>
7
7
  #include <typeinfo>
8
8
 
9
+ namespace jsi = facebook::jsi;
10
+ namespace react = facebook::react;
11
+ namespace jni = facebook::jni;
12
+
9
13
  // This file is not using raw jni but rather fbjni, do not change how the native
10
14
  // functions are registered
11
15
  // https://github.com/facebookincubator/fbjni/blob/main/docs/quickref.md
@@ -1,8 +1,11 @@
1
1
  #include "DBHostObject.h"
2
2
  #include "PreparedStatementHostObject.h"
3
+ #if OP_SQLITE_USE_LIBSQL
4
+ #include "libsql/bridge.h"
5
+ #else
3
6
  #include "bridge.h"
7
+ #endif
4
8
  #include "macros.h"
5
- #include "sqlbatchexecutor.h"
6
9
  #include "utils.h"
7
10
  #include <iostream>
8
11
 
@@ -11,6 +14,7 @@ namespace opsqlite {
11
14
  namespace jsi = facebook::jsi;
12
15
  namespace react = facebook::react;
13
16
 
17
+ #ifndef OP_SQLITE_USE_LIBSQL
14
18
  void DBHostObject::auto_register_update_hook() {
15
19
  if (update_hook_callback == nullptr && reactive_queries.size() == 0 &&
16
20
  has_update_hook_registered) {
@@ -61,18 +65,35 @@ void DBHostObject::auto_register_update_hook() {
61
65
  for (const auto &query_ptr : reactive_queries) {
62
66
 
63
67
  auto query = query_ptr.get();
64
- if (query->tables.size() == 0) {
68
+ if (query->discriminators.size() == 0) {
65
69
  continue;
66
70
  }
67
71
 
68
- if (std::find(query->tables.begin(), query->tables.end(), table_name) ==
69
- query->tables.end()) {
70
- continue;
72
+ bool shouldFire = false;
73
+
74
+ for (const auto &discriminator : query->discriminators) {
75
+ if (discriminator.table != table_name) {
76
+ continue;
77
+ }
78
+
79
+ // Table has matched
80
+
81
+ // If no ids are specified, then we should fire
82
+ if (discriminator.ids.size() == 0) {
83
+ shouldFire = true;
84
+ break;
85
+ } else { // If ids are specified, then we should check if the rowId
86
+ // matches
87
+ for (const auto &discrimator_id : discriminator.ids) {
88
+ if (rowId == discrimator_id) {
89
+ shouldFire = true;
90
+ break;
91
+ }
92
+ }
93
+ }
71
94
  }
72
95
 
73
- if (query->rowIds.size() > 0 &&
74
- std::find(query->rowIds.begin(), query->rowIds.end(), rowId) ==
75
- query->rowIds.end()) {
96
+ if (!shouldFire) {
76
97
  continue;
77
98
  }
78
99
 
@@ -80,8 +101,8 @@ void DBHostObject::auto_register_update_hook() {
80
101
  std::shared_ptr<std::vector<SmartHostObject>> metadata =
81
102
  std::make_shared<std::vector<SmartHostObject>>();
82
103
 
83
- auto status = opsqlite_execute(dbName, query->query, &query->args,
84
- &results, metadata);
104
+ auto status = opsqlite_execute_prepared_statement(db_name, query->stmt,
105
+ &results, metadata);
85
106
 
86
107
  if (status.type == SQLiteError) {
87
108
  jsCallInvoker->invokeAsync(
@@ -114,6 +135,7 @@ void DBHostObject::auto_register_update_hook() {
114
135
  opsqlite_register_update_hook(db_name, std::move(hook));
115
136
  has_update_hook_registered = true;
116
137
  }
138
+ #endif
117
139
 
118
140
  DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
119
141
  std::shared_ptr<react::CallInvoker> jsCallInvoker,
@@ -127,6 +149,8 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
127
149
  #ifdef OP_SQLITE_USE_SQLCIPHER
128
150
  BridgeResult result =
129
151
  opsqlite_open(db_name, path, crsqlite_path, encryption_key);
152
+ #elif OP_SQLITE_USE_LIBSQL
153
+ BridgeResult result = opsqlite_libsql_open(db_name, path);
130
154
  #else
131
155
  BridgeResult result = opsqlite_open(db_name, path, crsqlite_path);
132
156
  #endif
@@ -159,9 +183,13 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
159
183
  std::string dbName = args[0].asString(rt).utf8(rt);
160
184
  std::string databaseToAttach = args[1].asString(rt).utf8(rt);
161
185
  std::string alias = args[2].asString(rt).utf8(rt);
186
+ #ifdef OP_SQLITE_USE_LIBSQL
187
+ BridgeResult result =
188
+ opsqlite_libsql_attach(dbName, tempDocPath, databaseToAttach, alias);
189
+ #else
162
190
  BridgeResult result =
163
191
  opsqlite_attach(dbName, tempDocPath, databaseToAttach, alias);
164
-
192
+ #endif
165
193
  if (result.type == SQLiteError) {
166
194
  throw std::runtime_error(result.message);
167
195
  }
@@ -182,7 +210,11 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
182
210
 
183
211
  std::string dbName = args[0].asString(rt).utf8(rt);
184
212
  std::string alias = args[1].asString(rt).utf8(rt);
213
+ #ifdef OP_SQLITE_USE_LIBSQL
214
+ BridgeResult result = opsqlite_libsql_detach(dbName, alias);
215
+ #else
185
216
  BridgeResult result = opsqlite_detach(dbName, alias);
217
+ #endif
186
218
 
187
219
  if (result.type == SQLiteError) {
188
220
  throw jsi::JSError(rt, result.message.c_str());
@@ -192,7 +224,11 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
192
224
  });
193
225
 
194
226
  auto close = HOSTFN("close", 0) {
227
+ #ifdef OP_SQLITE_USE_LIBSQL
228
+ BridgeResult result = opsqlite_libsql_close(db_name);
229
+ #else
195
230
  BridgeResult result = opsqlite_close(db_name);
231
+ #endif
196
232
 
197
233
  if (result.type == SQLiteError) {
198
234
  throw jsi::JSError(rt, result.message.c_str());
@@ -224,7 +260,11 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
224
260
  }
225
261
  }
226
262
 
263
+ #ifdef OP_SQLITE_USE_LIBSQL
264
+ BridgeResult result = opsqlite_libsql_remove(db_name, path);
265
+ #else
227
266
  BridgeResult result = opsqlite_remove(db_name, path);
267
+ #endif
228
268
 
229
269
  if (result.type == SQLiteError) {
230
270
  throw std::runtime_error(result.message);
@@ -246,7 +286,12 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
246
286
  std::shared_ptr<std::vector<SmartHostObject>> metadata =
247
287
  std::make_shared<std::vector<SmartHostObject>>();
248
288
 
289
+ #ifdef OP_SQLITE_USE_LIBSQL
290
+ auto status =
291
+ opsqlite_libsql_execute(db_name, query, &params, &results, metadata);
292
+ #else
249
293
  auto status = opsqlite_execute(db_name, query, &params, &results, metadata);
294
+ #endif
250
295
 
251
296
  if (status.type == SQLiteError) {
252
297
  throw std::runtime_error(status.message);
@@ -266,7 +311,7 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
266
311
  }
267
312
 
268
313
  auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
269
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
314
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
270
315
  auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
271
316
  auto reject = std::make_shared<jsi::Value>(rt, args[1]);
272
317
 
@@ -275,7 +320,12 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
275
320
  try {
276
321
  std::vector<std::vector<JSVariant>> results;
277
322
 
323
+ #ifdef OP_SQLITE_USE_LIBSQL
324
+ auto status =
325
+ opsqlite_libsql_execute_raw(db_name, query, &params, &results);
326
+ #else
278
327
  auto status = opsqlite_execute_raw(db_name, query, &params, &results);
328
+ #endif
279
329
  //
280
330
  // if (invalidated) {
281
331
  // return;
@@ -308,13 +358,12 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
308
358
  thread_pool->queueWork(task);
309
359
 
310
360
  return {};
311
- }));
361
+ }));
312
362
 
313
- return promise;
363
+ return promise;
314
364
  });
315
365
 
316
366
  auto execute_async = HOSTFN("executeAsync", 2) {
317
-
318
367
  const std::string query = args[0].asString(rt).utf8(rt);
319
368
  std::vector<JSVariant> params;
320
369
 
@@ -334,9 +383,13 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
334
383
  std::vector<DumbHostObject> results;
335
384
  std::shared_ptr<std::vector<SmartHostObject>> metadata =
336
385
  std::make_shared<std::vector<SmartHostObject>>();
337
-
386
+ #ifdef OP_SQLITE_USE_LIBSQL
387
+ auto status = opsqlite_libsql_execute(db_name, query, &params,
388
+ &results, metadata);
389
+ #else
338
390
  auto status =
339
391
  opsqlite_execute(db_name, query, &params, &results, metadata);
392
+ #endif
340
393
 
341
394
  // if (invalidated) {
342
395
  // return;
@@ -391,9 +444,13 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
391
444
  }
392
445
  const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
393
446
  std::vector<BatchArguments> commands;
394
- toBatchArguments(rt, batchParams, &commands);
447
+ to_batch_arguments(rt, batchParams, &commands);
395
448
 
396
- auto batchResult = sqliteExecuteBatch(db_name, &commands);
449
+ #ifdef OP_SQLITE_USE_LIBSQL
450
+ auto batchResult = opsqlite_libsql_execute_batch(db_name, &commands);
451
+ #else
452
+ auto batchResult = opsqlite_execute_batch(db_name, &commands);
453
+ #endif
397
454
  if (batchResult.type == SQLiteOk) {
398
455
  auto res = jsi::Object(rt);
399
456
  res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
@@ -422,10 +479,10 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
422
479
  const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
423
480
 
424
481
  std::vector<BatchArguments> commands;
425
- toBatchArguments(rt, batchParams, &commands);
482
+ to_batch_arguments(rt, batchParams, &commands);
426
483
 
427
484
  auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
428
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
485
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
429
486
  auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
430
487
  auto reject = std::make_shared<jsi::Value>(rt, args[1]);
431
488
 
@@ -434,7 +491,12 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
434
491
  std::make_shared<std::vector<BatchArguments>>(commands),
435
492
  resolve, reject]() {
436
493
  try {
437
- auto batchResult = sqliteExecuteBatch(db_name, commands.get());
494
+ #ifdef OP_SQLITE_USE_LIBSQL
495
+ auto batchResult =
496
+ opsqlite_libsql_execute_batch(db_name, commands.get());
497
+ #else
498
+ auto batchResult = opsqlite_execute_batch(db_name, commands.get());
499
+ #endif
438
500
  jsCallInvoker->invokeAsync([&rt, batchResult = std::move(batchResult),
439
501
  resolve, reject] {
440
502
  if (batchResult.type == SQLiteOk) {
@@ -457,11 +519,12 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
457
519
  thread_pool->queueWork(task);
458
520
 
459
521
  return {};
460
- }));
522
+ }));
461
523
 
462
- return promise;
524
+ return promise;
463
525
  });
464
526
 
527
+ #ifndef OP_SQLITE_USE_LIBSQL
465
528
  auto load_file = HOSTFN("loadFile", 1) {
466
529
  if (sizeof(args) < 1) {
467
530
  throw std::runtime_error(
@@ -472,7 +535,8 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
472
535
  const std::string sqlFileName = args[0].asString(rt).utf8(rt);
473
536
 
474
537
  auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
475
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
538
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2)
539
+ {
476
540
  auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
477
541
  auto reject = std::make_shared<jsi::Value>(rt, args[1]);
478
542
 
@@ -503,9 +567,9 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
503
567
  };
504
568
  thread_pool->queueWork(task);
505
569
  return {};
506
- }));
570
+ }));
507
571
 
508
- return promise;
572
+ return promise;
509
573
  });
510
574
 
511
575
  auto update_hook = HOSTFN("updateHook", 1) {
@@ -566,17 +630,6 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
566
630
  return {};
567
631
  });
568
632
 
569
- auto prepare_statement = HOSTFN("prepareStatement", 1) {
570
- auto query = args[0].asString(rt).utf8(rt);
571
-
572
- sqlite3_stmt *statement = opsqlite_prepare_statement(db_name, query);
573
-
574
- auto preparedStatementHostObject =
575
- std::make_shared<PreparedStatementHostObject>(db_name, statement);
576
-
577
- return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
578
- });
579
-
580
633
  auto load_extension = HOSTFN("loadExtension", 1) {
581
634
  auto path = args[0].asString(rt).utf8(rt);
582
635
  std::string entry_point = "";
@@ -591,29 +644,6 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
591
644
  return {};
592
645
  });
593
646
 
594
- auto get_db_path = HOSTFN("getDbPath", 1) {
595
- std::string path = std::string(base_path);
596
- if (count == 1 && !args[0].isUndefined() && !args[0].isNull()) {
597
- if (!args[0].isString()) {
598
- throw std::runtime_error(
599
- "[op-sqlite][open] database location must be a string");
600
- }
601
-
602
- std::string lastPath = args[0].asString(rt).utf8(rt);
603
-
604
- if (lastPath == ":memory:") {
605
- path = ":memory:";
606
- } else if (lastPath.rfind("/", 0) == 0) {
607
- path = lastPath;
608
- } else {
609
- path = path + "/" + lastPath;
610
- }
611
- }
612
-
613
- auto result = opsqlite_get_db_path(db_name, path);
614
- return jsi::String::createFromUtf8(rt, result);
615
- });
616
-
617
647
  auto reactive_execute = HOSTFN("reactiveExecute", 0) {
618
648
  auto query = args[0].asObject(rt);
619
649
  // if (!query.hasProperty(rt, "query") || !query.hasProperty(rt, "args")
@@ -628,23 +658,47 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
628
658
 
629
659
  const std::string query_str =
630
660
  query.getProperty(rt, "query").asString(rt).utf8(rt);
631
- auto argsArray = query.getProperty(rt, "args");
632
- auto tablesArray = query.getProperty(rt, "tables");
661
+ auto js_args = query.getProperty(rt, "args");
662
+ auto js_discriminators =
663
+ query.getProperty(rt, "fireOn").asObject(rt).asArray(rt);
664
+ auto variant_args = to_variant_vec(rt, js_args);
665
+
666
+ sqlite3_stmt *stmt = opsqlite_prepare_statement(db_name, query_str);
667
+ opsqlite_bind_statement(stmt, &variant_args);
633
668
 
634
669
  auto callback =
635
670
  std::make_shared<jsi::Value>(query.getProperty(rt, "callback"));
636
671
 
637
- std::vector<JSVariant> query_args = to_variant_vec(rt, argsArray);
638
- std::vector<std::string> tables = to_string_vec(rt, tablesArray);
639
- std::vector<int> rowIds;
640
- if (query.hasProperty(rt, "rowIds")) {
641
- auto rowIdsArray = query.getProperty(rt, "rowIds");
642
- rowIds = to_int_vec(rt, rowIdsArray);
672
+ // std::vector<JSVariant> query_args = to_variant_vec(rt, argsArray);
673
+ // std::vector<std::string> tables = to_string_vec(rt, tablesArray);
674
+ // std::vector<int> rowIds;
675
+ // if (query.hasProperty(rt, "rowIds")) {
676
+ // auto rowIdsArray = query.getProperty(rt, "rowIds");
677
+ // rowIds = to_int_vec(rt, rowIdsArray);
678
+ // }
679
+
680
+ std::vector<TableRowDiscriminator> discriminators;
681
+
682
+ for (size_t i = 0; i < js_discriminators.length(rt); i++) {
683
+ auto js_discriminator =
684
+ js_discriminators.getValueAtIndex(rt, i).asObject(rt);
685
+ std::string table =
686
+ js_discriminator.getProperty(rt, "table").asString(rt).utf8(rt);
687
+ std::vector<int> ids;
688
+ if (js_discriminator.hasProperty(rt, "ids")) {
689
+ auto js_ids =
690
+ js_discriminator.getProperty(rt, "ids").asObject(rt).asArray(rt);
691
+ for (size_t j = 0; j < js_ids.length(rt); j++) {
692
+ ids.push_back(
693
+ static_cast<int>(js_ids.getValueAtIndex(rt, j).asNumber()));
694
+ }
695
+ }
696
+ discriminators.push_back({table, ids});
643
697
  }
644
698
 
645
699
  std::shared_ptr<ReactiveQuery> reactiveQuery =
646
700
  std::make_shared<ReactiveQuery>(
647
- ReactiveQuery{query_str, query_args, tables, rowIds, callback});
701
+ ReactiveQuery{stmt, discriminators, callback});
648
702
 
649
703
  reactive_queries.push_back(reactiveQuery);
650
704
 
@@ -663,6 +717,44 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
663
717
  return unsubscribe;
664
718
  });
665
719
 
720
+ #endif
721
+
722
+ auto prepare_statement = HOSTFN("prepareStatement", 1) {
723
+ auto query = args[0].asString(rt).utf8(rt);
724
+ #ifdef OP_SQLITE_USE_LIBSQL
725
+ libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db_name, query);
726
+ #else
727
+ sqlite3_stmt *statement = opsqlite_prepare_statement(db_name, query);
728
+ #endif
729
+ auto preparedStatementHostObject =
730
+ std::make_shared<PreparedStatementHostObject>(db_name, statement);
731
+
732
+ return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
733
+ });
734
+
735
+ auto get_db_path = HOSTFN("getDbPath", 1) {
736
+ std::string path = std::string(base_path);
737
+ if (count == 1 && !args[0].isUndefined() && !args[0].isNull()) {
738
+ if (!args[0].isString()) {
739
+ throw std::runtime_error(
740
+ "[op-sqlite][open] database location must be a string");
741
+ }
742
+
743
+ std::string lastPath = args[0].asString(rt).utf8(rt);
744
+
745
+ if (lastPath == ":memory:") {
746
+ path = ":memory:";
747
+ } else if (lastPath.rfind("/", 0) == 0) {
748
+ path = lastPath;
749
+ } else {
750
+ path = path + "/" + lastPath;
751
+ }
752
+ }
753
+
754
+ auto result = opsqlite_get_db_path(db_name, path);
755
+ return jsi::String::createFromUtf8(rt, result);
756
+ });
757
+
666
758
  function_map["attach"] = std::move(attach);
667
759
  function_map["detach"] = std::move(detach);
668
760
  function_map["close"] = std::move(close);
@@ -672,14 +764,16 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
672
764
  function_map["delete"] = std::move(remove);
673
765
  function_map["executeBatch"] = std::move(execute_batch);
674
766
  function_map["executeBatchAsync"] = std::move(execute_batch_async);
767
+ #ifndef OP_SQLITE_USE_LIBSQL
675
768
  function_map["loadFile"] = std::move(load_file);
676
769
  function_map["updateHook"] = std::move(update_hook);
677
770
  function_map["commitHook"] = std::move(commit_hook);
678
771
  function_map["rollbackHook"] = std::move(rollback_hook);
679
- function_map["prepareStatement"] = std::move(prepare_statement);
680
772
  function_map["loadExtension"] = std::move(load_extension);
681
- function_map["getDbPath"] = std::move(get_db_path);
682
773
  function_map["reactiveExecute"] = std::move(reactive_execute);
774
+ #endif
775
+ function_map["prepareStatement"] = std::move(prepare_statement);
776
+ function_map["getDbPath"] = std::move(get_db_path);
683
777
  };
684
778
 
685
779
  std::vector<jsi::PropNameID> DBHostObject::getPropertyNames(jsi::Runtime &rt) {
@@ -719,6 +813,44 @@ jsi::Value DBHostObject::get(jsi::Runtime &rt,
719
813
  if (name == "executeBatchAsync") {
720
814
  return jsi::Value(rt, function_map["executeBatchAsync"]);
721
815
  }
816
+ if (name == "prepareStatement") {
817
+ return jsi::Value(rt, function_map["prepareStatement"]);
818
+ }
819
+ if (name == "getDbPath") {
820
+ return jsi::Value(rt, function_map["getDbPath"]);
821
+ }
822
+ #ifdef OP_SQLITE_USE_LIBSQL
823
+ if (name == "loadFile") {
824
+ return HOSTFN("loadFile", 0) {
825
+ throw std::runtime_error("[op-sqlite] Load file not implemented");
826
+ });
827
+ }
828
+ if (name == "updateHook") {
829
+ return HOSTFN("updateHook", 0) {
830
+ throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
831
+ });
832
+ }
833
+ if (name == "commitHook") {
834
+ return HOSTFN("commitHook", 0) {
835
+ throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
836
+ });
837
+ }
838
+ if (name == "rollbackHook") {
839
+ return HOSTFN("rollbackHook", 0) {
840
+ throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
841
+ });
842
+ }
843
+ if (name == "loadExtension") {
844
+ return HOSTFN("loadExtension", 0) {
845
+ throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
846
+ });
847
+ }
848
+ if (name == "reactiveExecute") {
849
+ return HOSTFN("reactiveExecute", 0) {
850
+ throw std::runtime_error("[op-sqlite] Hooks not supported in libsql");
851
+ });
852
+ }
853
+ #else
722
854
  if (name == "loadFile") {
723
855
  return jsi::Value(rt, function_map["loadFile"]);
724
856
  }
@@ -731,25 +863,20 @@ jsi::Value DBHostObject::get(jsi::Runtime &rt,
731
863
  if (name == "rollbackHook") {
732
864
  return jsi::Value(rt, function_map["rollbackHook"]);
733
865
  }
734
- if (name == "prepareStatement") {
735
- return jsi::Value(rt, function_map["prepareStatement"]);
736
- }
737
866
  if (name == "loadExtension") {
738
867
  return jsi::Value(rt, function_map["loadExtension"]);
739
868
  }
740
- if (name == "getDbPath") {
741
- return jsi::Value(rt, function_map["getDbPath"]);
742
- }
743
869
  if (name == "reactiveExecute") {
744
870
  return jsi::Value(rt, function_map["reactiveExecute"]);
745
871
  }
872
+ #endif
746
873
 
747
874
  return {};
748
875
  }
749
876
 
750
- // void DBHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
751
- // const jsi::Value &value) {
752
- // throw std::runtime_error("You cannot write to this object!");
753
- // }
877
+ void DBHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
878
+ const jsi::Value &value) {
879
+ throw std::runtime_error("You cannot write to this object!");
880
+ }
754
881
 
755
882
  } // namespace opsqlite