@op-engineering/op-sqlite 11.2.13 → 11.2.15

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.
@@ -19,110 +19,117 @@ namespace react = facebook::react;
19
19
  #ifdef OP_SQLITE_USE_LIBSQL
20
20
  void DBHostObject::flush_pending_reactive_queries(
21
21
  const std::shared_ptr<jsi::Value> &resolve) {
22
- invoker->invokeAsync(
23
- [this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
22
+ invoker->invokeAsync([this, resolve]() {
23
+ resolve->asObject(rt).asFunction(rt).call(rt, {});
24
+ });
24
25
  }
25
26
  #else
26
27
  void DBHostObject::flush_pending_reactive_queries(
27
28
  const std::shared_ptr<jsi::Value> &resolve) {
28
- for (const auto &query_ptr : pending_reactive_queries) {
29
- auto query = query_ptr.get();
29
+ for (const auto &query_ptr : pending_reactive_queries) {
30
+ auto query = query_ptr.get();
30
31
 
31
- std::vector<DumbHostObject> results;
32
- std::shared_ptr<std::vector<SmartHostObject>> metadata =
33
- std::make_shared<std::vector<SmartHostObject>>();
32
+ std::vector<DumbHostObject> results;
33
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
34
+ std::make_shared<std::vector<SmartHostObject>>();
34
35
 
35
- auto status = opsqlite_execute_prepared_statement(db, query->stmt, &results,
36
- metadata);
36
+ auto status = opsqlite_execute_prepared_statement(db, query->stmt,
37
+ &results, metadata);
37
38
 
38
- invoker->invokeAsync(
39
- [this, results = std::make_shared<std::vector<DumbHostObject>>(results),
40
- callback = query->callback, metadata, status = std::move(status)] {
41
- auto jsiResult = create_result(rt, status, results.get(), metadata);
42
- callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
43
- });
44
- }
39
+ invoker->invokeAsync(
40
+ [this,
41
+ results = std::make_shared<std::vector<DumbHostObject>>(results),
42
+ callback = query->callback, metadata, status = std::move(status)] {
43
+ auto jsiResult =
44
+ create_result(rt, status, results.get(), metadata);
45
+ callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
46
+ });
47
+ }
45
48
 
46
- pending_reactive_queries.clear();
49
+ pending_reactive_queries.clear();
47
50
 
48
- invoker->invokeAsync(
49
- [this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
51
+ invoker->invokeAsync([this, resolve]() {
52
+ resolve->asObject(rt).asFunction(rt).call(rt, {});
53
+ });
50
54
  }
51
55
 
52
56
  void DBHostObject::on_commit() {
53
- invoker->invokeAsync(
54
- [this] { commit_hook_callback->asObject(rt).asFunction(rt).call(rt); });
57
+ invoker->invokeAsync(
58
+ [this] { commit_hook_callback->asObject(rt).asFunction(rt).call(rt); });
55
59
  }
56
60
 
57
61
  void DBHostObject::on_rollback() {
58
- invoker->invokeAsync(
59
- [this] { rollback_hook_callback->asObject(rt).asFunction(rt).call(rt); });
62
+ invoker->invokeAsync([this] {
63
+ rollback_hook_callback->asObject(rt).asFunction(rt).call(rt);
64
+ });
60
65
  }
61
66
 
62
67
  void DBHostObject::on_update(const std::string &table,
63
68
  const std::string &operation, long long row_id) {
64
- if (update_hook_callback != nullptr) {
65
- invoker->invokeAsync(
66
- [this, callback = update_hook_callback, table, operation, row_id] {
67
- auto res = jsi::Object(rt);
68
- res.setProperty(rt, "table", jsi::String::createFromUtf8(rt, table));
69
- res.setProperty(rt, "operation",
70
- jsi::String::createFromUtf8(rt, operation));
71
- res.setProperty(rt, "rowId", jsi::Value(static_cast<double>(row_id)));
72
-
73
- callback->asObject(rt).asFunction(rt).call(rt, res);
74
- });
75
- }
76
-
77
- for (const auto &query_ptr : reactive_queries) {
78
- auto query = query_ptr.get();
79
- if (query->discriminators.empty()) {
80
- continue;
69
+ if (update_hook_callback != nullptr) {
70
+ invoker->invokeAsync(
71
+ [this, callback = update_hook_callback, table, operation, row_id] {
72
+ auto res = jsi::Object(rt);
73
+ res.setProperty(rt, "table",
74
+ jsi::String::createFromUtf8(rt, table));
75
+ res.setProperty(rt, "operation",
76
+ jsi::String::createFromUtf8(rt, operation));
77
+ res.setProperty(rt, "rowId",
78
+ jsi::Value(static_cast<double>(row_id)));
79
+
80
+ callback->asObject(rt).asFunction(rt).call(rt, res);
81
+ });
81
82
  }
82
83
 
83
- bool shouldFire = false;
84
-
85
- for (const auto &discriminator : query->discriminators) {
86
- // Tables don't match then skip
87
- if (discriminator.table != table) {
88
- continue;
89
- }
90
-
91
- // If no ids are specified, then we should fire
92
- if (discriminator.ids.empty()) {
93
- shouldFire = true;
94
- break;
95
- }
96
-
97
- // If ids are specified, then we should check if the rowId matches
98
- for (const auto &discrimator_id : discriminator.ids) {
99
- if (row_id == discrimator_id) {
100
- shouldFire = true;
101
- break;
84
+ for (const auto &query_ptr : reactive_queries) {
85
+ auto query = query_ptr.get();
86
+ if (query->discriminators.empty()) {
87
+ continue;
88
+ }
89
+
90
+ bool shouldFire = false;
91
+
92
+ for (const auto &discriminator : query->discriminators) {
93
+ // Tables don't match then skip
94
+ if (discriminator.table != table) {
95
+ continue;
96
+ }
97
+
98
+ // If no ids are specified, then we should fire
99
+ if (discriminator.ids.empty()) {
100
+ shouldFire = true;
101
+ break;
102
+ }
103
+
104
+ // If ids are specified, then we should check if the rowId matches
105
+ for (const auto &discrimator_id : discriminator.ids) {
106
+ if (row_id == discrimator_id) {
107
+ shouldFire = true;
108
+ break;
109
+ }
110
+ }
102
111
  }
103
- }
104
- }
105
112
 
106
- if (shouldFire) {
107
- pending_reactive_queries.insert(query_ptr);
113
+ if (shouldFire) {
114
+ pending_reactive_queries.insert(query_ptr);
115
+ }
108
116
  }
109
- }
110
117
  }
111
118
 
112
119
  void DBHostObject::auto_register_update_hook() {
113
- if (update_hook_callback == nullptr && reactive_queries.empty() &&
114
- is_update_hook_registered) {
115
- opsqlite_deregister_update_hook(db);
116
- is_update_hook_registered = false;
117
- return;
118
- }
119
-
120
- if (is_update_hook_registered) {
121
- return;
122
- }
123
-
124
- opsqlite_register_update_hook(db, this);
125
- is_update_hook_registered = true;
120
+ if (update_hook_callback == nullptr && reactive_queries.empty() &&
121
+ is_update_hook_registered) {
122
+ opsqlite_deregister_update_hook(db);
123
+ is_update_hook_registered = false;
124
+ return;
125
+ }
126
+
127
+ if (is_update_hook_registered) {
128
+ return;
129
+ }
130
+
131
+ opsqlite_register_update_hook(db, this);
132
+ is_update_hook_registered = true;
126
133
  }
127
134
  #endif
128
135
 
@@ -135,13 +142,11 @@ void DBHostObject::auto_register_update_hook() {
135
142
  #ifdef OP_SQLITE_USE_LIBSQL
136
143
  DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &url,
137
144
  std::string &auth_token,
138
- std::shared_ptr<react::CallInvoker> invoker
139
- )
140
- : db_name(url), invoker(std::move(invoker)),
141
- rt(rt) {
142
- db = opsqlite_libsql_open_remote(url, auth_token);
145
+ std::shared_ptr<react::CallInvoker> invoker)
146
+ : db_name(url), invoker(std::move(invoker)), rt(rt) {
147
+ db = opsqlite_libsql_open_remote(url, auth_token);
143
148
 
144
- create_jsi_functions();
149
+ create_jsi_functions();
145
150
  }
146
151
 
147
152
  DBHostObject::DBHostObject(jsi::Runtime &rt,
@@ -149,13 +154,11 @@ DBHostObject::DBHostObject(jsi::Runtime &rt,
149
154
  std::string &db_name, std::string &path,
150
155
  std::string &url, std::string &auth_token,
151
156
  int sync_interval)
152
- : db_name(db_name), invoker(std::move(invoker)),
153
- rt(rt) {
154
- db =
155
- opsqlite_libsql_open_sync(db_name, path, url, auth_token, sync_interval);
157
+ : db_name(db_name), invoker(std::move(invoker)), rt(rt) {
158
+ db = opsqlite_libsql_open_sync(db_name, path, url, auth_token,
159
+ sync_interval);
156
160
 
157
-
158
- create_jsi_functions();
161
+ create_jsi_functions();
159
162
  }
160
163
 
161
164
  #endif
@@ -168,655 +171,688 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
168
171
  std::string &encryption_key)
169
172
  : base_path(base_path), invoker(std::move(invoker)), db_name(db_name),
170
173
  rt(rt) {
171
- _thread_pool = std::make_shared<ThreadPool>();
174
+ _thread_pool = std::make_shared<ThreadPool>();
172
175
 
173
176
  #ifdef OP_SQLITE_USE_SQLCIPHER
174
- db = opsqlite_open(db_name, path, crsqlite_path,
175
- sqlite_vec_path, encryption_key);
177
+ db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path,
178
+ encryption_key);
176
179
  #elif OP_SQLITE_USE_LIBSQL
177
- db = opsqlite_libsql_open(db_name, path, crsqlite_path);
180
+ db = opsqlite_libsql_open(db_name, path, crsqlite_path);
178
181
  #else
179
- db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path);
182
+ db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path);
180
183
  #endif
181
- create_jsi_functions();
184
+ create_jsi_functions();
182
185
  };
183
186
 
184
187
  void DBHostObject::create_jsi_functions() {
185
- function_map["attach"] = HOSTFN("attach") {
186
- if (count < 3) {
187
- throw std::runtime_error(
188
- "[op-sqlite][attach] Incorrect number of arguments");
189
- }
190
- if (!args[0].isString() || !args[1].isString() || !args[2].isString()) {
191
- throw std::runtime_error(
192
- "[op-sqlite] name, database to attach and alias must be strings");
193
- }
188
+ function_map["attach"] = HOSTFN("attach") {
189
+ if (count < 3) {
190
+ throw std::runtime_error(
191
+ "[op-sqlite][attach] Incorrect number of arguments");
192
+ }
193
+ if (!args[0].isString() || !args[1].isString() || !args[2].isString()) {
194
+ throw std::runtime_error("[op-sqlite] name, database to attach and "
195
+ "alias must be strings");
196
+ }
194
197
 
195
- std::string secondary_db_path = std::string(base_path);
196
- if (count > 3) {
197
- if (!args[3].isString()) {
198
- throw std::runtime_error(
199
- "[op-sqlite][attach] database location must be a string");
200
- }
198
+ std::string secondary_db_path = std::string(base_path);
199
+ if (count > 3) {
200
+ if (!args[3].isString()) {
201
+ throw std::runtime_error(
202
+ "[op-sqlite][attach] database location must be a string");
203
+ }
201
204
 
202
- secondary_db_path += "/" + args[3].asString(rt).utf8(rt);
203
- }
205
+ secondary_db_path += "/" + args[3].asString(rt).utf8(rt);
206
+ }
204
207
 
205
- std::string main_db_name = args[0].asString(rt).utf8(rt);
206
- std::string secondary_db_name = args[1].asString(rt).utf8(rt);
207
- std::string alias = args[2].asString(rt).utf8(rt);
208
+ std::string main_db_name = args[0].asString(rt).utf8(rt);
209
+ std::string secondary_db_name = args[1].asString(rt).utf8(rt);
210
+ std::string alias = args[2].asString(rt).utf8(rt);
208
211
  #ifdef OP_SQLITE_USE_LIBSQL
209
- opsqlite_libsql_attach(
210
- db, secondary_db_path, secondary_db_name, alias);
212
+ opsqlite_libsql_attach(db, secondary_db_path, secondary_db_name, alias);
211
213
  #else
212
- opsqlite_attach(db, main_db_name, secondary_db_path, secondary_db_name,
213
- alias);
214
+ opsqlite_attach(db, main_db_name, secondary_db_path, secondary_db_name,
215
+ alias);
214
216
  #endif
215
217
 
216
- return {};
217
- });
218
+ return {};
219
+ });
218
220
 
219
- function_map["detach"] = HOSTFN("detach") {
220
- if (count < 2) {
221
- throw std::runtime_error(
222
- "[op-sqlite][detach] Incorrect number of arguments");
223
- }
224
- if (!args[0].isString() || !args[1].isString()) {
225
- throw std::runtime_error(
226
- "[op-sqlite] database name and alias must be a strings");
227
- }
221
+ function_map["detach"] = HOSTFN("detach") {
222
+ if (count < 2) {
223
+ throw std::runtime_error(
224
+ "[op-sqlite][detach] Incorrect number of arguments");
225
+ }
226
+ if (!args[0].isString() || !args[1].isString()) {
227
+ throw std::runtime_error(
228
+ "[op-sqlite] database name and alias must be a strings");
229
+ }
228
230
 
229
- std::string dbName = args[0].asString(rt).utf8(rt);
230
- std::string alias = args[1].asString(rt).utf8(rt);
231
+ std::string dbName = args[0].asString(rt).utf8(rt);
232
+ std::string alias = args[1].asString(rt).utf8(rt);
231
233
  #ifdef OP_SQLITE_USE_LIBSQL
232
- opsqlite_libsql_detach(db, alias);
234
+ opsqlite_libsql_detach(db, alias);
233
235
  #else
234
- opsqlite_detach(db, dbName, alias);
236
+ opsqlite_detach(db, dbName, alias);
235
237
  #endif
236
238
 
237
- return {};
238
- });
239
+ return {};
240
+ });
241
+
242
+ function_map["close"] = HOSTFN("close") {
243
+ invalidated = true;
239
244
 
240
- function_map["close"] = HOSTFN("close") {
241
245
  #ifdef OP_SQLITE_USE_LIBSQL
242
- opsqlite_libsql_close(db);
246
+ opsqlite_libsql_close(db);
243
247
  #else
244
- opsqlite_close(db);
248
+ opsqlite_close(db);
245
249
  #endif
246
250
 
247
- return {};
248
- });
251
+ return {};
252
+ });
249
253
 
250
- function_map["delete"] = HOSTFN("delete") {
251
- std::string path = std::string(base_path);
254
+ function_map["delete"] = HOSTFN("delete") {
255
+ invalidated = true;
252
256
 
253
- if (count == 1) {
254
- if (!args[1].isString()) {
255
- throw std::runtime_error(
256
- "[op-sqlite][open] database location must be a string");
257
- }
257
+ std::string path = std::string(base_path);
258
258
 
259
- std::string location = args[1].asString(rt).utf8(rt);
259
+ if (count == 1) {
260
+ if (!args[1].isString()) {
261
+ throw std::runtime_error(
262
+ "[op-sqlite][open] database location must be a string");
263
+ }
260
264
 
261
- if (!location.empty()) {
262
- if (location == ":memory:") {
263
- path = ":memory:";
264
- } else if (location.rfind('/', 0) == 0) {
265
- path = location;
266
- } else {
267
- path = path + "/" + location;
265
+ std::string location = args[1].asString(rt).utf8(rt);
266
+
267
+ if (!location.empty()) {
268
+ if (location == ":memory:") {
269
+ path = ":memory:";
270
+ } else if (location.rfind('/', 0) == 0) {
271
+ path = location;
272
+ } else {
273
+ path = path + "/" + location;
274
+ }
275
+ }
268
276
  }
269
- }
270
- }
271
277
 
272
278
  #ifdef OP_SQLITE_USE_LIBSQL
273
- opsqlite_libsql_remove(db, db_name, path);
279
+ opsqlite_libsql_remove(db, db_name, path);
274
280
  #else
275
- opsqlite_remove(db, db_name, path);
281
+ opsqlite_remove(db, db_name, path);
276
282
  #endif
277
283
 
278
- return {};
279
- });
284
+ return {};
285
+ });
280
286
 
281
- function_map["executeRaw"] = HOSTFN("executeRaw") {
282
- const std::string query = args[0].asString(rt).utf8(rt);
283
- std::vector<JSVariant> params = count == 2 && args[1].isObject()
284
- ? to_variant_vec(rt, args[1])
285
- : std::vector<JSVariant>();
287
+ function_map["executeRaw"] = HOSTFN("executeRaw") {
288
+ const std::string query = args[0].asString(rt).utf8(rt);
289
+ std::vector<JSVariant> params = count == 2 && args[1].isObject()
290
+ ? to_variant_vec(rt, args[1])
291
+ : std::vector<JSVariant>();
286
292
 
287
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
293
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
288
294
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
289
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
290
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
295
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
296
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
291
297
 
292
- auto task = [this, &rt, query, params, resolve, reject]() {
293
- try {
294
- std::vector<std::vector<JSVariant>> results;
298
+ auto task = [this, &rt, query, params, resolve, reject]() {
299
+ try {
300
+ std::vector<std::vector<JSVariant>> results;
295
301
 
296
302
  #ifdef OP_SQLITE_USE_LIBSQL
297
- auto status =
298
- opsqlite_libsql_execute_raw(db, query, &params, &results);
303
+ auto status = opsqlite_libsql_execute_raw(
304
+ db, query, &params, &results);
299
305
  #else
300
- auto status = opsqlite_execute_raw(db, query, &params, &results);
306
+ auto status =
307
+ opsqlite_execute_raw(db, query, &params, &results);
301
308
  #endif
302
309
 
303
- if (invalidated) {
304
- return;
305
- }
306
-
307
- invoker->invokeAsync([&rt, results = std::move(results),
308
- status = std::move(status), resolve, reject] {
309
- auto jsiResult = create_raw_result(rt, status, &results);
310
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(jsiResult));
311
- });
312
- } catch (std::runtime_error &e) {
313
- auto what = e.what();
314
- invoker->invokeAsync([&rt, what, reject] {
315
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
316
- auto error = errorCtr.callAsConstructor(
317
- rt, jsi::String::createFromAscii(rt, what));
318
- reject->asObject(rt).asFunction(rt).call(rt, error);
319
- });
320
- } catch (std::exception &exc) {
321
- auto what = exc.what();
322
- invoker->invokeAsync([&rt, what, reject] {
323
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
324
- auto error = errorCtr.callAsConstructor(
325
- rt, jsi::String::createFromAscii(rt, what));
326
- reject->asObject(rt).asFunction(rt).call(rt, error);
327
- });
328
- }
329
- };
330
-
331
- _thread_pool->queueWork(task);
332
-
333
- return {};
310
+ if (invalidated) {
311
+ return;
312
+ }
313
+
314
+ invoker->invokeAsync([&rt, results = std::move(results),
315
+ status = std::move(status), resolve,
316
+ reject] {
317
+ auto jsiResult =
318
+ create_raw_result(rt, status, &results);
319
+ resolve->asObject(rt).asFunction(rt).call(
320
+ rt, std::move(jsiResult));
321
+ });
322
+ } catch (std::runtime_error &e) {
323
+ auto what = e.what();
324
+ invoker->invokeAsync([&rt, what, reject] {
325
+ auto errorCtr =
326
+ rt.global().getPropertyAsFunction(rt, "Error");
327
+ auto error = errorCtr.callAsConstructor(
328
+ rt, jsi::String::createFromAscii(rt, what));
329
+ reject->asObject(rt).asFunction(rt).call(rt, error);
330
+ });
331
+ } catch (std::exception &exc) {
332
+ auto what = exc.what();
333
+ invoker->invokeAsync([&rt, what, reject] {
334
+ auto errorCtr =
335
+ rt.global().getPropertyAsFunction(rt, "Error");
336
+ auto error = errorCtr.callAsConstructor(
337
+ rt, jsi::String::createFromAscii(rt, what));
338
+ reject->asObject(rt).asFunction(rt).call(rt, error);
339
+ });
340
+ }
341
+ };
342
+
343
+ _thread_pool->queueWork(task);
344
+
345
+ return {};
334
346
  }));
335
347
 
336
348
  return promise;
337
- });
349
+ });
338
350
 
339
- function_map["executeSync"] = HOSTFN("executeSync") {
340
- std::string query = args[0].asString(rt).utf8(rt);
341
- std::vector<JSVariant> params;
351
+ function_map["executeSync"] = HOSTFN("executeSync") {
352
+ std::string query = args[0].asString(rt).utf8(rt);
353
+ std::vector<JSVariant> params;
342
354
 
343
- if (count == 2) {
344
- params = to_variant_vec(rt, args[1]);
345
- }
355
+ if (count == 2) {
356
+ params = to_variant_vec(rt, args[1]);
357
+ }
346
358
  #ifdef OP_SQLITE_USE_LIBSQL
347
- auto status = opsqlite_libsql_execute(db, query, &params);
359
+ auto status = opsqlite_libsql_execute(db, query, &params);
348
360
  #else
349
- auto status = opsqlite_execute(db, query, &params);
361
+ auto status = opsqlite_execute(db, query, &params);
350
362
  #endif
351
363
 
352
- return create_js_rows(rt, status);
353
- });
364
+ return create_js_rows(rt, status);
365
+ });
354
366
 
355
- function_map["execute"] = HOSTFN("execute") {
356
- const std::string query = args[0].asString(rt).utf8(rt);
357
- std::vector<JSVariant> params = count == 2 && args[1].isObject()
358
- ? to_variant_vec(rt, args[1])
359
- : std::vector<JSVariant>();
367
+ function_map["execute"] = HOSTFN("execute") {
368
+ const std::string query = args[0].asString(rt).utf8(rt);
369
+ std::vector<JSVariant> params = count == 2 && args[1].isObject()
370
+ ? to_variant_vec(rt, args[1])
371
+ : std::vector<JSVariant>();
360
372
 
361
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
373
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
362
374
  auto promise = promiseCtr.callAsConstructor(rt,
363
375
  HOSTFN("executor") {
364
- auto task = [this, &rt, query, params,
365
- resolve = std::make_shared<jsi::Value>(rt, args[0]),
366
- reject = std::make_shared<jsi::Value>(rt, args[1])]() {
367
- try {
376
+ auto task = [this, &rt, query, params,
377
+ resolve = std::make_shared<jsi::Value>(rt, args[0]),
378
+ reject = std::make_shared<jsi::Value>(rt, args[1])]() {
379
+ try {
368
380
  #ifdef OP_SQLITE_USE_LIBSQL
369
- auto status = opsqlite_libsql_execute(db, query, &params);
381
+ auto status = opsqlite_libsql_execute(db, query, &params);
370
382
  #else
371
- auto status = opsqlite_execute(db, query, &params);
383
+ auto status = opsqlite_execute(db, query, &params);
372
384
  #endif
373
385
 
374
- if (invalidated) {
375
- return;
376
- }
377
-
378
- invoker->invokeAsync([&rt, status = std::move(status), resolve,
379
- reject] {
380
- auto jsiResult = create_js_rows(rt, status);
381
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(jsiResult));
382
- });
383
- // On Android RN is broken and does not correctly match runtime_error
384
- // to the generic exception We have to explicitly catch it
385
- // https://github.com/facebook/react-native/issues/48027
386
- } catch (std::runtime_error &e) {
387
- auto what = e.what();
388
- invoker->invokeAsync([&rt, what = std::string(what), reject] {
389
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
390
- auto error = errorCtr.callAsConstructor(
391
- rt, jsi::String::createFromAscii(rt, what));
392
- reject->asObject(rt).asFunction(rt).call(rt, error);
393
- });
394
- } catch (std::exception &exc) {
395
- auto what = exc.what();
396
- invoker->invokeAsync([&rt, what = std::string(what), reject] {
397
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
398
- auto error = errorCtr.callAsConstructor(
399
- rt, jsi::String::createFromAscii(rt, what));
400
- reject->asObject(rt).asFunction(rt).call(rt, error);
401
- });
402
- }
403
- };
404
-
405
- _thread_pool->queueWork(task);
406
-
407
- return {};
386
+ if (invalidated) {
387
+ return;
388
+ }
389
+
390
+ invoker->invokeAsync(
391
+ [&rt, status = std::move(status), resolve, reject] {
392
+ auto jsiResult = create_js_rows(rt, status);
393
+ resolve->asObject(rt).asFunction(rt).call(
394
+ rt, std::move(jsiResult));
395
+ });
396
+ // On Android RN is broken and does not correctly match
397
+ // runtime_error to the generic exception We have to
398
+ // explicitly catch it
399
+ // https://github.com/facebook/react-native/issues/48027
400
+ } catch (std::runtime_error &e) {
401
+ auto what = e.what();
402
+ invoker->invokeAsync(
403
+ [&rt, what = std::string(what), reject] {
404
+ auto errorCtr =
405
+ rt.global().getPropertyAsFunction(rt, "Error");
406
+ auto error = errorCtr.callAsConstructor(
407
+ rt, jsi::String::createFromAscii(rt, what));
408
+ reject->asObject(rt).asFunction(rt).call(rt, error);
409
+ });
410
+ } catch (std::exception &exc) {
411
+ auto what = exc.what();
412
+ invoker->invokeAsync(
413
+ [&rt, what = std::string(what), reject] {
414
+ auto errorCtr =
415
+ rt.global().getPropertyAsFunction(rt, "Error");
416
+ auto error = errorCtr.callAsConstructor(
417
+ rt, jsi::String::createFromAscii(rt, what));
418
+ reject->asObject(rt).asFunction(rt).call(rt, error);
419
+ });
420
+ }
421
+ };
422
+
423
+ _thread_pool->queueWork(task);
424
+
425
+ return {};
408
426
  }));
409
427
 
410
428
  return promise;
411
- });
429
+ });
412
430
 
413
- function_map["executeWithHostObjects"] = HOSTFN("executeWithHostObjects") {
414
- const std::string query = args[0].asString(rt).utf8(rt);
415
- std::vector<JSVariant> params;
431
+ function_map["executeWithHostObjects"] = HOSTFN("executeWithHostObjects") {
432
+ const std::string query = args[0].asString(rt).utf8(rt);
433
+ std::vector<JSVariant> params;
416
434
 
417
- if (count == 2) {
418
- const jsi::Value &originalParams = args[1];
419
- params = to_variant_vec(rt, originalParams);
420
- }
435
+ if (count == 2) {
436
+ const jsi::Value &originalParams = args[1];
437
+ params = to_variant_vec(rt, originalParams);
438
+ }
421
439
 
422
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
440
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
423
441
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
424
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
425
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
426
-
427
- auto task = [&rt, this, query, params, resolve, reject]() {
428
- try {
429
- std::vector<DumbHostObject> results;
430
- std::shared_ptr<std::vector<SmartHostObject>> metadata =
431
- std::make_shared<std::vector<SmartHostObject>>();
442
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
443
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
444
+
445
+ auto task = [&rt, this, query, params, resolve, reject]() {
446
+ try {
447
+ std::vector<DumbHostObject> results;
448
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
449
+ std::make_shared<std::vector<SmartHostObject>>();
432
450
  #ifdef OP_SQLITE_USE_LIBSQL
433
- auto status = opsqlite_libsql_execute_with_host_objects(
434
- db, query, &params, &results, metadata);
451
+ auto status = opsqlite_libsql_execute_with_host_objects(
452
+ db, query, &params, &results, metadata);
435
453
  #else
436
- auto status = opsqlite_execute_host_objects(db, query, &params,
437
- &results, metadata);
454
+ auto status = opsqlite_execute_host_objects(
455
+ db, query, &params, &results, metadata);
438
456
  #endif
439
457
 
440
- if (invalidated) {
441
- return;
442
- }
443
-
444
- invoker->invokeAsync(
445
- [&rt,
446
- results = std::make_shared<std::vector<DumbHostObject>>(results),
447
- metadata, status = std::move(status), resolve, reject] {
448
- auto jsiResult =
449
- create_result(rt, status, results.get(), metadata);
450
- resolve->asObject(rt).asFunction(rt).call(rt,
451
- std::move(jsiResult));
452
- });
453
- } catch (std::runtime_error &e) {
454
- auto what = e.what();
455
- invoker->invokeAsync([&rt, what = std::string(what), reject] {
456
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
457
- auto error = errorCtr.callAsConstructor(
458
- rt, jsi::String::createFromAscii(rt, what));
459
- reject->asObject(rt).asFunction(rt).call(rt, error);
460
- });
461
- } catch (std::exception &exc) {
462
- auto what = exc.what();
463
- invoker->invokeAsync([&rt, what, reject] {
464
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
465
- auto error = errorCtr.callAsConstructor(
466
- rt, jsi::String::createFromAscii(rt, what));
467
- reject->asObject(rt).asFunction(rt).call(rt, error);
468
- });
469
- }
470
- };
471
-
472
- _thread_pool->queueWork(task);
473
-
474
- return {};
458
+ if (invalidated) {
459
+ return;
460
+ }
461
+
462
+ invoker->invokeAsync(
463
+ [&rt,
464
+ results =
465
+ std::make_shared<std::vector<DumbHostObject>>(
466
+ results),
467
+ metadata, status = std::move(status), resolve,
468
+ reject] {
469
+ auto jsiResult = create_result(
470
+ rt, status, results.get(), metadata);
471
+ resolve->asObject(rt).asFunction(rt).call(
472
+ rt, std::move(jsiResult));
473
+ });
474
+ } catch (std::runtime_error &e) {
475
+ auto what = e.what();
476
+ invoker->invokeAsync(
477
+ [&rt, what = std::string(what), reject] {
478
+ auto errorCtr =
479
+ rt.global().getPropertyAsFunction(rt, "Error");
480
+ auto error = errorCtr.callAsConstructor(
481
+ rt, jsi::String::createFromAscii(rt, what));
482
+ reject->asObject(rt).asFunction(rt).call(rt, error);
483
+ });
484
+ } catch (std::exception &exc) {
485
+ auto what = exc.what();
486
+ invoker->invokeAsync([&rt, what, reject] {
487
+ auto errorCtr =
488
+ rt.global().getPropertyAsFunction(rt, "Error");
489
+ auto error = errorCtr.callAsConstructor(
490
+ rt, jsi::String::createFromAscii(rt, what));
491
+ reject->asObject(rt).asFunction(rt).call(rt, error);
492
+ });
493
+ }
494
+ };
495
+
496
+ _thread_pool->queueWork(task);
497
+
498
+ return {};
475
499
  }));
476
500
 
477
501
  return promise;
478
- });
502
+ });
479
503
 
480
- function_map["executeBatch"] = HOSTFN("executeBatch") {
481
- if (count < 1) {
482
- throw std::runtime_error(
483
- "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
484
- return {};
485
- }
504
+ function_map["executeBatch"] = HOSTFN("executeBatch") {
505
+ if (count < 1) {
506
+ throw std::runtime_error(
507
+ "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
508
+ }
486
509
 
487
- const jsi::Value &params = args[0];
510
+ const jsi::Value &params = args[0];
488
511
 
489
- if (params.isNull() || params.isUndefined()) {
490
- throw std::runtime_error(
491
- "[op-sqlite][executeAsyncBatch] - An array of SQL "
492
- "commands or parameters is needed");
493
- return {};
494
- }
512
+ if (params.isNull() || params.isUndefined()) {
513
+ throw std::runtime_error(
514
+ "[op-sqlite][executeAsyncBatch] - An array of SQL "
515
+ "commands or parameters is needed");
516
+ }
495
517
 
496
- const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
518
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
497
519
 
498
- std::vector<BatchArguments> commands;
499
- to_batch_arguments(rt, batchParams, &commands);
520
+ std::vector<BatchArguments> commands;
521
+ to_batch_arguments(rt, batchParams, &commands);
500
522
 
501
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
502
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
503
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
504
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
505
-
506
- auto task = [this, &rt,
507
- commands =
508
- std::make_shared<std::vector<BatchArguments>>(commands),
509
- resolve, reject]() {
510
- try {
523
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
524
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
525
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
526
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
527
+
528
+ auto task = [this, &rt, commands, resolve, reject]() {
529
+ try {
511
530
  #ifdef OP_SQLITE_USE_LIBSQL
512
- auto batchResult =
513
- opsqlite_libsql_execute_batch(db, commands.get());
531
+ auto batchResult =
532
+ opsqlite_libsql_execute_batch(db, &commands);
514
533
  #else
515
- auto batchResult = opsqlite_execute_batch(db, commands.get());
534
+ auto batchResult = opsqlite_execute_batch(db, &commands);
516
535
  #endif
517
536
 
518
- if (invalidated) {
519
- return;
520
- }
521
-
522
- invoker->invokeAsync(
523
- [&rt, batchResult = std::move(batchResult), resolve] {
524
- auto res = jsi::Object(rt);
525
- res.setProperty(rt, "rowsAffected",
526
- jsi::Value(batchResult.affectedRows));
527
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
528
- });
529
- } catch (std::runtime_error &e) {
530
- auto what = e.what();
531
- invoker->invokeAsync([&rt, what, reject] {
532
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
533
- auto error = errorCtr.callAsConstructor(
534
- rt, jsi::String::createFromAscii(rt, what));
535
- reject->asObject(rt).asFunction(rt).call(rt, error);
536
- });
537
- } catch (std::exception &exc) {
538
- auto what = exc.what();
539
- invoker->invokeAsync([&rt, what, reject] {
540
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
541
- auto error = errorCtr.callAsConstructor(
542
- rt, jsi::String::createFromAscii(rt, what));
543
- reject->asObject(rt).asFunction(rt).call(rt, error);
544
- });
545
- }
546
- };
547
- _thread_pool->queueWork(task);
548
-
549
- return {};
537
+ if (invalidated) {
538
+ return;
539
+ }
540
+
541
+ invoker->invokeAsync([&rt,
542
+ batchResult = std::move(batchResult),
543
+ resolve] {
544
+ auto res = jsi::Object(rt);
545
+ res.setProperty(rt, "rowsAffected",
546
+ jsi::Value(batchResult.affectedRows));
547
+ resolve->asObject(rt).asFunction(rt).call(
548
+ rt, std::move(res));
549
+ });
550
+ } catch (std::runtime_error &e) {
551
+ auto what = e.what();
552
+ invoker->invokeAsync([&rt, what, reject] {
553
+ auto errorCtr =
554
+ rt.global().getPropertyAsFunction(rt, "Error");
555
+ auto error = errorCtr.callAsConstructor(
556
+ rt, jsi::String::createFromAscii(rt, what));
557
+ reject->asObject(rt).asFunction(rt).call(rt, error);
558
+ });
559
+ } catch (std::exception &exc) {
560
+ auto what = exc.what();
561
+ invoker->invokeAsync([&rt, what, reject] {
562
+ auto errorCtr =
563
+ rt.global().getPropertyAsFunction(rt, "Error");
564
+ auto error = errorCtr.callAsConstructor(
565
+ rt, jsi::String::createFromAscii(rt, what));
566
+ reject->asObject(rt).asFunction(rt).call(rt, error);
567
+ });
568
+ }
569
+ };
570
+ _thread_pool->queueWork(task);
571
+
572
+ return {};
550
573
  }));
551
574
 
552
- return promise;
553
- });
575
+ return promise;
576
+ });
554
577
 
555
578
  #ifdef OP_SQLITE_USE_LIBSQL
556
- function_map["sync"] = HOSTFN("sync") {
557
- opsqlite_libsql_sync(db);
558
- return {};
559
- });
579
+ function_map["sync"] = HOSTFN("sync") {
580
+ opsqlite_libsql_sync(db);
581
+ return {};
582
+ });
560
583
  #else
561
- function_map["loadFile"] = HOSTFN("loadFile") {
562
- if (count < 1) {
563
- throw std::runtime_error(
564
- "[op-sqlite][loadFile] Incorrect parameter count");
565
- return {};
566
- }
584
+ function_map["loadFile"] = HOSTFN("loadFile") {
585
+ if (count < 1) {
586
+ throw std::runtime_error(
587
+ "[op-sqlite][loadFile] Incorrect parameter count");
588
+ return {};
589
+ }
567
590
 
568
- const std::string sqlFileName = args[0].asString(rt).utf8(rt);
591
+ const std::string sqlFileName = args[0].asString(rt).utf8(rt);
569
592
 
570
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
593
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
571
594
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
572
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
573
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
574
-
575
- auto task = [&rt, this, sqlFileName, resolve, reject]() {
576
- try {
577
- const auto result = import_sql_file(db, sqlFileName);
578
-
579
- invoker->invokeAsync([&rt, result, resolve] {
580
- auto res = jsi::Object(rt);
581
- res.setProperty(rt, "rowsAffected",
582
- jsi::Value(result.affectedRows));
583
- res.setProperty(rt, "commands", jsi::Value(result.commands));
584
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
585
- });
586
- } catch (std::runtime_error &e) {
587
- auto what = e.what();
588
- invoker->invokeAsync([&rt, what = std::string(what), reject] {
589
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
590
- auto error = errorCtr.callAsConstructor(
591
- rt, jsi::String::createFromAscii(rt, what));
592
- reject->asObject(rt).asFunction(rt).call(rt, error);
593
- });
594
- } catch (std::exception &exc) {
595
- auto what = exc.what();
596
- invoker->invokeAsync([&rt, what = std::string(what), reject] {
597
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
598
- auto error = errorCtr.callAsConstructor(
599
- rt, jsi::String::createFromAscii(rt, what));
600
- reject->asObject(rt).asFunction(rt).call(rt, error);
601
- });
602
- }
603
- };
604
- _thread_pool->queueWork(task);
605
- return {};
595
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
596
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
597
+
598
+ auto task = [&rt, this, sqlFileName, resolve, reject]() {
599
+ try {
600
+ const auto result = import_sql_file(db, sqlFileName);
601
+
602
+ invoker->invokeAsync([&rt, result, resolve] {
603
+ auto res = jsi::Object(rt);
604
+ res.setProperty(rt, "rowsAffected",
605
+ jsi::Value(result.affectedRows));
606
+ res.setProperty(rt, "commands",
607
+ jsi::Value(result.commands));
608
+ resolve->asObject(rt).asFunction(rt).call(
609
+ rt, std::move(res));
610
+ });
611
+ } catch (std::runtime_error &e) {
612
+ auto what = e.what();
613
+ invoker->invokeAsync(
614
+ [&rt, what = std::string(what), reject] {
615
+ auto errorCtr =
616
+ rt.global().getPropertyAsFunction(rt, "Error");
617
+ auto error = errorCtr.callAsConstructor(
618
+ rt, jsi::String::createFromAscii(rt, what));
619
+ reject->asObject(rt).asFunction(rt).call(rt, error);
620
+ });
621
+ } catch (std::exception &exc) {
622
+ auto what = exc.what();
623
+ invoker->invokeAsync(
624
+ [&rt, what = std::string(what), reject] {
625
+ auto errorCtr =
626
+ rt.global().getPropertyAsFunction(rt, "Error");
627
+ auto error = errorCtr.callAsConstructor(
628
+ rt, jsi::String::createFromAscii(rt, what));
629
+ reject->asObject(rt).asFunction(rt).call(rt, error);
630
+ });
631
+ }
632
+ };
633
+ _thread_pool->queueWork(task);
634
+ return {};
606
635
  }));
607
636
 
608
637
  return promise;
609
- });
638
+ });
610
639
 
611
- function_map["updateHook"] = HOSTFN("updateHook") {
612
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
640
+ function_map["updateHook"] = HOSTFN("updateHook") {
641
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
613
642
 
614
- if (callback->isUndefined() || callback->isNull()) {
615
- update_hook_callback = nullptr;
616
- } else {
617
- update_hook_callback = callback;
618
- }
643
+ if (callback->isUndefined() || callback->isNull()) {
644
+ update_hook_callback = nullptr;
645
+ } else {
646
+ update_hook_callback = callback;
647
+ }
619
648
 
620
- auto_register_update_hook();
621
- return {};
622
- });
649
+ auto_register_update_hook();
650
+ return {};
651
+ });
623
652
 
624
- function_map["commitHook"] = HOSTFN("commitHook") {
625
- if (count < 1) {
626
- throw std::runtime_error("[op-sqlite][commitHook] callback needed");
627
- }
653
+ function_map["commitHook"] = HOSTFN("commitHook") {
654
+ if (count < 1) {
655
+ throw std::runtime_error("[op-sqlite][commitHook] callback needed");
656
+ }
628
657
 
629
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
630
- if (callback->isUndefined() || callback->isNull()) {
631
- opsqlite_deregister_commit_hook(db);
632
- return {};
633
- }
634
- commit_hook_callback = callback;
635
- opsqlite_register_commit_hook(db, this);
658
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
659
+ if (callback->isUndefined() || callback->isNull()) {
660
+ opsqlite_deregister_commit_hook(db);
661
+ return {};
662
+ }
663
+ commit_hook_callback = callback;
664
+ opsqlite_register_commit_hook(db, this);
636
665
 
637
- return {};
638
- });
666
+ return {};
667
+ });
639
668
 
640
- function_map["rollbackHook"] = HOSTFN("rollbackHook") {
641
- if (count < 1) {
642
- throw std::runtime_error("[op-sqlite][rollbackHook] callback needed");
643
- }
669
+ function_map["rollbackHook"] = HOSTFN("rollbackHook") {
670
+ if (count < 1) {
671
+ throw std::runtime_error(
672
+ "[op-sqlite][rollbackHook] callback needed");
673
+ }
644
674
 
645
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
675
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
646
676
 
647
- if (callback->isUndefined() || callback->isNull()) {
648
- opsqlite_deregister_rollback_hook(db);
649
- return {};
650
- }
651
- rollback_hook_callback = callback;
677
+ if (callback->isUndefined() || callback->isNull()) {
678
+ opsqlite_deregister_rollback_hook(db);
679
+ return {};
680
+ }
681
+ rollback_hook_callback = callback;
682
+
683
+ opsqlite_register_rollback_hook(db, this);
684
+ return {};
685
+ });
652
686
 
653
- opsqlite_register_rollback_hook(db, this);
654
- return {};
655
- });
687
+ function_map["loadExtension"] = HOSTFN("loadExtension") {
688
+ auto path = args[0].asString(rt).utf8(rt);
689
+ std::string entry_point;
690
+ if (count > 1 && args[1].isString()) {
691
+ entry_point = args[1].asString(rt).utf8(rt);
692
+ }
656
693
 
657
- function_map["loadExtension"] = HOSTFN("loadExtension") {
658
- auto path = args[0].asString(rt).utf8(rt);
659
- std::string entry_point;
660
- if (count > 1 && args[1].isString()) {
661
- entry_point = args[1].asString(rt).utf8(rt);
662
- }
694
+ opsqlite_load_extension(db, path, entry_point);
695
+ return {};
696
+ });
663
697
 
664
- opsqlite_load_extension(db, path, entry_point);
665
- return {};
666
- });
667
-
668
- function_map["reactiveExecute"] = HOSTFN("reactiveExecute") {
669
- auto query = args[0].asObject(rt);
670
-
671
- const std::string query_str =
672
- query.getProperty(rt, "query").asString(rt).utf8(rt);
673
- auto js_args = query.getProperty(rt, "arguments");
674
- auto js_discriminators =
675
- query.getProperty(rt, "fireOn").asObject(rt).asArray(rt);
676
- auto variant_args = to_variant_vec(rt, js_args);
677
-
678
- sqlite3_stmt *stmt = opsqlite_prepare_statement(db, query_str);
679
- opsqlite_bind_statement(stmt, &variant_args);
680
-
681
- auto callback =
682
- std::make_shared<jsi::Value>(query.getProperty(rt, "callback"));
683
-
684
- std::vector<TableRowDiscriminator> discriminators;
685
-
686
- for (size_t i = 0; i < js_discriminators.length(rt); i++) {
687
- auto js_discriminator =
688
- js_discriminators.getValueAtIndex(rt, i).asObject(rt);
689
- std::string table =
690
- js_discriminator.getProperty(rt, "table").asString(rt).utf8(rt);
691
- std::vector<int> ids;
692
- if (js_discriminator.hasProperty(rt, "ids")) {
693
- auto js_ids =
694
- js_discriminator.getProperty(rt, "ids").asObject(rt).asArray(rt);
695
- for (size_t j = 0; j < js_ids.length(rt); j++) {
696
- ids.push_back(
697
- static_cast<int>(js_ids.getValueAtIndex(rt, j).asNumber()));
698
+ function_map["reactiveExecute"] = HOSTFN("reactiveExecute") {
699
+ auto query = args[0].asObject(rt);
700
+
701
+ const std::string query_str =
702
+ query.getProperty(rt, "query").asString(rt).utf8(rt);
703
+ auto js_args = query.getProperty(rt, "arguments");
704
+ auto js_discriminators =
705
+ query.getProperty(rt, "fireOn").asObject(rt).asArray(rt);
706
+ auto variant_args = to_variant_vec(rt, js_args);
707
+
708
+ sqlite3_stmt *stmt = opsqlite_prepare_statement(db, query_str);
709
+ opsqlite_bind_statement(stmt, &variant_args);
710
+
711
+ auto callback =
712
+ std::make_shared<jsi::Value>(query.getProperty(rt, "callback"));
713
+
714
+ std::vector<TableRowDiscriminator> discriminators;
715
+
716
+ for (size_t i = 0; i < js_discriminators.length(rt); i++) {
717
+ auto js_discriminator =
718
+ js_discriminators.getValueAtIndex(rt, i).asObject(rt);
719
+ std::string table =
720
+ js_discriminator.getProperty(rt, "table").asString(rt).utf8(rt);
721
+ std::vector<int> ids;
722
+ if (js_discriminator.hasProperty(rt, "ids")) {
723
+ auto js_ids = js_discriminator.getProperty(rt, "ids")
724
+ .asObject(rt)
725
+ .asArray(rt);
726
+ for (size_t j = 0; j < js_ids.length(rt); j++) {
727
+ ids.push_back(static_cast<int>(
728
+ js_ids.getValueAtIndex(rt, j).asNumber()));
729
+ }
730
+ }
731
+ discriminators.push_back({table, ids});
698
732
  }
699
- }
700
- discriminators.push_back({table, ids});
701
- }
702
733
 
703
- std::shared_ptr<ReactiveQuery> reactiveQuery =
704
- std::make_shared<ReactiveQuery>(
705
- ReactiveQuery{stmt, discriminators, callback});
734
+ std::shared_ptr<ReactiveQuery> reactiveQuery =
735
+ std::make_shared<ReactiveQuery>(
736
+ ReactiveQuery{stmt, discriminators, callback});
706
737
 
707
- reactive_queries.push_back(reactiveQuery);
738
+ reactive_queries.push_back(reactiveQuery);
708
739
 
709
- auto_register_update_hook();
740
+ auto_register_update_hook();
710
741
 
711
- auto unsubscribe = HOSTFN("unsubscribe") {
712
- auto it = std::find(reactive_queries.begin(), reactive_queries.end(),
713
- reactiveQuery);
714
- if (it != reactive_queries.end()) {
715
- reactive_queries.erase(it);
716
- }
717
- auto_register_update_hook();
718
- return {};
719
- });
742
+ auto unsubscribe = HOSTFN("unsubscribe") {
743
+ auto it = std::find(reactive_queries.begin(),
744
+ reactive_queries.end(), reactiveQuery);
745
+ if (it != reactive_queries.end()) {
746
+ reactive_queries.erase(it);
747
+ }
748
+ auto_register_update_hook();
749
+ return {};
750
+ });
720
751
 
721
- return unsubscribe;
722
- });
752
+ return unsubscribe;
753
+ });
723
754
  #endif
724
755
 
725
- function_map["prepareStatement"] = HOSTFN("prepareStatement") {
726
- auto query = args[0].asString(rt).utf8(rt);
756
+ function_map["prepareStatement"] = HOSTFN("prepareStatement") {
757
+ auto query = args[0].asString(rt).utf8(rt);
727
758
  #ifdef OP_SQLITE_USE_LIBSQL
728
- libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db, query);
759
+ libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db, query);
729
760
  #else
730
- sqlite3_stmt *statement = opsqlite_prepare_statement(db, query);
761
+ sqlite3_stmt *statement = opsqlite_prepare_statement(db, query);
731
762
  #endif
732
- auto preparedStatementHostObject =
733
- std::make_shared<PreparedStatementHostObject>(db, db_name, statement,
734
- invoker, _thread_pool);
735
-
736
- return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
737
- });
738
-
739
- function_map["getDbPath"] = HOSTFN("getDbPath") {
740
- std::string path = std::string(base_path);
741
-
742
- if (count == 1) {
743
- if(!args[0].isString()) {
744
- throw std::runtime_error(
745
- "[op-sqlite][open] database location must be a string");
746
- }
747
-
748
- std::string last_path = args[0].asString(rt).utf8(rt);
749
-
750
- if (last_path == ":memory:") {
751
- path = ":memory:";
752
- } else if (last_path.rfind('/', 0) == 0) {
753
- path = last_path;
754
- } else {
755
- path = path + "/" + last_path;
756
- }
757
- }
763
+ auto preparedStatementHostObject =
764
+ std::make_shared<PreparedStatementHostObject>(
765
+ db, db_name, statement, invoker, _thread_pool);
766
+
767
+ return jsi::Object::createFromHostObject(rt,
768
+ preparedStatementHostObject);
769
+ });
758
770
 
759
- auto result = opsqlite_get_db_path(db_name, path);
760
- return jsi::String::createFromUtf8(rt, result);
761
- });
771
+ function_map["getDbPath"] = HOSTFN("getDbPath") {
772
+ std::string path = std::string(base_path);
762
773
 
763
- function_map["flushPendingReactiveQueries"] =
764
- HOSTFN("flushPendingReactiveQueries") {
765
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
774
+ if (count == 1) {
775
+ if (!args[0].isString()) {
776
+ throw std::runtime_error(
777
+ "[op-sqlite][open] database location must be a string");
778
+ }
779
+
780
+ std::string last_path = args[0].asString(rt).utf8(rt);
781
+
782
+ if (last_path == ":memory:") {
783
+ path = ":memory:";
784
+ } else if (last_path.rfind('/', 0) == 0) {
785
+ path = last_path;
786
+ } else {
787
+ path = path + "/" + last_path;
788
+ }
789
+ }
790
+
791
+ auto result = opsqlite_get_db_path(db_name, path);
792
+ return jsi::String::createFromUtf8(rt, result);
793
+ });
794
+
795
+ function_map["flushPendingReactiveQueries"] =
796
+ HOSTFN("flushPendingReactiveQueries") {
797
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
766
798
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
767
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
799
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
768
800
 
769
- auto task = [&rt, this, resolve]() {
770
- flush_pending_reactive_queries(resolve);
771
- };
801
+ auto task = [&rt, this, resolve]() {
802
+ flush_pending_reactive_queries(resolve);
803
+ };
772
804
 
773
- _thread_pool->queueWork(task);
805
+ _thread_pool->queueWork(task);
774
806
 
775
- return {};
807
+ return {};
776
808
  }));
777
809
 
778
810
  return promise;
779
- });
811
+ });
780
812
  }
781
813
 
782
814
  std::vector<jsi::PropNameID> DBHostObject::getPropertyNames(jsi::Runtime &_rt) {
783
- std::vector<jsi::PropNameID> keys;
784
- keys.reserve(function_map.size());
785
- for (const auto &pair : function_map) {
786
- keys.emplace_back(jsi::PropNameID::forUtf8(_rt, pair.first));
787
- }
788
- return keys;
815
+ std::vector<jsi::PropNameID> keys;
816
+ keys.reserve(function_map.size());
817
+ for (const auto &pair : function_map) {
818
+ keys.emplace_back(jsi::PropNameID::forUtf8(_rt, pair.first));
819
+ }
820
+ return keys;
789
821
  }
790
822
 
791
823
  jsi::Value DBHostObject::get(jsi::Runtime &_rt,
792
824
  const jsi::PropNameID &propNameID) {
793
- auto name = propNameID.utf8(rt);
794
- if (function_map.count(name) != 1) {
795
- return HOST_STATIC_FN(name.c_str()) {
796
- throw std::runtime_error(
797
- "[op-sqlite] Function " + name +
798
- " not implemented for current backend (libsql or sqlcipher)");
799
- });
800
- }
825
+ auto name = propNameID.utf8(rt);
826
+ if (function_map.count(name) != 1) {
827
+ return HOST_STATIC_FN(name.c_str()) {
828
+ throw std::runtime_error(
829
+ "[op-sqlite] Function " + name +
830
+ " not implemented for current backend (libsql or sqlcipher)");
831
+ });
832
+ }
801
833
 
802
- return {rt, function_map[name]};
834
+ return {rt, function_map[name]};
803
835
  }
804
836
 
805
837
  void DBHostObject::set(jsi::Runtime &_rt, const jsi::PropNameID &name,
806
838
  const jsi::Value &value) {
807
- throw std::runtime_error("You cannot write to this object!");
839
+ throw std::runtime_error("You cannot write to this object!");
808
840
  }
809
841
 
810
842
  void DBHostObject::invalidate() {
811
- invalidated = true;
812
- _thread_pool->restartPool();
843
+ if (invalidated) {
844
+ return;
845
+ }
846
+
847
+ invalidated = true;
848
+ _thread_pool->restartPool();
813
849
  #ifdef OP_SQLITE_USE_LIBSQL
814
850
  opsqlite_libsql_close(db);
815
851
  #else
816
- if (db != nullptr) {
817
- opsqlite_close(db);
818
- db = nullptr;
819
- }
852
+ if (db != nullptr) {
853
+ opsqlite_close(db);
854
+ db = nullptr;
855
+ }
820
856
  #endif
821
857
  }
822
858