@op-engineering/op-sqlite 2.0.1 → 2.0.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.
package/cpp/bindings.cpp CHANGED
@@ -1,15 +1,17 @@
1
1
  #include "bindings.h"
2
+ #include "DumbHostObject.h"
3
+ #include "PreparedStatementHostObject.h"
4
+ #include "ThreadPool.h"
2
5
  #include "bridge.h"
3
6
  #include "logs.h"
4
- #include "utils.h"
5
- #include "ThreadPool.h"
6
- #include "sqlbatchexecutor.h"
7
- #include <vector>
8
- #include <string>
9
7
  #include "macros.h"
8
+ #include "sqlbatchexecutor.h"
9
+ #include "utils.h"
10
10
  #include <iostream>
11
- #include "DumbHostObject.h"
11
+ #include <sqlite3.h>
12
+ #include <string>
12
13
  #include <unordered_map>
14
+ #include <vector>
13
15
 
14
16
  namespace opsqlite {
15
17
 
@@ -18,552 +20,545 @@ namespace jsi = facebook::jsi;
18
20
  std::string basePath;
19
21
  std::shared_ptr<react::CallInvoker> invoker;
20
22
  ThreadPool pool;
21
- std::unordered_map<std::string, std::shared_ptr<jsi::Value>> updateHooks = std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
22
- std::unordered_map<std::string, std::shared_ptr<jsi::Value>> commitHooks = std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
23
- std::unordered_map<std::string, std::shared_ptr<jsi::Value>> rollbackHooks = std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
24
-
23
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>> updateHooks =
24
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
25
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>> commitHooks =
26
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
27
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>> rollbackHooks =
28
+ std::unordered_map<std::string, std::shared_ptr<jsi::Value>>();
25
29
 
26
- // React native will try to clean the module on JS context invalidation (CodePush/Hot Reload)
27
- // The clearState function is called and we use this flag to prevent any ongoing
28
- // operations from continuing work and can return early
30
+ // React native will try to clean the module on JS context invalidation
31
+ // (CodePush/Hot Reload) The clearState function is called and we use this flag
32
+ // to prevent any ongoing operations from continuing work and can return early
29
33
  bool invalidated = false;
30
34
 
31
35
  void clearState() {
32
- invalidated = true;
33
- // Will terminate all operations and database connections
34
- sqliteCloseAll();
35
- // We then join all the threads before the context gets invalidated
36
- pool.restartPool();
36
+ invalidated = true;
37
+ // Will terminate all operations and database connections
38
+ sqliteCloseAll();
39
+ // We then join all the threads before the context gets invalidated
40
+ pool.restartPool();
41
+
42
+ updateHooks.clear();
43
+ commitHooks.clear();
44
+ rollbackHooks.clear();
37
45
  }
38
46
 
39
- void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker, const char *docPath)
40
- {
41
- invalidated = false;
42
- basePath = std::string(docPath);
43
- invoker = jsCallInvoker;
44
-
45
- auto open = HOSTFN("open", 3) {
46
- if (count == 0)
47
- {
48
- throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
49
- }
50
-
51
- if (!args[0].isString())
52
- {
53
- throw jsi::JSError(rt, "[op-sqlite][open] database name must be a string");
54
- }
55
-
56
- std::string dbName = args[0].asString(rt).utf8(rt);
57
- std::string path = std::string(basePath);
58
-
59
- if (count > 1 && !args[1].isUndefined() && !args[1].isNull())
60
- {
61
- if (!args[1].isString())
62
- {
63
- throw jsi::JSError(rt, "[op-sqlite][open] database location must be a string");
64
- }
47
+ void install(jsi::Runtime &rt,
48
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
49
+ const char *docPath) {
50
+ invalidated = false;
51
+ basePath = std::string(docPath);
52
+ invoker = jsCallInvoker;
65
53
 
66
- std::string lastPath = args[1].asString(rt).utf8(rt);
54
+ auto open = HOSTFN("open", 3) {
55
+ if (count == 0) {
56
+ throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
57
+ }
67
58
 
68
- if(lastPath == ":memory:") {
69
- path = ":memory:";
70
- } else if( lastPath.rfind("/", 0) == 0) {
71
- path = lastPath;
72
- } else {
73
- path = path + "/" + lastPath;
74
- }
75
- }
76
-
77
- BridgeResult result = sqliteOpenDb(dbName, path);
78
-
79
- if (result.type == SQLiteError)
80
- {
81
- throw jsi::JSError(rt, result.message.c_str());
82
- }
83
-
84
- return {};
85
- });
86
-
87
- auto attach = HOSTFN("attach", 4) {
88
- if(count < 3) {
89
- throw jsi::JSError(rt, "[op-sqlite][attach] Incorrect number of arguments");
90
- }
91
- if (!args[0].isString() || !args[1].isString() || !args[2].isString())
92
- {
93
- throw jsi::JSError(rt, "dbName, databaseToAttach and alias must be a strings");
94
- return {};
95
- }
96
-
97
- std::string tempDocPath = std::string(basePath);
98
- if (count > 3 && !args[3].isUndefined() && !args[3].isNull())
99
- {
100
- if (!args[3].isString())
101
- {
102
- throw jsi::JSError(rt, "[op-sqlite][attach] database location must be a string");
103
- }
104
-
105
- tempDocPath = tempDocPath + "/" + args[3].asString(rt).utf8(rt);
106
- }
107
-
108
- std::string dbName = args[0].asString(rt).utf8(rt);
109
- std::string databaseToAttach = args[1].asString(rt).utf8(rt);
110
- std::string alias = args[2].asString(rt).utf8(rt);
111
- BridgeResult result = sqliteAttachDb(dbName, tempDocPath, databaseToAttach, alias);
112
-
113
- if (result.type == SQLiteError)
114
- {
115
- throw jsi::JSError(rt, result.message.c_str());
116
- }
117
-
118
- return {};
119
- });
120
-
121
- auto detach = HOSTFN("detach", 2) {
122
- if(count < 2) {
123
- throw jsi::JSError(rt, "[op-sqlite][detach] Incorrect number of arguments");
124
- }
125
- if (!args[0].isString() || !args[1].isString())
126
- {
127
- throw jsi::JSError(rt, "dbName, databaseToAttach and alias must be a strings");
128
- return {};
129
- }
130
-
131
- std::string dbName = args[0].asString(rt).utf8(rt);
132
- std::string alias = args[1].asString(rt).utf8(rt);
133
- BridgeResult result = sqliteDetachDb(dbName, alias);
134
-
135
- if (result.type == SQLiteError)
136
- {
137
- throw jsi::JSError(rt, result.message.c_str());
138
- }
139
-
140
- return {};
141
- });
142
-
143
- auto close = HOSTFN("close", 1)
144
- {
145
- if (count == 0)
146
- {
147
- throw jsi::JSError(rt, "[op-sqlite][close] database name is required");
148
- }
149
-
150
- if (!args[0].isString())
151
- {
152
- throw jsi::JSError(rt, "[op-sqlite][close] database name must be a string");
153
- }
154
-
155
- std::string dbName = args[0].asString(rt).utf8(rt);
156
-
157
- BridgeResult result = sqliteCloseDb(dbName);
158
-
159
- if (result.type == SQLiteError)
160
- {
161
- throw jsi::JSError(rt, result.message.c_str());
162
- }
163
-
164
- return {};
165
- });
166
-
167
- auto remove = HOSTFN("delete", 2)
168
- {
169
- if (count == 0)
170
- {
171
- throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
172
- }
173
-
174
- if (!args[0].isString())
175
- {
176
- throw jsi::JSError(rt, "[op-sqlite][open] database name must be a string");
177
- }
178
-
179
- std::string dbName = args[0].asString(rt).utf8(rt);
180
-
181
- std::string tempDocPath = std::string(basePath);
182
-
183
- if (count > 1 && !args[1].isUndefined() && !args[1].isNull())
184
- {
185
- if (!args[1].isString())
186
- {
187
- throw jsi::JSError(rt, "[op-sqlite][open] database location must be a string");
188
- }
189
-
190
- tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
191
- }
192
-
193
-
194
- BridgeResult result = sqliteRemoveDb(dbName, tempDocPath);
195
-
196
- if (result.type == SQLiteError)
197
- {
198
- throw jsi::JSError(rt, result.message.c_str());
199
- }
200
-
201
- return {};
202
- });
203
-
204
- auto execute = HOSTFN("execute", 3)
205
- {
206
- const std::string dbName = args[0].asString(rt).utf8(rt);
207
- const std::string query = args[1].asString(rt).utf8(rt);
208
- std::vector<JSVariant> params;
209
- try {
210
- if(count == 3) {
211
- const jsi::Value &originalParams = args[2];
212
- params = toVariantVec(rt, originalParams);
213
- }
214
-
215
- std::vector<DumbHostObject> results;
216
- std::shared_ptr<std::vector<DynamicHostObject>> metadata = std::make_shared<std::vector<DynamicHostObject>>();
217
-
218
- auto status = sqliteExecute(dbName, query, &params, &results, metadata);
219
-
220
- if(status.type == SQLiteError) {
221
- throw jsi::JSError(rt, status.message);
222
- }
223
-
224
- auto jsiResult = createResult(rt, status, &results, metadata);
225
- return jsiResult;
226
- } catch (const std::exception &e) {
227
- throw jsi::JSError(rt, e.what());
228
- }
229
- });
230
-
231
- auto executeAsync = HOSTFN("executeAsync", 3)
232
- {
233
- if (count < 3)
234
- {
235
- throw jsi::JSError(rt, "[op-sqlite][executeAsync] Incorrect arguments for executeAsync");
236
- }
237
-
238
- const std::string dbName = args[0].asString(rt).utf8(rt);
239
- const std::string query = args[1].asString(rt).utf8(rt);
59
+ if (!args[0].isString()) {
60
+ throw jsi::JSError(rt,
61
+ "[op-sqlite][open] database name must be a string");
62
+ }
63
+
64
+ std::string dbName = args[0].asString(rt).utf8(rt);
65
+ std::string path = std::string(basePath);
66
+
67
+ if (count > 1 && !args[1].isUndefined() && !args[1].isNull()) {
68
+ if (!args[1].isString()) {
69
+ throw jsi::JSError(
70
+ rt, "[op-sqlite][open] database location must be a string");
71
+ }
72
+
73
+ std::string lastPath = args[1].asString(rt).utf8(rt);
74
+
75
+ if (lastPath == ":memory:") {
76
+ path = ":memory:";
77
+ } else if (lastPath.rfind("/", 0) == 0) {
78
+ path = lastPath;
79
+ } else {
80
+ path = path + "/" + lastPath;
81
+ }
82
+ }
83
+
84
+ BridgeResult result = sqliteOpenDb(dbName, path);
85
+
86
+ if (result.type == SQLiteError) {
87
+ throw jsi::JSError(rt, result.message.c_str());
88
+ }
89
+
90
+ return {};
91
+ });
92
+
93
+ auto attach = HOSTFN("attach", 4) {
94
+ if (count < 3) {
95
+ throw jsi::JSError(rt,
96
+ "[op-sqlite][attach] Incorrect number of arguments");
97
+ }
98
+ if (!args[0].isString() || !args[1].isString() || !args[2].isString()) {
99
+ throw jsi::JSError(
100
+ rt, "dbName, databaseToAttach and alias must be a strings");
101
+ return {};
102
+ }
103
+
104
+ std::string tempDocPath = std::string(basePath);
105
+ if (count > 3 && !args[3].isUndefined() && !args[3].isNull()) {
106
+ if (!args[3].isString()) {
107
+ throw jsi::JSError(
108
+ rt, "[op-sqlite][attach] database location must be a string");
109
+ }
110
+
111
+ tempDocPath = tempDocPath + "/" + args[3].asString(rt).utf8(rt);
112
+ }
113
+
114
+ std::string dbName = args[0].asString(rt).utf8(rt);
115
+ std::string databaseToAttach = args[1].asString(rt).utf8(rt);
116
+ std::string alias = args[2].asString(rt).utf8(rt);
117
+ BridgeResult result =
118
+ sqliteAttachDb(dbName, tempDocPath, databaseToAttach, alias);
119
+
120
+ if (result.type == SQLiteError) {
121
+ throw jsi::JSError(rt, result.message.c_str());
122
+ }
123
+
124
+ return {};
125
+ });
126
+
127
+ auto detach = HOSTFN("detach", 2) {
128
+ if (count < 2) {
129
+ throw jsi::JSError(rt,
130
+ "[op-sqlite][detach] Incorrect number of arguments");
131
+ }
132
+ if (!args[0].isString() || !args[1].isString()) {
133
+ throw jsi::JSError(
134
+ rt, "dbName, databaseToAttach and alias must be a strings");
135
+ return {};
136
+ }
137
+
138
+ std::string dbName = args[0].asString(rt).utf8(rt);
139
+ std::string alias = args[1].asString(rt).utf8(rt);
140
+ BridgeResult result = sqliteDetachDb(dbName, alias);
141
+
142
+ if (result.type == SQLiteError) {
143
+ throw jsi::JSError(rt, result.message.c_str());
144
+ }
145
+
146
+ return {};
147
+ });
148
+
149
+ auto close = HOSTFN("close", 1) {
150
+ if (count == 0) {
151
+ throw jsi::JSError(rt, "[op-sqlite][close] database name is required");
152
+ }
153
+
154
+ if (!args[0].isString()) {
155
+ throw jsi::JSError(rt,
156
+ "[op-sqlite][close] database name must be a string");
157
+ }
158
+
159
+ std::string dbName = args[0].asString(rt).utf8(rt);
160
+
161
+ BridgeResult result = sqliteCloseDb(dbName);
162
+
163
+ if (result.type == SQLiteError) {
164
+ throw jsi::JSError(rt, result.message.c_str());
165
+ }
166
+
167
+ return {};
168
+ });
169
+
170
+ auto remove = HOSTFN("delete", 2) {
171
+ if (count == 0) {
172
+ throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
173
+ }
174
+
175
+ if (!args[0].isString()) {
176
+ throw jsi::JSError(rt,
177
+ "[op-sqlite][open] database name must be a string");
178
+ }
179
+
180
+ std::string dbName = args[0].asString(rt).utf8(rt);
181
+
182
+ std::string tempDocPath = std::string(basePath);
183
+
184
+ if (count > 1 && !args[1].isUndefined() && !args[1].isNull()) {
185
+ if (!args[1].isString()) {
186
+ throw jsi::JSError(
187
+ rt, "[op-sqlite][open] database location must be a string");
188
+ }
189
+
190
+ tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
191
+ }
192
+
193
+ BridgeResult result = sqliteRemoveDb(dbName, tempDocPath);
194
+
195
+ if (result.type == SQLiteError) {
196
+ throw jsi::JSError(rt, result.message.c_str());
197
+ }
198
+
199
+ return {};
200
+ });
201
+
202
+ auto execute = HOSTFN("execute", 3) {
203
+ const std::string dbName = args[0].asString(rt).utf8(rt);
204
+ const std::string query = args[1].asString(rt).utf8(rt);
205
+ std::vector<JSVariant> params;
206
+ try {
207
+ if (count == 3) {
240
208
  const jsi::Value &originalParams = args[2];
241
-
242
- std::vector<JSVariant> params = toVariantVec(rt, originalParams);
243
-
244
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
209
+ params = toVariantVec(rt, originalParams);
210
+ }
211
+
212
+ std::vector<DumbHostObject> results;
213
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
214
+ std::make_shared<std::vector<SmartHostObject>>();
215
+
216
+ auto status = sqliteExecute(dbName, query, &params, &results, metadata);
217
+
218
+ if (status.type == SQLiteError) {
219
+ throw jsi::JSError(rt, status.message);
220
+ }
221
+
222
+ auto jsiResult = createResult(rt, status, &results, metadata);
223
+ return jsiResult;
224
+ } catch (const std::exception &e) {
225
+ throw jsi::JSError(rt, e.what());
226
+ }
227
+ });
228
+
229
+ auto executeAsync = HOSTFN("executeAsync", 3) {
230
+ if (count < 3) {
231
+ throw jsi::JSError(
232
+ rt, "[op-sqlite][executeAsync] Incorrect arguments for executeAsync");
233
+ }
234
+
235
+ const std::string dbName = args[0].asString(rt).utf8(rt);
236
+ const std::string query = args[1].asString(rt).utf8(rt);
237
+ const jsi::Value &originalParams = args[2];
238
+
239
+ std::vector<JSVariant> params = toVariantVec(rt, originalParams);
240
+
241
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
245
242
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
246
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
247
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
248
-
249
- auto task =
250
- [&rt, dbName, query, params = std::move(params), resolve, reject]()
251
- {
252
- try
253
- {
254
- std::vector<DumbHostObject> results;
255
- std::shared_ptr<std::vector<DynamicHostObject>> metadata = std::make_shared<std::vector<DynamicHostObject>>();;
256
-
257
- auto status = sqliteExecute(dbName, query, &params, &results, metadata);
258
-
259
- if(invalidated) {
260
- return;
261
- }
262
-
263
- invoker->invokeAsync([&rt,
264
- results = std::make_shared<std::vector<DumbHostObject>>(results),
265
- metadata,
266
- status = std::move(status),
267
- resolve,
268
- reject] {
269
- if(status.type == SQLiteOk) {
270
- auto jsiResult = createResult(rt, status, results.get(), metadata);
271
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(jsiResult));
272
- } else {
273
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
274
- auto error = errorCtr.callAsConstructor(rt, jsi::String::createFromUtf8(rt, status.message));
275
- reject->asObject(rt).asFunction(rt).call(rt, error);
276
- }
277
- });
278
-
279
- }
280
- catch (std::exception &exc)
281
- {
282
- invoker->invokeAsync([&rt, exc = std::move(exc), reject] {
283
- auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
284
- auto error = errorCtr.callAsConstructor(rt, jsi::String::createFromAscii(rt, exc.what()));
285
- reject->asObject(rt).asFunction(rt).call(rt, error);
286
- });
243
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
244
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
245
+
246
+ auto task = [&rt, dbName, query, params = std::move(params), resolve,
247
+ reject]() {
248
+ try {
249
+ std::vector<DumbHostObject> results;
250
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
251
+ std::make_shared<std::vector<SmartHostObject>>();
252
+ ;
253
+
254
+ auto status =
255
+ sqliteExecute(dbName, query, &params, &results, metadata);
256
+
257
+ if (invalidated) {
258
+ return;
259
+ }
260
+
261
+ invoker->invokeAsync(
262
+ [&rt,
263
+ results = std::make_shared<std::vector<DumbHostObject>>(results),
264
+ metadata, status = std::move(status), resolve, reject] {
265
+ if (status.type == SQLiteOk) {
266
+ auto jsiResult =
267
+ createResult(rt, status, results.get(), metadata);
268
+ resolve->asObject(rt).asFunction(rt).call(
269
+ rt, std::move(jsiResult));
270
+ } else {
271
+ auto errorCtr =
272
+ rt.global().getPropertyAsFunction(rt, "Error");
273
+ auto error = errorCtr.callAsConstructor(
274
+ rt, jsi::String::createFromUtf8(rt, status.message));
275
+ reject->asObject(rt).asFunction(rt).call(rt, error);
287
276
  }
288
- };
289
-
290
- pool.queueWork(task);
291
-
292
- return {};
277
+ });
278
+
279
+ } catch (std::exception &exc) {
280
+ invoker->invokeAsync([&rt, exc = std::move(exc), reject] {
281
+ auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
282
+ auto error = errorCtr.callAsConstructor(
283
+ rt, jsi::String::createFromAscii(rt, exc.what()));
284
+ reject->asObject(rt).asFunction(rt).call(rt, error);
285
+ });
286
+ }
287
+ };
288
+
289
+ pool.queueWork(task);
290
+
291
+ return {};
293
292
  }));
294
-
293
+
295
294
  return promise;
296
- });
297
-
298
- // Execute a batch of SQL queries in a transaction
299
- // Parameters can be: [[sql: string, arguments: any[] | arguments: any[][] ]]
300
- auto executeBatch = HOSTFN("executeBatch", 2)
301
- {
302
- if (sizeof(args) < 2)
303
- {
304
- throw jsi::JSError(rt, "[op-sqlite][executeBatch] - Incorrect parameter count");
305
- }
306
-
307
- const jsi::Value &params = args[1];
308
- if (params.isNull() || params.isUndefined())
309
- {
310
- throw jsi::JSError(rt, "[op-sqlite][executeBatch] - An array of SQL commands or parameters is needed");
311
- }
312
- const std::string dbName = args[0].asString(rt).utf8(rt);
313
- const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
314
- std::vector<BatchArguments> commands;
315
- toBatchArguments(rt, batchParams, &commands);
316
-
317
- auto batchResult = sqliteExecuteBatch(dbName, &commands);
318
- if (batchResult.type == SQLiteOk)
319
- {
320
- auto res = jsi::Object(rt);
321
- res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
322
- return std::move(res);
323
- }
324
- else
325
- {
326
- throw jsi::JSError(rt, batchResult.message);
327
- }
328
- });
329
-
330
- auto executeBatchAsync = HOSTFN("executeBatchAsync", 2)
331
- {
332
- if (sizeof(args) < 2)
333
- {
334
- throw jsi::JSError(rt, "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
335
- return {};
336
- }
337
-
338
- const jsi::Value &params = args[1];
339
-
340
- if (params.isNull() || params.isUndefined())
341
- {
342
- throw jsi::JSError(rt, "[op-sqlite][executeAsyncBatch] - An array of SQL commands or parameters is needed");
343
- return {};
344
- }
345
-
346
- const std::string dbName = args[0].asString(rt).utf8(rt);
347
- const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
348
-
349
- std::vector<BatchArguments> commands;
350
- toBatchArguments(rt, batchParams, &commands);
351
-
352
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
295
+ });
296
+
297
+ // Execute a batch of SQL queries in a transaction
298
+ // Parameters can be: [[sql: string, arguments: any[] | arguments: any[][] ]]
299
+ auto executeBatch = HOSTFN("executeBatch", 2) {
300
+ if (sizeof(args) < 2) {
301
+ throw jsi::JSError(
302
+ rt, "[op-sqlite][executeBatch] - Incorrect parameter count");
303
+ }
304
+
305
+ const jsi::Value &params = args[1];
306
+ if (params.isNull() || params.isUndefined()) {
307
+ throw jsi::JSError(rt, "[op-sqlite][executeBatch] - An array of SQL "
308
+ "commands or parameters is needed");
309
+ }
310
+ const std::string dbName = args[0].asString(rt).utf8(rt);
311
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
312
+ std::vector<BatchArguments> commands;
313
+ toBatchArguments(rt, batchParams, &commands);
314
+
315
+ auto batchResult = sqliteExecuteBatch(dbName, &commands);
316
+ if (batchResult.type == SQLiteOk) {
317
+ auto res = jsi::Object(rt);
318
+ res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
319
+ return std::move(res);
320
+ } else {
321
+ throw jsi::JSError(rt, batchResult.message);
322
+ }
323
+ });
324
+
325
+ auto executeBatchAsync = HOSTFN("executeBatchAsync", 2) {
326
+ if (sizeof(args) < 2) {
327
+ throw jsi::JSError(
328
+ rt, "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
329
+ return {};
330
+ }
331
+
332
+ const jsi::Value &params = args[1];
333
+
334
+ if (params.isNull() || params.isUndefined()) {
335
+ throw jsi::JSError(rt, "[op-sqlite][executeAsyncBatch] - An array of SQL "
336
+ "commands or parameters is needed");
337
+ return {};
338
+ }
339
+
340
+ const std::string dbName = args[0].asString(rt).utf8(rt);
341
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
342
+
343
+ std::vector<BatchArguments> commands;
344
+ toBatchArguments(rt, batchParams, &commands);
345
+
346
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
353
347
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
354
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
355
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
356
-
357
- auto task =
358
- [&rt, dbName, commands = std::make_shared<std::vector<BatchArguments>>(commands), resolve, reject]()
359
- {
360
- try
361
- {
362
- auto batchResult = sqliteExecuteBatch(dbName, commands.get());
363
- invoker->invokeAsync([&rt, batchResult = std::move(batchResult), resolve, reject]
364
- {
365
- if(batchResult.type == SQLiteOk)
366
- {
367
- auto res = jsi::Object(rt);
368
- res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
369
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
370
- } else
371
- {
372
- throw jsi::JSError(rt, batchResult.message);
373
- } });
374
- }
375
- catch (std::exception &exc)
376
- {
377
- invoker->invokeAsync([&rt, reject, &exc]
378
- {
379
- throw jsi::JSError(rt, exc.what());
380
- });
348
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
349
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
350
+
351
+ auto task = [&rt, dbName,
352
+ commands =
353
+ std::make_shared<std::vector<BatchArguments>>(commands),
354
+ resolve, reject]() {
355
+ try {
356
+ auto batchResult = sqliteExecuteBatch(dbName, commands.get());
357
+ invoker->invokeAsync(
358
+ [&rt, batchResult = std::move(batchResult), resolve, reject] {
359
+ if (batchResult.type == SQLiteOk) {
360
+ auto res = jsi::Object(rt);
361
+ res.setProperty(rt, "rowsAffected",
362
+ jsi::Value(batchResult.affectedRows));
363
+ resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
364
+ } else {
365
+ throw jsi::JSError(rt, batchResult.message);
381
366
  }
382
- };
383
- pool.queueWork(task);
384
-
385
- return {};
367
+ });
368
+ } catch (std::exception &exc) {
369
+ invoker->invokeAsync(
370
+ [&rt, reject, &exc] { throw jsi::JSError(rt, exc.what()); });
371
+ }
372
+ };
373
+ pool.queueWork(task);
374
+
375
+ return {};
386
376
  }));
387
-
377
+
388
378
  return promise;
389
- });
390
-
391
- auto loadFile = HOSTFN("loadFile", 2)
392
- {
393
- if (sizeof(args) < 2)
394
- {
395
- throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameter count");
396
- return {};
397
- }
398
-
399
- const std::string dbName = args[0].asString(rt).utf8(rt);
400
- const std::string sqlFileName = args[1].asString(rt).utf8(rt);
401
-
402
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
379
+ });
380
+
381
+ auto loadFile = HOSTFN("loadFile", 2) {
382
+ if (sizeof(args) < 2) {
383
+ throw jsi::JSError(
384
+ rt, "[op-sqlite][loadFileAsync] Incorrect parameter count");
385
+ return {};
386
+ }
387
+
388
+ const std::string dbName = args[0].asString(rt).utf8(rt);
389
+ const std::string sqlFileName = args[1].asString(rt).utf8(rt);
390
+
391
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
403
392
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
404
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
405
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
406
-
407
- auto task =
408
- [&rt, dbName, sqlFileName, resolve, reject]()
409
- {
410
- try
411
- {
412
- const auto importResult = importSQLFile(dbName, sqlFileName);
413
-
414
- invoker->invokeAsync([&rt, result = std::move(importResult), resolve, reject]
415
- {
416
- if(result.type == SQLiteOk)
417
- {
418
- auto res = jsi::Object(rt);
419
- res.setProperty(rt, "rowsAffected", jsi::Value(result.affectedRows));
420
- res.setProperty(rt, "commands", jsi::Value(result.commands));
421
- resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
422
- } else {
423
- throw jsi::JSError(rt, result.message);
424
- } });
425
- }
426
- catch (std::exception &exc)
427
- {
428
- invoker->invokeAsync([&rt, err = exc.what(), reject]
429
- {
430
- throw jsi::JSError(rt, err);
431
- });
393
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
394
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
395
+
396
+ auto task = [&rt, dbName, sqlFileName, resolve, reject]() {
397
+ try {
398
+ const auto importResult = importSQLFile(dbName, sqlFileName);
399
+
400
+ invoker->invokeAsync(
401
+ [&rt, result = std::move(importResult), resolve, reject] {
402
+ if (result.type == SQLiteOk) {
403
+ auto res = jsi::Object(rt);
404
+ res.setProperty(rt, "rowsAffected",
405
+ jsi::Value(result.affectedRows));
406
+ res.setProperty(rt, "commands", jsi::Value(result.commands));
407
+ resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
408
+ } else {
409
+ throw jsi::JSError(rt, result.message);
432
410
  }
433
- };
434
- pool.queueWork(task);
435
- return {};
411
+ });
412
+ } catch (std::exception &exc) {
413
+ invoker->invokeAsync(
414
+ [&rt, err = exc.what(), reject] { throw jsi::JSError(rt, err); });
415
+ }
416
+ };
417
+ pool.queueWork(task);
418
+ return {};
436
419
  }));
437
-
420
+
438
421
  return promise;
439
- });
440
-
441
- auto updateHook = HOSTFN("updateHook", 2)
442
- {
443
- if (sizeof(args) < 2)
444
- {
445
- throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: dbName and callback needed");
446
- return {};
447
- }
448
-
449
- auto dbName = args[0].asString(rt).utf8(rt);
450
- auto callback = std::make_shared<jsi::Value>(rt, args[1]);
451
-
452
- if (callback->isUndefined() || callback->isNull())
453
- {
454
- unregisterUpdateHook(dbName);
455
- return {};
456
- }
422
+ });
423
+
424
+ auto updateHook = HOSTFN("updateHook", 2) {
425
+ if (sizeof(args) < 2) {
426
+ throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: "
427
+ "dbName and callback needed");
428
+ return {};
429
+ }
430
+
431
+ auto dbName = args[0].asString(rt).utf8(rt);
432
+ auto callback = std::make_shared<jsi::Value>(rt, args[1]);
433
+
434
+ if (callback->isUndefined() || callback->isNull()) {
435
+ unregisterUpdateHook(dbName);
436
+ return {};
437
+ }
438
+
439
+ updateHooks[dbName] = callback;
457
440
 
458
- updateHooks[dbName] = callback;
459
-
460
- auto hook = [&rt, callback](std::string dbName, std::string tableName, std::string operation, int rowId) {
461
- std::vector<JSVariant> params;
462
- std::vector<DumbHostObject> results;
463
- std::shared_ptr<std::vector<DynamicHostObject>> metadata = std::make_shared<std::vector<DynamicHostObject>>();;
464
-
465
- if(operation != "DELETE") {
466
- std::string query = "SELECT * FROM " + tableName + " where rowid = " + std::to_string(rowId) + ";";
467
- sqliteExecute(dbName, query, &params, &results, metadata);
441
+ auto hook = [&rt, callback](std::string dbName, std::string tableName,
442
+ std::string operation, int rowId) {
443
+ std::vector<JSVariant> params;
444
+ std::vector<DumbHostObject> results;
445
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
446
+ std::make_shared<std::vector<SmartHostObject>>();
447
+ ;
448
+
449
+ if (operation != "DELETE") {
450
+ std::string query = "SELECT * FROM " + tableName +
451
+ " where rowid = " + std::to_string(rowId) + ";";
452
+ sqliteExecute(dbName, query, &params, &results, metadata);
453
+ }
454
+
455
+ invoker->invokeAsync(
456
+ [&rt,
457
+ results = std::make_shared<std::vector<DumbHostObject>>(results),
458
+ callback, tableName = std::move(tableName),
459
+ operation = std::move(operation), &rowId] {
460
+ auto res = jsi::Object(rt);
461
+ res.setProperty(rt, "table",
462
+ jsi::String::createFromUtf8(rt, tableName));
463
+ res.setProperty(rt, "operation",
464
+ jsi::String::createFromUtf8(rt, operation));
465
+ res.setProperty(rt, "rowId", jsi::Value(rowId));
466
+ if (results->size() != 0) {
467
+ res.setProperty(
468
+ rt, "row",
469
+ jsi::Object::createFromHostObject(
470
+ rt, std::make_shared<DumbHostObject>(results->at(0))));
468
471
  }
469
-
470
- invoker->invokeAsync([&rt, results = std::make_shared<std::vector<DumbHostObject>>(results), callback, tableName = std::move(tableName), operation = std::move(operation), &rowId]
471
- {
472
- auto res = jsi::Object(rt);
473
- res.setProperty(rt, "table", jsi::String::createFromUtf8(rt, tableName));
474
- res.setProperty(rt, "operation", jsi::String::createFromUtf8(rt, operation));
475
- res.setProperty(rt, "rowId", jsi::Value(rowId));
476
- if(results->size() != 0) {
477
- res.setProperty(rt, "row", jsi::Object::createFromHostObject(rt, std::make_shared<DumbHostObject>(results->at(0))));
478
- }
479
-
480
- callback->asObject(rt).asFunction(rt).call(rt, res);
481
-
482
- });
483
- };
484
-
485
- registerUpdateHook(dbName, std::move(hook));
486
-
487
- return {};
488
- });
489
-
490
- auto commitHook = HOSTFN("commitHook", 2)
491
- {
492
- if (sizeof(args) < 2)
493
- {
494
- throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: dbName and callback needed");
495
- return {};
496
- }
497
-
498
- auto dbName = args[0].asString(rt).utf8(rt);
499
- auto callback = std::make_shared<jsi::Value>(rt, args[1]);
500
- if (callback->isUndefined() || callback->isNull())
501
- {
502
- unregisterCommitHook(dbName);
503
- return {};
504
- }
505
- commitHooks[dbName] = callback;
506
-
507
- auto hook = [&rt, callback](std::string dbName) {
508
- invoker->invokeAsync([&rt, callback]
509
- {
510
- callback->asObject(rt).asFunction(rt).call(rt);
511
- });
512
- };
513
-
514
- registerCommitHook(dbName, std::move(hook));
515
-
516
- return {};
517
- });
518
-
519
- auto rollbackHook = HOSTFN("rollbackHook", 2)
520
- {
521
- if (sizeof(args) < 2)
522
- {
523
- throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: dbName and callback needed");
524
- return {};
525
- }
526
-
527
- auto dbName = args[0].asString(rt).utf8(rt);
528
- auto callback = std::make_shared<jsi::Value>(rt, args[1]);
529
-
530
- if (callback->isUndefined() || callback->isNull())
531
- {
532
- unregisterRollbackHook(dbName);
533
- return {};
534
- }
535
- rollbackHooks[dbName] = callback;
536
-
537
- auto hook = [&rt, callback](std::string dbName) {
538
-
539
- invoker->invokeAsync([&rt, callback] {
540
- callback->asObject(rt).asFunction(rt).call(rt);
541
-
542
- });
543
- };
544
-
545
- registerRollbackHook(dbName, std::move(hook));
546
-
547
- return {};
548
- });
549
-
550
- jsi::Object module = jsi::Object(rt);
551
-
552
- module.setProperty(rt, "open", std::move(open));
553
- module.setProperty(rt, "close", std::move(close));
554
- module.setProperty(rt, "attach", std::move(attach));
555
- module.setProperty(rt, "detach", std::move(detach));
556
- module.setProperty(rt, "delete", std::move(remove));
557
- module.setProperty(rt, "execute", std::move(execute));
558
- module.setProperty(rt, "executeAsync", std::move(executeAsync));
559
- module.setProperty(rt, "executeBatch", std::move(executeBatch));
560
- module.setProperty(rt, "executeBatchAsync", std::move(executeBatchAsync));
561
- module.setProperty(rt, "loadFile", std::move(loadFile));
562
- module.setProperty(rt, "updateHook", std::move(updateHook));
563
- module.setProperty(rt, "commitHook", std::move(commitHook));
564
- module.setProperty(rt, "rollbackHook", std::move(rollbackHook));
565
-
566
- rt.global().setProperty(rt, "__OPSQLiteProxy", std::move(module));
567
- }
568
472
 
473
+ callback->asObject(rt).asFunction(rt).call(rt, res);
474
+ });
475
+ };
476
+
477
+ registerUpdateHook(dbName, std::move(hook));
478
+
479
+ return {};
480
+ });
481
+
482
+ auto commitHook = HOSTFN("commitHook", 2) {
483
+ if (sizeof(args) < 2) {
484
+ throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: "
485
+ "dbName and callback needed");
486
+ return {};
487
+ }
488
+
489
+ auto dbName = args[0].asString(rt).utf8(rt);
490
+ auto callback = std::make_shared<jsi::Value>(rt, args[1]);
491
+ if (callback->isUndefined() || callback->isNull()) {
492
+ unregisterCommitHook(dbName);
493
+ return {};
494
+ }
495
+ commitHooks[dbName] = callback;
496
+
497
+ auto hook = [&rt, callback](std::string dbName) {
498
+ invoker->invokeAsync(
499
+ [&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
500
+ };
501
+
502
+ registerCommitHook(dbName, std::move(hook));
503
+
504
+ return {};
505
+ });
506
+
507
+ auto rollbackHook = HOSTFN("rollbackHook", 2) {
508
+ if (sizeof(args) < 2) {
509
+ throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameters: "
510
+ "dbName and callback needed");
511
+ return {};
512
+ }
513
+
514
+ auto dbName = args[0].asString(rt).utf8(rt);
515
+ auto callback = std::make_shared<jsi::Value>(rt, args[1]);
516
+
517
+ if (callback->isUndefined() || callback->isNull()) {
518
+ unregisterRollbackHook(dbName);
519
+ return {};
520
+ }
521
+ rollbackHooks[dbName] = callback;
522
+
523
+ auto hook = [&rt, callback](std::string dbName) {
524
+ invoker->invokeAsync(
525
+ [&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
526
+ };
527
+
528
+ registerRollbackHook(dbName, std::move(hook));
529
+ return {};
530
+ });
531
+
532
+ auto prepareStatement = HOSTFN("prepareStatement", 1) {
533
+ auto dbName = args[0].asString(rt).utf8(rt);
534
+ auto query = args[1].asString(rt).utf8(rt);
535
+
536
+ sqlite3_stmt *statement = sqlite_prepare_statement(dbName, query);
537
+
538
+ auto preparedStatementHostObject =
539
+ std::make_shared<PreparedStatementHostObject>(dbName, statement);
540
+
541
+ return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
542
+ });
543
+
544
+ jsi::Object module = jsi::Object(rt);
545
+
546
+ module.setProperty(rt, "open", std::move(open));
547
+ module.setProperty(rt, "close", std::move(close));
548
+ module.setProperty(rt, "attach", std::move(attach));
549
+ module.setProperty(rt, "detach", std::move(detach));
550
+ module.setProperty(rt, "delete", std::move(remove));
551
+ module.setProperty(rt, "execute", std::move(execute));
552
+ module.setProperty(rt, "executeAsync", std::move(executeAsync));
553
+ module.setProperty(rt, "executeBatch", std::move(executeBatch));
554
+ module.setProperty(rt, "executeBatchAsync", std::move(executeBatchAsync));
555
+ module.setProperty(rt, "loadFile", std::move(loadFile));
556
+ module.setProperty(rt, "updateHook", std::move(updateHook));
557
+ module.setProperty(rt, "commitHook", std::move(commitHook));
558
+ module.setProperty(rt, "rollbackHook", std::move(rollbackHook));
559
+ module.setProperty(rt, "prepareStatement", std::move(prepareStatement));
560
+
561
+ rt.global().setProperty(rt, "__OPSQLiteProxy", std::move(module));
569
562
  }
563
+
564
+ } // namespace opsqlite