@op-engineering/op-sqlite 11.2.14 → 11.3.0
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/DBHostObject.cpp +627 -591
- package/cpp/DBHostObject.h +54 -53
- package/cpp/DumbHostObject.cpp +35 -34
- package/cpp/DumbHostObject.h +12 -11
- package/cpp/PreparedStatementHostObject.cpp +102 -96
- package/cpp/PreparedStatementHostObject.h +28 -26
- package/cpp/SmartHostObject.cpp +13 -13
- package/cpp/SmartHostObject.h +6 -5
- package/cpp/ThreadPool.cpp +80 -78
- package/cpp/ThreadPool.h +28 -28
- package/cpp/bindings.cpp +112 -108
- package/cpp/bridge.cpp +637 -615
- package/cpp/bridge.h +4 -4
- package/cpp/libsql/bridge.cpp +566 -564
- package/cpp/libsql/bridge.h +16 -23
- package/cpp/libsql/libsql.h +62 -48
- package/cpp/logs.h +17 -17
- package/cpp/types.h +12 -12
- package/cpp/utils.cpp +254 -248
- package/lib/commonjs/Storage.js +60 -0
- package/lib/commonjs/Storage.js.map +1 -0
- package/lib/commonjs/index.js +9 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/Storage.js +53 -0
- package/lib/module/Storage.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/Storage.d.ts +23 -0
- package/lib/typescript/src/Storage.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Storage.ts +85 -0
- package/src/index.ts +4 -1
package/cpp/DBHostObject.cpp
CHANGED
|
@@ -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
|
-
|
|
23
|
-
|
|
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
|
-
|
|
29
|
-
|
|
29
|
+
for (const auto &query_ptr : pending_reactive_queries) {
|
|
30
|
+
auto query = query_ptr.get();
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
std::vector<DumbHostObject> results;
|
|
33
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
34
|
+
std::make_shared<std::vector<SmartHostObject>>();
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
auto status = opsqlite_execute_prepared_statement(db, query->stmt,
|
|
37
|
+
&results, metadata);
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
49
|
+
pending_reactive_queries.clear();
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
107
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
154
|
-
|
|
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
|
-
|
|
174
|
+
_thread_pool = std::make_shared<ThreadPool>();
|
|
172
175
|
|
|
173
176
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path,
|
|
178
|
+
encryption_key);
|
|
176
179
|
#elif OP_SQLITE_USE_LIBSQL
|
|
177
|
-
|
|
180
|
+
db = opsqlite_libsql_open(db_name, path, crsqlite_path);
|
|
178
181
|
#else
|
|
179
|
-
|
|
182
|
+
db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path);
|
|
180
183
|
#endif
|
|
181
|
-
|
|
184
|
+
create_jsi_functions();
|
|
182
185
|
};
|
|
183
186
|
|
|
184
187
|
void DBHostObject::create_jsi_functions() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
203
|
-
|
|
205
|
+
secondary_db_path += "/" + args[3].asString(rt).utf8(rt);
|
|
206
|
+
}
|
|
204
207
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
+
opsqlite_attach(db, main_db_name, secondary_db_path, secondary_db_name,
|
|
215
|
+
alias);
|
|
214
216
|
#endif
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
return {};
|
|
219
|
+
});
|
|
218
220
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
|
|
230
|
-
|
|
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
|
-
|
|
234
|
+
opsqlite_libsql_detach(db, alias);
|
|
233
235
|
#else
|
|
234
|
-
|
|
236
|
+
opsqlite_detach(db, dbName, alias);
|
|
235
237
|
#endif
|
|
236
238
|
|
|
237
|
-
|
|
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
|
-
|
|
246
|
+
opsqlite_libsql_close(db);
|
|
243
247
|
#else
|
|
244
|
-
|
|
248
|
+
opsqlite_close(db);
|
|
245
249
|
#endif
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
251
|
+
return {};
|
|
252
|
+
});
|
|
249
253
|
|
|
250
|
-
|
|
251
|
-
|
|
254
|
+
function_map["delete"] = HOSTFN("delete") {
|
|
255
|
+
invalidated = true;
|
|
252
256
|
|
|
253
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
|
|
279
|
+
opsqlite_libsql_remove(db, db_name, path);
|
|
274
280
|
#else
|
|
275
|
-
|
|
281
|
+
opsqlite_remove(db, db_name, path);
|
|
276
282
|
#endif
|
|
277
283
|
|
|
278
|
-
|
|
279
|
-
|
|
284
|
+
return {};
|
|
285
|
+
});
|
|
280
286
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
293
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
288
294
|
auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
298
|
-
|
|
303
|
+
auto status = opsqlite_libsql_execute_raw(
|
|
304
|
+
db, query, ¶ms, &results);
|
|
299
305
|
#else
|
|
300
|
-
|
|
306
|
+
auto status =
|
|
307
|
+
opsqlite_execute_raw(db, query, ¶ms, &results);
|
|
301
308
|
#endif
|
|
302
309
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
351
|
+
function_map["executeSync"] = HOSTFN("executeSync") {
|
|
352
|
+
std::string query = args[0].asString(rt).utf8(rt);
|
|
353
|
+
std::vector<JSVariant> params;
|
|
342
354
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
355
|
+
if (count == 2) {
|
|
356
|
+
params = to_variant_vec(rt, args[1]);
|
|
357
|
+
}
|
|
346
358
|
#ifdef OP_SQLITE_USE_LIBSQL
|
|
347
|
-
|
|
359
|
+
auto status = opsqlite_libsql_execute(db, query, ¶ms);
|
|
348
360
|
#else
|
|
349
|
-
|
|
361
|
+
auto status = opsqlite_execute(db, query, ¶ms);
|
|
350
362
|
#endif
|
|
351
363
|
|
|
352
|
-
|
|
353
|
-
|
|
364
|
+
return create_js_rows(rt, status);
|
|
365
|
+
});
|
|
354
366
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
373
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
362
374
|
auto promise = promiseCtr.callAsConstructor(rt,
|
|
363
375
|
HOSTFN("executor") {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
381
|
+
auto status = opsqlite_libsql_execute(db, query, ¶ms);
|
|
370
382
|
#else
|
|
371
|
-
|
|
383
|
+
auto status = opsqlite_execute(db, query, ¶ms);
|
|
372
384
|
#endif
|
|
373
385
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
435
|
+
if (count == 2) {
|
|
436
|
+
const jsi::Value &originalParams = args[1];
|
|
437
|
+
params = to_variant_vec(rt, originalParams);
|
|
438
|
+
}
|
|
421
439
|
|
|
422
|
-
|
|
440
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
423
441
|
auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
-
|
|
434
|
-
|
|
451
|
+
auto status = opsqlite_libsql_execute_with_host_objects(
|
|
452
|
+
db, query, ¶ms, &results, metadata);
|
|
435
453
|
#else
|
|
436
|
-
|
|
437
|
-
|
|
454
|
+
auto status = opsqlite_execute_host_objects(
|
|
455
|
+
db, query, ¶ms, &results, metadata);
|
|
438
456
|
#endif
|
|
439
457
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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
|
-
|
|
510
|
+
const jsi::Value ¶ms = args[0];
|
|
488
511
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
|
|
518
|
+
const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
|
|
497
519
|
|
|
498
|
-
|
|
499
|
-
|
|
520
|
+
std::vector<BatchArguments> commands;
|
|
521
|
+
to_batch_arguments(rt, batchParams, &commands);
|
|
500
522
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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
|
-
|
|
513
|
-
|
|
531
|
+
auto batchResult =
|
|
532
|
+
opsqlite_libsql_execute_batch(db, &commands);
|
|
514
533
|
#else
|
|
515
|
-
|
|
534
|
+
auto batchResult = opsqlite_execute_batch(db, &commands);
|
|
516
535
|
#endif
|
|
517
536
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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
|
-
|
|
553
|
-
|
|
575
|
+
return promise;
|
|
576
|
+
});
|
|
554
577
|
|
|
555
578
|
#ifdef OP_SQLITE_USE_LIBSQL
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
579
|
+
function_map["sync"] = HOSTFN("sync") {
|
|
580
|
+
opsqlite_libsql_sync(db);
|
|
581
|
+
return {};
|
|
582
|
+
});
|
|
560
583
|
#else
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
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
|
-
|
|
591
|
+
const std::string sqlFileName = args[0].asString(rt).utf8(rt);
|
|
569
592
|
|
|
570
|
-
|
|
593
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
571
594
|
auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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
|
-
|
|
612
|
-
|
|
640
|
+
function_map["updateHook"] = HOSTFN("updateHook") {
|
|
641
|
+
auto callback = std::make_shared<jsi::Value>(rt, args[0]);
|
|
613
642
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
643
|
+
if (callback->isUndefined() || callback->isNull()) {
|
|
644
|
+
update_hook_callback = nullptr;
|
|
645
|
+
} else {
|
|
646
|
+
update_hook_callback = callback;
|
|
647
|
+
}
|
|
619
648
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
649
|
+
auto_register_update_hook();
|
|
650
|
+
return {};
|
|
651
|
+
});
|
|
623
652
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
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
|
-
|
|
638
|
-
|
|
666
|
+
return {};
|
|
667
|
+
});
|
|
639
668
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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
|
-
|
|
675
|
+
auto callback = std::make_shared<jsi::Value>(rt, args[0]);
|
|
646
676
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
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
|
-
|
|
654
|
-
|
|
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
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
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
|
-
|
|
704
|
-
|
|
705
|
-
|
|
734
|
+
std::shared_ptr<ReactiveQuery> reactiveQuery =
|
|
735
|
+
std::make_shared<ReactiveQuery>(
|
|
736
|
+
ReactiveQuery{stmt, discriminators, callback});
|
|
706
737
|
|
|
707
|
-
|
|
738
|
+
reactive_queries.push_back(reactiveQuery);
|
|
708
739
|
|
|
709
|
-
|
|
740
|
+
auto_register_update_hook();
|
|
710
741
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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
|
-
|
|
722
|
-
|
|
752
|
+
return unsubscribe;
|
|
753
|
+
});
|
|
723
754
|
#endif
|
|
724
755
|
|
|
725
|
-
|
|
726
|
-
|
|
756
|
+
function_map["prepareStatement"] = HOSTFN("prepareStatement") {
|
|
757
|
+
auto query = args[0].asString(rt).utf8(rt);
|
|
727
758
|
#ifdef OP_SQLITE_USE_LIBSQL
|
|
728
|
-
|
|
759
|
+
libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db, query);
|
|
729
760
|
#else
|
|
730
|
-
|
|
761
|
+
sqlite3_stmt *statement = opsqlite_prepare_statement(db, query);
|
|
731
762
|
#endif
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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
|
-
|
|
760
|
-
|
|
761
|
-
});
|
|
771
|
+
function_map["getDbPath"] = HOSTFN("getDbPath") {
|
|
772
|
+
std::string path = std::string(base_path);
|
|
762
773
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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
|
-
|
|
799
|
+
auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
|
|
768
800
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
801
|
+
auto task = [&rt, this, resolve]() {
|
|
802
|
+
flush_pending_reactive_queries(resolve);
|
|
803
|
+
};
|
|
772
804
|
|
|
773
|
-
|
|
805
|
+
_thread_pool->queueWork(task);
|
|
774
806
|
|
|
775
|
-
|
|
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
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
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
|
-
|
|
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
|
-
|
|
839
|
+
throw std::runtime_error("You cannot write to this object!");
|
|
808
840
|
}
|
|
809
841
|
|
|
810
842
|
void DBHostObject::invalidate() {
|
|
811
|
-
|
|
812
|
-
|
|
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
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
852
|
+
if (db != nullptr) {
|
|
853
|
+
opsqlite_close(db);
|
|
854
|
+
db = nullptr;
|
|
855
|
+
}
|
|
820
856
|
#endif
|
|
821
857
|
}
|
|
822
858
|
|