@op-engineering/op-sqlite 6.0.2-beta1 → 6.0.2-beta4
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/android/CMakeLists.txt +26 -15
- package/android/build.gradle +10 -1
- package/android/cpp-adapter.cpp +4 -0
- package/android/jniLibs/arm64-v8a/libsql_experimental.a +0 -0
- package/android/jniLibs/armeabi-v7a/libsql_experimental.a +0 -0
- package/android/jniLibs/x86/libsql_experimental.a +0 -0
- package/android/jniLibs/x86_64/libsql_experimental.a +0 -0
- package/cpp/DBHostObject.cpp +234 -87
- package/cpp/DBHostObject.h +19 -10
- package/cpp/PreparedStatementHostObject.cpp +28 -14
- package/cpp/PreparedStatementHostObject.h +18 -14
- package/cpp/bindings.cpp +49 -32
- package/cpp/bindings.h +4 -3
- package/cpp/bridge.cpp +45 -0
- package/cpp/bridge.h +3 -0
- package/cpp/libsql/bridge.cpp +660 -0
- package/cpp/libsql/bridge.h +76 -0
- package/cpp/libsql/libsql.h +133 -0
- package/cpp/sqlite3.h +0 -1
- package/cpp/types.h +5 -0
- package/cpp/utils.cpp +45 -3
- package/cpp/utils.h +2 -3
- package/ios/libsql.xcframework/Info.plist +48 -0
- package/ios/libsql.xcframework/ios-arm64/Headers/libsql.h +133 -0
- package/ios/libsql.xcframework/ios-arm64/libsql_experimental.a +0 -0
- package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/Headers/libsql.h +133 -0
- package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/libsql_experimental.a +0 -0
- package/lib/commonjs/index.js +167 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +164 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +14 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/op-sqlite.podspec +20 -3
- package/package.json +1 -1
- package/src/index.ts +209 -3
- package/cpp/sqlbatchexecutor.cpp +0 -93
- package/cpp/sqlbatchexecutor.h +0 -30
package/src/index.ts
CHANGED
|
@@ -180,8 +180,10 @@ export type DB = {
|
|
|
180
180
|
reactiveExecute: (params: {
|
|
181
181
|
query: string;
|
|
182
182
|
arguments: any[];
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
fireOn: {
|
|
184
|
+
table: string;
|
|
185
|
+
ids?: number[];
|
|
186
|
+
}[];
|
|
185
187
|
callback: (response: any) => void;
|
|
186
188
|
}) => () => void;
|
|
187
189
|
};
|
|
@@ -192,7 +194,9 @@ type OPSQLiteProxy = {
|
|
|
192
194
|
location?: string;
|
|
193
195
|
encryptionKey?: string;
|
|
194
196
|
}) => DB;
|
|
197
|
+
openRemote: (options: { url: string; authToken: string }) => DB;
|
|
195
198
|
isSQLCipher: () => boolean;
|
|
199
|
+
isLibsql: () => boolean;
|
|
196
200
|
};
|
|
197
201
|
|
|
198
202
|
const locks: Record<
|
|
@@ -216,6 +220,204 @@ function enhanceQueryResult(result: QueryResult): void {
|
|
|
216
220
|
}
|
|
217
221
|
}
|
|
218
222
|
|
|
223
|
+
// TODO de-dupe this function with open
|
|
224
|
+
export const openRemote = (options: { url: string; authToken: string }): DB => {
|
|
225
|
+
if (!isLibsql()) {
|
|
226
|
+
throw new Error('This function is only available for libsql');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const db = OPSQLite.openRemote(options);
|
|
230
|
+
|
|
231
|
+
const lock = {
|
|
232
|
+
queue: [] as PendingTransaction[],
|
|
233
|
+
inProgress: false,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const startNextTransaction = () => {
|
|
237
|
+
if (lock.inProgress) {
|
|
238
|
+
// Transaction is already in process bail out
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (lock.queue.length) {
|
|
243
|
+
lock.inProgress = true;
|
|
244
|
+
const tx = lock.queue.shift();
|
|
245
|
+
|
|
246
|
+
if (!tx) {
|
|
247
|
+
throw new Error('Could not get a operation on database');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
setImmediate(() => {
|
|
251
|
+
tx.start();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// spreading the object is not working, so we need to do it manually
|
|
257
|
+
let enhancedDb = {
|
|
258
|
+
delete: db.delete,
|
|
259
|
+
attach: db.attach,
|
|
260
|
+
detach: db.detach,
|
|
261
|
+
executeBatch: db.executeBatch,
|
|
262
|
+
executeBatchAsync: db.executeBatchAsync,
|
|
263
|
+
|
|
264
|
+
loadFile: db.loadFile,
|
|
265
|
+
updateHook: db.updateHook,
|
|
266
|
+
commitHook: db.commitHook,
|
|
267
|
+
rollbackHook: db.rollbackHook,
|
|
268
|
+
loadExtension: db.loadExtension,
|
|
269
|
+
executeRawAsync: db.executeRawAsync,
|
|
270
|
+
getDbPath: db.getDbPath,
|
|
271
|
+
reactiveExecute: db.reactiveExecute,
|
|
272
|
+
close: () => {
|
|
273
|
+
db.close();
|
|
274
|
+
delete locks[options.url];
|
|
275
|
+
},
|
|
276
|
+
execute: (query: string, params?: any[] | undefined): QueryResult => {
|
|
277
|
+
const sanitizedParams = params?.map((p) => {
|
|
278
|
+
if (ArrayBuffer.isView(p)) {
|
|
279
|
+
return p.buffer;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return p;
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const result = db.execute(query, sanitizedParams);
|
|
286
|
+
enhanceQueryResult(result);
|
|
287
|
+
return result;
|
|
288
|
+
},
|
|
289
|
+
executeAsync: async (
|
|
290
|
+
query: string,
|
|
291
|
+
params?: any[] | undefined
|
|
292
|
+
): Promise<QueryResult> => {
|
|
293
|
+
const sanitizedParams = params?.map((p) => {
|
|
294
|
+
if (ArrayBuffer.isView(p)) {
|
|
295
|
+
return p.buffer;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return p;
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const result = await db.executeAsync(query, sanitizedParams);
|
|
302
|
+
enhanceQueryResult(result);
|
|
303
|
+
return result;
|
|
304
|
+
},
|
|
305
|
+
prepareStatement: (query: string) => {
|
|
306
|
+
const stmt = db.prepareStatement(query);
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
bind: (params: any[]) => {
|
|
310
|
+
const sanitizedParams = params.map((p) => {
|
|
311
|
+
if (ArrayBuffer.isView(p)) {
|
|
312
|
+
return p.buffer;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return p;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
stmt.bind(sanitizedParams);
|
|
319
|
+
},
|
|
320
|
+
execute: () => {
|
|
321
|
+
const res = stmt.execute();
|
|
322
|
+
enhanceQueryResult(res);
|
|
323
|
+
return res;
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
},
|
|
327
|
+
transaction: async (
|
|
328
|
+
fn: (tx: Transaction) => Promise<void>
|
|
329
|
+
): Promise<void> => {
|
|
330
|
+
let isFinalized = false;
|
|
331
|
+
|
|
332
|
+
// Local transaction context object implementation
|
|
333
|
+
const execute = (query: string, params?: any[]): QueryResult => {
|
|
334
|
+
if (isFinalized) {
|
|
335
|
+
throw Error(
|
|
336
|
+
`OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return enhancedDb.execute(query, params);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const executeAsync = (query: string, params?: any[] | undefined) => {
|
|
343
|
+
if (isFinalized) {
|
|
344
|
+
throw Error(
|
|
345
|
+
`OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
return enhancedDb.executeAsync(query, params);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const commit = () => {
|
|
352
|
+
if (isFinalized) {
|
|
353
|
+
throw Error(
|
|
354
|
+
`OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
const result = enhancedDb.execute('COMMIT;');
|
|
358
|
+
isFinalized = true;
|
|
359
|
+
return result;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const rollback = () => {
|
|
363
|
+
if (isFinalized) {
|
|
364
|
+
throw Error(
|
|
365
|
+
`OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
const result = enhancedDb.execute('ROLLBACK;');
|
|
369
|
+
isFinalized = true;
|
|
370
|
+
return result;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
async function run() {
|
|
374
|
+
try {
|
|
375
|
+
await enhancedDb.executeAsync('BEGIN TRANSACTION;');
|
|
376
|
+
|
|
377
|
+
await fn({
|
|
378
|
+
commit,
|
|
379
|
+
execute,
|
|
380
|
+
executeAsync,
|
|
381
|
+
rollback,
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
if (!isFinalized) {
|
|
385
|
+
commit();
|
|
386
|
+
}
|
|
387
|
+
} catch (executionError) {
|
|
388
|
+
console.warn('transaction error', executionError);
|
|
389
|
+
if (!isFinalized) {
|
|
390
|
+
try {
|
|
391
|
+
rollback();
|
|
392
|
+
} catch (rollbackError) {
|
|
393
|
+
throw rollbackError;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
throw executionError;
|
|
398
|
+
} finally {
|
|
399
|
+
lock.inProgress = false;
|
|
400
|
+
isFinalized = false;
|
|
401
|
+
startNextTransaction();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return await new Promise((resolve, reject) => {
|
|
406
|
+
const tx: PendingTransaction = {
|
|
407
|
+
start: () => {
|
|
408
|
+
run().then(resolve).catch(reject);
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
lock.queue.push(tx);
|
|
413
|
+
startNextTransaction();
|
|
414
|
+
});
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
return enhancedDb;
|
|
419
|
+
};
|
|
420
|
+
|
|
219
421
|
export const open = (options: {
|
|
220
422
|
name: string;
|
|
221
423
|
location?: string;
|
|
@@ -375,7 +577,7 @@ export const open = (options: {
|
|
|
375
577
|
executeAsync,
|
|
376
578
|
rollback,
|
|
377
579
|
});
|
|
378
|
-
|
|
580
|
+
|
|
379
581
|
if (!isFinalized) {
|
|
380
582
|
commit();
|
|
381
583
|
}
|
|
@@ -424,3 +626,7 @@ export const moveAssetsDatabase = async (args: {
|
|
|
424
626
|
export const isSQLCipher = (): boolean => {
|
|
425
627
|
return OPSQLite.isSQLCipher();
|
|
426
628
|
};
|
|
629
|
+
|
|
630
|
+
export const isLibsql = (): boolean => {
|
|
631
|
+
return OPSQLite.isLibsql();
|
|
632
|
+
};
|
package/cpp/sqlbatchexecutor.cpp
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
#include "sqlbatchexecutor.h"
|
|
2
|
-
|
|
3
|
-
namespace opsqlite {
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Batch execution implementation
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
void toBatchArguments(jsi::Runtime &rt, jsi::Array const &batchParams,
|
|
10
|
-
std::vector<BatchArguments> *commands) {
|
|
11
|
-
for (int i = 0; i < batchParams.length(rt); i++) {
|
|
12
|
-
const jsi::Array &command =
|
|
13
|
-
batchParams.getValueAtIndex(rt, i).asObject(rt).asArray(rt);
|
|
14
|
-
if (command.length(rt) == 0) {
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const std::string query =
|
|
19
|
-
command.getValueAtIndex(rt, 0).asString(rt).utf8(rt);
|
|
20
|
-
const jsi::Value &commandParams = command.length(rt) > 1
|
|
21
|
-
? command.getValueAtIndex(rt, 1)
|
|
22
|
-
: jsi::Value::undefined();
|
|
23
|
-
if (!commandParams.isUndefined() &&
|
|
24
|
-
commandParams.asObject(rt).isArray(rt) &&
|
|
25
|
-
commandParams.asObject(rt).asArray(rt).length(rt) > 0 &&
|
|
26
|
-
commandParams.asObject(rt)
|
|
27
|
-
.asArray(rt)
|
|
28
|
-
.getValueAtIndex(rt, 0)
|
|
29
|
-
.isObject()) {
|
|
30
|
-
// This arguments is an array of arrays, like a batch update of a single
|
|
31
|
-
// sql command.
|
|
32
|
-
const jsi::Array &batchUpdateParams =
|
|
33
|
-
commandParams.asObject(rt).asArray(rt);
|
|
34
|
-
for (int x = 0; x < batchUpdateParams.length(rt); x++) {
|
|
35
|
-
const jsi::Value &p = batchUpdateParams.getValueAtIndex(rt, x);
|
|
36
|
-
auto params =
|
|
37
|
-
std::make_shared<std::vector<JSVariant>>(to_variant_vec(rt, p));
|
|
38
|
-
commands->push_back({query, params});
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
auto params = std::make_shared<std::vector<JSVariant>>(
|
|
42
|
-
to_variant_vec(rt, commandParams));
|
|
43
|
-
commands->push_back({query, params});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
BatchResult sqliteExecuteBatch(std::string dbName,
|
|
49
|
-
std::vector<BatchArguments> *commands) {
|
|
50
|
-
size_t commandCount = commands->size();
|
|
51
|
-
if (commandCount <= 0) {
|
|
52
|
-
return BatchResult{
|
|
53
|
-
.type = SQLiteError,
|
|
54
|
-
.message = "No SQL commands provided",
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
int affectedRows = 0;
|
|
60
|
-
opsqlite_execute(dbName, "BEGIN EXCLUSIVE TRANSACTION", nullptr, nullptr,
|
|
61
|
-
nullptr);
|
|
62
|
-
for (int i = 0; i < commandCount; i++) {
|
|
63
|
-
auto command = commands->at(i);
|
|
64
|
-
// We do not provide a datastructure to receive query data because we
|
|
65
|
-
// don't need/want to handle this results in a batch execution
|
|
66
|
-
auto result = opsqlite_execute(dbName, command.sql, command.params.get(),
|
|
67
|
-
nullptr, nullptr);
|
|
68
|
-
if (result.type == SQLiteError) {
|
|
69
|
-
opsqlite_execute(dbName, "ROLLBACK", nullptr, nullptr, nullptr);
|
|
70
|
-
return BatchResult{
|
|
71
|
-
.type = SQLiteError,
|
|
72
|
-
.message = result.message,
|
|
73
|
-
};
|
|
74
|
-
} else {
|
|
75
|
-
affectedRows += result.affectedRows;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
opsqlite_execute(dbName, "COMMIT", nullptr, nullptr, nullptr);
|
|
79
|
-
return BatchResult{
|
|
80
|
-
.type = SQLiteOk,
|
|
81
|
-
.affectedRows = affectedRows,
|
|
82
|
-
.commands = static_cast<int>(commandCount),
|
|
83
|
-
};
|
|
84
|
-
} catch (std::exception &exc) {
|
|
85
|
-
opsqlite_execute(dbName, "ROLLBACK", nullptr, nullptr, nullptr);
|
|
86
|
-
return BatchResult{
|
|
87
|
-
.type = SQLiteError,
|
|
88
|
-
.message = exc.what(),
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
} // namespace opsqlite
|
package/cpp/sqlbatchexecutor.h
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQL Batch execution implementation using default sqliteBridge implementation
|
|
3
|
-
*/
|
|
4
|
-
#include "bridge.h"
|
|
5
|
-
#include "types.h"
|
|
6
|
-
#include "utils.h"
|
|
7
|
-
|
|
8
|
-
namespace opsqlite {
|
|
9
|
-
|
|
10
|
-
namespace jsi = facebook::jsi;
|
|
11
|
-
|
|
12
|
-
struct BatchArguments {
|
|
13
|
-
std::string sql;
|
|
14
|
-
std::shared_ptr<std::vector<JSVariant>> params;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Local Helper method to translate JSI objects BatchArguments data structure
|
|
19
|
-
* MUST be called in the JavaScript Thread
|
|
20
|
-
*/
|
|
21
|
-
void toBatchArguments(jsi::Runtime &rt, jsi::Array const &batchParams,
|
|
22
|
-
std::vector<BatchArguments> *commands);
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Execute a batch of commands in a exclusive transaction
|
|
26
|
-
*/
|
|
27
|
-
BatchResult sqliteExecuteBatch(std::string dbName,
|
|
28
|
-
std::vector<BatchArguments> *commands);
|
|
29
|
-
|
|
30
|
-
} // namespace opsqlite
|