@op-engineering/op-sqlite 9.2.0 → 9.2.2

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.
@@ -9,13 +9,49 @@
9
9
  #include "macros.h"
10
10
  #include "utils.h"
11
11
  #include <iostream>
12
+ #include <utility>
12
13
 
13
14
  namespace opsqlite {
14
15
 
15
16
  namespace jsi = facebook::jsi;
16
17
  namespace react = facebook::react;
17
18
 
18
- #ifndef OP_SQLITE_USE_LIBSQL
19
+ #ifdef OP_SQLITE_USE_LIBSQL
20
+ void DBHostObject::flush_pending_reactive_queries() {
21
+ // intentionally left blank
22
+ }
23
+ #else
24
+ void DBHostObject::flush_pending_reactive_queries() {
25
+ for (const auto &query_ptr : pending_reactive_queries) {
26
+ auto query = query_ptr.get();
27
+
28
+ std::vector<DumbHostObject> results;
29
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
30
+ std::make_shared<std::vector<SmartHostObject>>();
31
+
32
+ auto status = opsqlite_execute_prepared_statement(db_name, query->stmt,
33
+ &results, metadata);
34
+
35
+ if (status.type == SQLiteError) {
36
+ invoker->invokeAsync(
37
+ [this, callback = query->callback, status = std::move(status)] {
38
+ auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
39
+ auto error = errorCtr.callAsConstructor(
40
+ rt, jsi::String::createFromUtf8(rt, status.message));
41
+ callback->asObject(rt).asFunction(rt).call(rt, error);
42
+ });
43
+ } else {
44
+ invoker->invokeAsync(
45
+ [this,
46
+ results = std::make_shared<std::vector<DumbHostObject>>(results),
47
+ callback = query->callback, metadata, status = std::move(status)] {
48
+ auto jsiResult = createResult(rt, status, results.get(), metadata);
49
+ callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
50
+ });
51
+ }
52
+ }
53
+ }
54
+
19
55
  void DBHostObject::auto_register_update_hook() {
20
56
  if (update_hook_callback == nullptr && reactive_queries.empty() &&
21
57
  is_update_hook_registered) {
@@ -31,19 +67,17 @@ void DBHostObject::auto_register_update_hook() {
31
67
  auto hook = [this](std::string name, std::string table_name,
32
68
  std::string operation, int rowid) {
33
69
  if (update_hook_callback != nullptr) {
34
- jsCallInvoker->invokeAsync(
35
- [this,
36
- callback = update_hook_callback, table_name,
37
- operation = std::move(operation), rowid] {
38
- auto res = jsi::Object(rt);
39
- res.setProperty(rt, "table",
40
- jsi::String::createFromUtf8(rt, table_name));
41
- res.setProperty(rt, "operation",
42
- jsi::String::createFromUtf8(rt, operation));
43
- res.setProperty(rt, "rowId", jsi::Value(rowid));
44
-
45
- callback->asObject(rt).asFunction(rt).call(rt, res);
46
- });
70
+ invoker->invokeAsync([this, callback = update_hook_callback, table_name,
71
+ operation = std::move(operation), rowid] {
72
+ auto res = jsi::Object(rt);
73
+ res.setProperty(rt, "table",
74
+ jsi::String::createFromUtf8(rt, table_name));
75
+ res.setProperty(rt, "operation",
76
+ jsi::String::createFromUtf8(rt, operation));
77
+ res.setProperty(rt, "rowId", jsi::Value(rowid));
78
+
79
+ callback->asObject(rt).asFunction(rt).call(rt, res);
80
+ });
47
81
  }
48
82
 
49
83
  for (const auto &query_ptr : reactive_queries) {
@@ -55,54 +89,28 @@ void DBHostObject::auto_register_update_hook() {
55
89
  bool shouldFire = false;
56
90
 
57
91
  for (const auto &discriminator : query->discriminators) {
92
+ // Tables don't match then skip
58
93
  if (discriminator.table != table_name) {
59
94
  continue;
60
95
  }
61
- // Table has matched
62
96
 
63
97
  // If no ids are specified, then we should fire
64
98
  if (discriminator.ids.size() == 0) {
65
99
  shouldFire = true;
66
100
  break;
67
- } else { // If ids are specified, then we should check if the rowId
68
- // matches
69
- for (const auto &discrimator_id : discriminator.ids) {
70
- if (rowid == discrimator_id) {
71
- shouldFire = true;
72
- break;
73
- }
74
- }
75
101
  }
76
- }
77
102
 
78
- if (!shouldFire) {
79
- continue;
103
+ // If ids are specified, then we should check if the rowId matches
104
+ for (const auto &discrimator_id : discriminator.ids) {
105
+ if (rowid == discrimator_id) {
106
+ shouldFire = true;
107
+ break;
108
+ }
109
+ }
80
110
  }
81
111
 
82
- std::vector<DumbHostObject> results;
83
- std::shared_ptr<std::vector<SmartHostObject>> metadata =
84
- std::make_shared<std::vector<SmartHostObject>>();
85
-
86
- auto status = opsqlite_execute_prepared_statement(db_name, query->stmt,
87
- &results, metadata);
88
-
89
- if (status.type == SQLiteError) {
90
- jsCallInvoker->invokeAsync(
91
- [this, callback = query->callback, status = std::move(status)] {
92
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
93
- auto error = errorCtr.callAsConstructor(
94
- rt, jsi::String::createFromUtf8(rt, status.message));
95
- callback->asObject(rt).asFunction(rt).call(rt, error);
96
- });
97
- } else {
98
- jsCallInvoker->invokeAsync(
99
- [this,
100
- results = std::make_shared<std::vector<DumbHostObject>>(results),
101
- callback = query->callback, metadata, status = std::move(status)] {
102
- auto jsiResult =
103
- createResult(rt, status, results.get(), metadata);
104
- callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
105
- });
112
+ if (shouldFire) {
113
+ pending_reactive_queries.insert(query_ptr);
106
114
  }
107
115
  }
108
116
  };
@@ -115,10 +123,10 @@ void DBHostObject::auto_register_update_hook() {
115
123
  #ifdef OP_SQLITE_USE_LIBSQL
116
124
  DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &url,
117
125
  std::string &auth_token,
118
- std::shared_ptr<react::CallInvoker> js_call_invoker,
126
+ std::shared_ptr<react::CallInvoker> invoker,
119
127
  std::shared_ptr<ThreadPool> thread_pool)
120
- : db_name(url), jsCallInvoker(js_call_invoker), thread_pool(thread_pool),
121
- rt(rt) {
128
+ : db_name(url), invoker(std::move(invoker)),
129
+ thread_pool(std::move(thread_pool)), rt(rt) {
122
130
  BridgeResult result = opsqlite_libsql_open_remote(url, auth_token);
123
131
 
124
132
  if (result.type == SQLiteError) {
@@ -134,8 +142,8 @@ DBHostObject::DBHostObject(jsi::Runtime &rt,
134
142
  std::string &db_name, std::string &path,
135
143
  std::string &url, std::string &auth_token,
136
144
  int sync_interval)
137
- : db_name(db_name), jsCallInvoker(invoker), thread_pool(thread_pool),
138
- rt(rt) {
145
+ : db_name(db_name), invoker(std::move(invoker)),
146
+ thread_pool(std::move(thread_pool)), rt(rt) {
139
147
  BridgeResult result =
140
148
  opsqlite_libsql_open_sync(db_name, path, url, auth_token, sync_interval);
141
149
 
@@ -149,14 +157,14 @@ DBHostObject::DBHostObject(jsi::Runtime &rt,
149
157
  #endif
150
158
 
151
159
  DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
152
- std::shared_ptr<react::CallInvoker> jsCallInvoker,
160
+ std::shared_ptr<react::CallInvoker> invoker,
153
161
  std::shared_ptr<ThreadPool> thread_pool,
154
162
  std::string &db_name, std::string &path,
155
163
  std::string &crsqlite_path,
156
164
  std::string &sqlite_vec_path,
157
165
  std::string &encryption_key)
158
- : base_path(base_path), jsCallInvoker(jsCallInvoker),
159
- thread_pool(thread_pool), db_name(db_name), rt(rt) {
166
+ : base_path(base_path), invoker(std::move(invoker)),
167
+ thread_pool(std::move(thread_pool)), db_name(db_name), rt(rt) {
160
168
 
161
169
  #ifdef OP_SQLITE_USE_SQLCIPHER
162
170
  BridgeResult result = opsqlite_open(db_name, path, crsqlite_path,
@@ -268,7 +276,7 @@ void DBHostObject::create_jsi_functions() {
268
276
  if (!location.empty()) {
269
277
  if (location == ":memory:") {
270
278
  path = ":memory:";
271
- } else if (location.rfind("/", 0) == 0) {
279
+ } else if (location.rfind('/', 0) == 0) {
272
280
  path = location;
273
281
  } else {
274
282
  path = path + "/" + location;
@@ -304,7 +312,7 @@ void DBHostObject::create_jsi_functions() {
304
312
  auto reject = std::make_shared<jsi::Value>(rt, args[1]);
305
313
 
306
314
  auto task = [&rt, this, query, params = std::move(params), resolve,
307
- reject, invoker = this->jsCallInvoker]() {
315
+ reject, invoker = this->invoker]() {
308
316
  try {
309
317
  std::vector<std::vector<JSVariant>> results;
310
318
 
@@ -367,7 +375,7 @@ void DBHostObject::create_jsi_functions() {
367
375
 
368
376
  auto task = [&rt, this, query = std::move(query),
369
377
  params = std::move(params), resolve, reject,
370
- invoker = this->jsCallInvoker]() {
378
+ invoker = this->invoker]() {
371
379
  try {
372
380
 
373
381
  #ifdef OP_SQLITE_USE_LIBSQL
@@ -429,7 +437,7 @@ void DBHostObject::create_jsi_functions() {
429
437
  auto reject = std::make_shared<jsi::Value>(rt, args[1]);
430
438
 
431
439
  auto task = [&rt, this, query, params = std::move(params), resolve,
432
- reject, invoker = this->jsCallInvoker]() {
440
+ reject, invoker = this->invoker]() {
433
441
  try {
434
442
  std::vector<DumbHostObject> results;
435
443
  std::shared_ptr<std::vector<SmartHostObject>> metadata =
@@ -525,8 +533,8 @@ void DBHostObject::create_jsi_functions() {
525
533
  return;
526
534
  }
527
535
 
528
- jsCallInvoker->invokeAsync([&rt, batchResult = std::move(batchResult),
529
- resolve, reject] {
536
+ invoker->invokeAsync([&rt, batchResult = std::move(batchResult),
537
+ resolve, reject] {
530
538
  if (batchResult.type == SQLiteOk) {
531
539
  auto res = jsi::Object(rt);
532
540
  res.setProperty(rt, "rowsAffected",
@@ -541,7 +549,7 @@ void DBHostObject::create_jsi_functions() {
541
549
  });
542
550
  } catch (std::exception &exc) {
543
551
  auto what = exc.what();
544
- jsCallInvoker->invokeAsync([&rt, what = std::move(what), reject] {
552
+ invoker->invokeAsync([&rt, what = std::move(what), reject] {
545
553
  auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
546
554
  auto error = errorCtr.callAsConstructor(
547
555
  rt, jsi::String::createFromAscii(rt, what));
@@ -585,8 +593,8 @@ void DBHostObject::create_jsi_functions() {
585
593
  try {
586
594
  const auto result = importSQLFile(db_name, sqlFileName);
587
595
 
588
- jsCallInvoker->invokeAsync([&rt, result = std::move(result), resolve,
589
- reject] {
596
+ invoker->invokeAsync([&rt, result = std::move(result), resolve,
597
+ reject] {
590
598
  if (result.type == SQLiteOk) {
591
599
  auto res = jsi::Object(rt);
592
600
  res.setProperty(rt, "rowsAffected",
@@ -602,7 +610,7 @@ void DBHostObject::create_jsi_functions() {
602
610
  });
603
611
  } catch (std::exception &exc) {
604
612
  auto what = exc.what();
605
- jsCallInvoker->invokeAsync([&rt, what = std::move(what), reject] {
613
+ invoker->invokeAsync([&rt, what = std::move(what), reject] {
606
614
  auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
607
615
  auto error = errorCtr.callAsConstructor(
608
616
  rt, jsi::String::createFromAscii(rt, what));
@@ -643,7 +651,7 @@ void DBHostObject::create_jsi_functions() {
643
651
  commit_hook_callback = callback;
644
652
 
645
653
  auto hook = [&rt, this, callback](std::string dbName) {
646
- jsCallInvoker->invokeAsync(
654
+ invoker->invokeAsync(
647
655
  [&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
648
656
  };
649
657
 
@@ -667,7 +675,7 @@ void DBHostObject::create_jsi_functions() {
667
675
  rollback_hook_callback = callback;
668
676
 
669
677
  auto hook = [&rt, this, callback](std::string db_name) {
670
- jsCallInvoker->invokeAsync(
678
+ invoker->invokeAsync(
671
679
  [&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
672
680
  };
673
681
 
@@ -772,8 +780,8 @@ void DBHostObject::create_jsi_functions() {
772
780
  sqlite3_stmt *statement = opsqlite_prepare_statement(db_name, query);
773
781
  #endif
774
782
  auto preparedStatementHostObject =
775
- std::make_shared<PreparedStatementHostObject>(
776
- db_name, statement, jsCallInvoker, thread_pool);
783
+ std::make_shared<PreparedStatementHostObject>(db_name, statement,
784
+ invoker, thread_pool);
777
785
 
778
786
  return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
779
787
  });
@@ -801,6 +809,12 @@ void DBHostObject::create_jsi_functions() {
801
809
  return jsi::String::createFromUtf8(rt, result);
802
810
  });
803
811
 
812
+ auto flush_pending_reactive_queries_js =
813
+ HOSTFN("flushPendingReactiveQueries") {
814
+ flush_pending_reactive_queries();
815
+ return {};
816
+ });
817
+
804
818
  function_map["attach"] = std::move(attach);
805
819
  function_map["detach"] = std::move(detach);
806
820
  function_map["close"] = std::move(close);
@@ -811,6 +825,8 @@ void DBHostObject::create_jsi_functions() {
811
825
  function_map["executeBatch"] = std::move(execute_batch);
812
826
  function_map["prepareStatement"] = std::move(prepare_statement);
813
827
  function_map["getDbPath"] = std::move(get_db_path);
828
+ function_map["flushPendingReactiveQueries"] =
829
+ std::move(flush_pending_reactive_queries_js);
814
830
  #ifdef OP_SQLITE_USE_LIBSQL
815
831
  function_map["sync"] = std::move(sync);
816
832
  #else
@@ -833,6 +849,12 @@ jsi::Value DBHostObject::get(jsi::Runtime &rt,
833
849
  const jsi::PropNameID &propNameID) {
834
850
 
835
851
  auto name = propNameID.utf8(rt);
852
+ if (name == "execute") {
853
+ return jsi::Value(rt, function_map["execute"]);
854
+ }
855
+ if (name == "flushPendingReactiveQueries") {
856
+ return jsi::Value(rt, function_map["flushPendingReactiveQueries"]);
857
+ }
836
858
  if (name == "attach") {
837
859
  return jsi::Value(rt, function_map["attach"]);
838
860
  }
@@ -845,9 +867,6 @@ jsi::Value DBHostObject::get(jsi::Runtime &rt,
845
867
  if (name == "executeRaw") {
846
868
  return jsi::Value(rt, function_map["executeRaw"]);
847
869
  }
848
- if (name == "execute") {
849
- return jsi::Value(rt, function_map["execute"]);
850
- }
851
870
  if (name == "executeWithHostObjects") {
852
871
  return jsi::Value(rt, function_map["executeWithHostObjects"]);
853
872
  }
@@ -4,16 +4,22 @@
4
4
  #include "sqlite3.h"
5
5
  #include "types.h"
6
6
  #include <ReactCommon/CallInvoker.h>
7
- #include <any>
8
7
  #include <jsi/jsi.h>
9
8
  #include <unordered_map>
10
9
  #include <vector>
10
+ #include <set>
11
11
 
12
12
  namespace opsqlite {
13
13
 
14
14
  namespace jsi = facebook::jsi;
15
15
  namespace react = facebook::react;
16
16
 
17
+ struct PendingReactiveInvocation {
18
+ std::string db_name;
19
+ std::string table;
20
+ std::string rowid;
21
+ };
22
+
17
23
  struct TableRowDiscriminator {
18
24
  std::string table;
19
25
  std::vector<int> ids;
@@ -29,7 +35,7 @@ class JSI_EXPORT DBHostObject : public jsi::HostObject {
29
35
  public:
30
36
  // Constructor for local databases
31
37
  DBHostObject(jsi::Runtime &rt, std::string &base_path,
32
- std::shared_ptr<react::CallInvoker> js_call_invoker,
38
+ std::shared_ptr<react::CallInvoker> invoker,
33
39
  std::shared_ptr<ThreadPool> thread_pool, std::string &db_name,
34
40
  std::string &path, std::string &crsqlite_path,
35
41
  std::string &sqlite_vec_path, std::string &encryption_key);
@@ -37,7 +43,7 @@ public:
37
43
  #ifdef OP_SQLITE_USE_LIBSQL
38
44
  // Constructor for remoteOpen, purely for remote databases
39
45
  DBHostObject(jsi::Runtime &rt, std::string &url, std::string &auth_token,
40
- std::shared_ptr<react::CallInvoker> js_call_invoker,
46
+ std::shared_ptr<react::CallInvoker> invoker,
41
47
  std::shared_ptr<ThreadPool> thread_pool);
42
48
 
43
49
  // Constructor for a local database with remote sync
@@ -55,13 +61,15 @@ public:
55
61
  ~DBHostObject();
56
62
 
57
63
  private:
64
+ std::set<std::shared_ptr<ReactiveQuery>> pending_reactive_queries;
58
65
  void auto_register_update_hook();
59
66
  void create_jsi_functions();
67
+ void flush_pending_reactive_queries();
60
68
 
61
69
  std::unordered_map<std::string, jsi::Value> function_map;
62
70
  std::string base_path;
63
71
  std::shared_ptr<jsi::Value> update_hook;
64
- std::shared_ptr<react::CallInvoker> jsCallInvoker;
72
+ std::shared_ptr<react::CallInvoker> invoker;
65
73
  std::shared_ptr<ThreadPool> thread_pool;
66
74
  std::string db_name;
67
75
  std::shared_ptr<jsi::Value> update_hook_callback;
@@ -69,6 +77,7 @@ private:
69
77
  std::shared_ptr<jsi::Value> rollback_hook_callback;
70
78
  jsi::Runtime &rt;
71
79
  std::vector<std::shared_ptr<ReactiveQuery>> reactive_queries;
80
+ std::vector<PendingReactiveInvocation> pending_reactive_invocations;
72
81
  bool is_update_hook_registered = false;
73
82
  bool invalidated = false;
74
83
  };