@op-engineering/op-sqlite 2.0.16 → 2.0.18
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/README.md +31 -5
- package/android/build.gradle +4 -0
- package/cpp/PreparedStatementHostObject.cpp +3 -3
- package/cpp/bindings.cpp +48 -44
- package/cpp/bridge.cpp +101 -129
- package/cpp/bridge.h +53 -49
- package/cpp/sqlbatchexecutor.cpp +6 -6
- package/cpp/sqlite3.c +5642 -2573
- package/cpp/sqlite3.h +127 -31
- package/cpp/utils.cpp +5 -5
- package/op-sqlite.podspec +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ yarn add @op-engineering/op-sqlite && npx pod-install
|
|
|
6
6
|
|
|
7
7
|
OP-SQLite embeds the latest version of SQLite and provides a low-level API to execute SQL queries.
|
|
8
8
|
|
|
9
|
-
**Current SQLite version: 3.
|
|
9
|
+
**Current SQLite version: 3.45.1**
|
|
10
10
|
|
|
11
11
|
Created by [@ospfranco](https://twitter.com/ospfranco). **Please consider sponsoring!**.
|
|
12
12
|
|
|
@@ -127,9 +127,9 @@ db.execute('PRAGMA journal_mode = MEMORY;'); // or OFF
|
|
|
127
127
|
|
|
128
128
|
If you use [prepared statements](#prepared-statements) are useful to reduce the time of critical queries.
|
|
129
129
|
|
|
130
|
-
# Perf
|
|
130
|
+
# Perf flags
|
|
131
131
|
|
|
132
|
-
You can turn on the performance flag to tweak all possible performance enhancing compilation flags, this greatly affects performance of sqlite itself
|
|
132
|
+
You can turn on the performance flag to tweak all possible performance enhancing compilation flags, this greatly affects performance of sqlite itself. Be aware this disables thread safety, you should only uses transactions (which operate based on a mutex in JS side) to avoid any issues.
|
|
133
133
|
|
|
134
134
|
```sh
|
|
135
135
|
# For iOS install pods with the following env variable, you can also just an export like on Android
|
|
@@ -147,6 +147,14 @@ If correctly set you should see the following output in your console
|
|
|
147
147
|
OP-SQLITE performance mode enabled! 🚀
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
If you want to keep SQLite thread safety based on mutexes, you can use OP_SQLITE_PERF=2. This flag will enable the general compilation flags, except DSQLITE_THREADSAFE=0.
|
|
151
|
+
If correctly set you should see the following output in your console
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
OP-SQLITE (thread safe) performance mode enabled! 🚀
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Here you can read more about [SQLite Thread Safe](https://www.sqlite.org/threadsafe.html)
|
|
150
158
|
# SQLite Gotchas
|
|
151
159
|
|
|
152
160
|
## Strictness
|
|
@@ -408,7 +416,7 @@ References: [Attach](https://www.sqlite.org/lang_attach.html) - [Detach](https:/
|
|
|
408
416
|
```ts
|
|
409
417
|
db.attach('mainDatabase', 'statistics', 'stats', '../databases');
|
|
410
418
|
|
|
411
|
-
const res = db.
|
|
419
|
+
const res = db.execute(
|
|
412
420
|
'mainDatabase',
|
|
413
421
|
'SELECT * FROM some_table_from_mainschema a INNER JOIN stats.some_table b on a.id_column = b.id_column'
|
|
414
422
|
);
|
|
@@ -502,7 +510,7 @@ On iOS you can use the embedded SQLite, when running `pod-install` add an enviro
|
|
|
502
510
|
OP_SQLITE_USE_PHONE_VERSION=1 npx pod-install
|
|
503
511
|
```
|
|
504
512
|
|
|
505
|
-
On Android, it is not possible to link the OS SQLite. It is also a bad idea due to vendor changes, old android bugs, etc. Unfortunately, this means this library will add some megabytes to your app size.
|
|
513
|
+
On Android, it is not possible to link the OS SQLite. It is also a bad idea due to vendor changes, old android bugs, etc. Unfortunately, this means this library will add some megabytes to your app size. Take note that the embedded version of SQLite does not support loading runtime extensions due to security concerns from apple.
|
|
506
514
|
|
|
507
515
|
# Enable compile-time options
|
|
508
516
|
|
|
@@ -553,6 +561,24 @@ On iOS, the SQLite database can be placed in an app group, in order to make it a
|
|
|
553
561
|
|
|
554
562
|
To use an app group, add the app group ID as the value for the `OPSQLite_AppGroup` key in your project's `Info.plist` file. You'll also need to configure the app group in your project settings. (Xcode -> Project Settings -> Signing & Capabilities -> Add Capability -> App Groups)
|
|
555
563
|
|
|
564
|
+
## use_frameworks
|
|
565
|
+
|
|
566
|
+
If you are using `use_frameworks` (because one of your dependencies requires e.g. firebase), you might get a linking error since the OS version will try to be linked instead of the version compiled directly from sources. In order to get around this you can add the following into your Podfile:
|
|
567
|
+
|
|
568
|
+
```ruby
|
|
569
|
+
pre_install do |installer|
|
|
570
|
+
installer.pod_targets.each do |pod|
|
|
571
|
+
if pod.name.eql?('op-sqlite')
|
|
572
|
+
def pod.build_type
|
|
573
|
+
Pod::BuildType.static_library
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
It will change the type of library only for op-sqlite only to static. This should be fine as SQLite is compiled from sources, so no missing symbols should be there.
|
|
581
|
+
|
|
556
582
|
# Contribute
|
|
557
583
|
|
|
558
584
|
You need to have clang-format installed (`brew install clang-format`)
|
package/android/build.gradle
CHANGED
|
@@ -80,6 +80,10 @@ android {
|
|
|
80
80
|
println "OP-SQLITE performance mode enabled! 🚀"
|
|
81
81
|
cFlags "-DSQLITE_DQS=0", "-DSQLITE_THREADSAFE=0", "-DSQLITE_DEFAULT_MEMSTATUS=0", "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1", "-DSQLITE_MAX_EXPR_DEPTH=0", "-DSQLITE_OMIT_DEPRECATED=1", "-DSQLITE_OMIT_PROGRESS_CALLBACK=1", "-DSQLITE_OMIT_SHARED_CACHE=1", "-DSQLITE_USE_ALLOCA=1"
|
|
82
82
|
}
|
|
83
|
+
if(System.getenv("OP_SQLITE_PERF") == '2') {
|
|
84
|
+
println "OP-SQLITE (thread safe) performance mode enabled! 🚀"
|
|
85
|
+
cFlags "-DSQLITE_DQS=0", "-DSQLITE_THREADSAFE=1", "-DSQLITE_DEFAULT_MEMSTATUS=0", "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1", "-DSQLITE_MAX_EXPR_DEPTH=0", "-DSQLITE_OMIT_DEPRECATED=1", "-DSQLITE_OMIT_PROGRESS_CALLBACK=1", "-DSQLITE_OMIT_SHARED_CACHE=1", "-DSQLITE_USE_ALLOCA=1"
|
|
86
|
+
}
|
|
83
87
|
cppFlags "-O2", "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID"
|
|
84
88
|
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
|
85
89
|
arguments '-DANDROID_STL=c++_shared',
|
|
@@ -38,7 +38,7 @@ jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt,
|
|
|
38
38
|
const jsi::Value &js_params = args[0];
|
|
39
39
|
std::vector<JSVariant> params = toVariantVec(rt, js_params);
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
opsqlite_bind_statement(_statement, ¶ms);
|
|
42
42
|
|
|
43
43
|
return {};
|
|
44
44
|
});
|
|
@@ -53,8 +53,8 @@ jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt,
|
|
|
53
53
|
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
54
54
|
std::make_shared<std::vector<SmartHostObject>>();
|
|
55
55
|
|
|
56
|
-
auto status =
|
|
57
|
-
|
|
56
|
+
auto status = opsqlite_execute_prepared_statement(_dbName, _statement,
|
|
57
|
+
&results, metadata);
|
|
58
58
|
|
|
59
59
|
if (status.type == SQLiteError) {
|
|
60
60
|
throw std::runtime_error(status.message);
|
package/cpp/bindings.cpp
CHANGED
|
@@ -35,7 +35,7 @@ bool invalidated = false;
|
|
|
35
35
|
void clearState() {
|
|
36
36
|
invalidated = true;
|
|
37
37
|
// Will terminate all operations and database connections
|
|
38
|
-
|
|
38
|
+
opsqlite_close_all();
|
|
39
39
|
// We then join all the threads before the context gets invalidated
|
|
40
40
|
pool.restartPool();
|
|
41
41
|
updateHooks.clear();
|
|
@@ -80,7 +80,7 @@ void install(jsi::Runtime &rt,
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
BridgeResult result =
|
|
83
|
+
BridgeResult result = opsqlite_open(dbName, path);
|
|
84
84
|
|
|
85
85
|
if (result.type == SQLiteError) {
|
|
86
86
|
throw std::runtime_error(result.message);
|
|
@@ -114,7 +114,7 @@ void install(jsi::Runtime &rt,
|
|
|
114
114
|
std::string databaseToAttach = args[1].asString(rt).utf8(rt);
|
|
115
115
|
std::string alias = args[2].asString(rt).utf8(rt);
|
|
116
116
|
BridgeResult result =
|
|
117
|
-
|
|
117
|
+
opsqlite_attach(dbName, tempDocPath, databaseToAttach, alias);
|
|
118
118
|
|
|
119
119
|
if (result.type == SQLiteError) {
|
|
120
120
|
throw std::runtime_error(result.message);
|
|
@@ -136,7 +136,7 @@ void install(jsi::Runtime &rt,
|
|
|
136
136
|
|
|
137
137
|
std::string dbName = args[0].asString(rt).utf8(rt);
|
|
138
138
|
std::string alias = args[1].asString(rt).utf8(rt);
|
|
139
|
-
BridgeResult result =
|
|
139
|
+
BridgeResult result = opsqlite_detach(dbName, alias);
|
|
140
140
|
|
|
141
141
|
if (result.type == SQLiteError) {
|
|
142
142
|
throw jsi::JSError(rt, result.message.c_str());
|
|
@@ -157,7 +157,7 @@ void install(jsi::Runtime &rt,
|
|
|
157
157
|
|
|
158
158
|
std::string dbName = args[0].asString(rt).utf8(rt);
|
|
159
159
|
|
|
160
|
-
BridgeResult result =
|
|
160
|
+
BridgeResult result = opsqlite_close(dbName);
|
|
161
161
|
|
|
162
162
|
if (result.type == SQLiteError) {
|
|
163
163
|
throw jsi::JSError(rt, result.message.c_str());
|
|
@@ -189,7 +189,7 @@ void install(jsi::Runtime &rt,
|
|
|
189
189
|
tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
BridgeResult result =
|
|
192
|
+
BridgeResult result = opsqlite_remove(dbName, tempDocPath);
|
|
193
193
|
|
|
194
194
|
if (result.type == SQLiteError) {
|
|
195
195
|
throw std::runtime_error(result.message);
|
|
@@ -212,7 +212,7 @@ void install(jsi::Runtime &rt,
|
|
|
212
212
|
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
213
213
|
std::make_shared<std::vector<SmartHostObject>>();
|
|
214
214
|
|
|
215
|
-
auto status =
|
|
215
|
+
auto status = opsqlite_execute(dbName, query, ¶ms, &results, metadata);
|
|
216
216
|
|
|
217
217
|
if (status.type == SQLiteError) {
|
|
218
218
|
throw std::runtime_error(status.message);
|
|
@@ -245,7 +245,7 @@ void install(jsi::Runtime &rt,
|
|
|
245
245
|
try {
|
|
246
246
|
std::vector<std::vector<JSVariant>> results;
|
|
247
247
|
|
|
248
|
-
auto status =
|
|
248
|
+
auto status = opsqlite_execute_raw(dbName, query, ¶ms, &results);
|
|
249
249
|
|
|
250
250
|
if (invalidated) {
|
|
251
251
|
return;
|
|
@@ -309,7 +309,7 @@ void install(jsi::Runtime &rt,
|
|
|
309
309
|
std::make_shared<std::vector<SmartHostObject>>();
|
|
310
310
|
|
|
311
311
|
auto status =
|
|
312
|
-
|
|
312
|
+
opsqlite_execute(dbName, query, ¶ms, &results, metadata);
|
|
313
313
|
|
|
314
314
|
if (invalidated) {
|
|
315
315
|
return;
|
|
@@ -410,18 +410,20 @@ void install(jsi::Runtime &rt,
|
|
|
410
410
|
resolve, reject]() {
|
|
411
411
|
try {
|
|
412
412
|
auto batchResult = sqliteExecuteBatch(dbName, commands.get());
|
|
413
|
-
invoker->invokeAsync(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
413
|
+
invoker->invokeAsync([&rt, batchResult = std::move(batchResult),
|
|
414
|
+
resolve, reject] {
|
|
415
|
+
if (batchResult.type == SQLiteOk) {
|
|
416
|
+
auto res = jsi::Object(rt);
|
|
417
|
+
res.setProperty(rt, "rowsAffected",
|
|
418
|
+
jsi::Value(batchResult.affectedRows));
|
|
419
|
+
resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
|
|
420
|
+
} else {
|
|
421
|
+
auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
|
|
422
|
+
auto error = errorCtr.callAsConstructor(
|
|
423
|
+
rt, jsi::String::createFromUtf8(rt, batchResult.message));
|
|
424
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
425
427
|
} catch (std::exception &exc) {
|
|
426
428
|
invoker->invokeAsync(
|
|
427
429
|
[&rt, reject, &exc] { throw jsi::JSError(rt, exc.what()); });
|
|
@@ -438,7 +440,7 @@ void install(jsi::Runtime &rt,
|
|
|
438
440
|
auto load_file = HOSTFN("loadFile", 2) {
|
|
439
441
|
if (sizeof(args) < 2) {
|
|
440
442
|
throw std::runtime_error(
|
|
441
|
-
"[op-sqlite][
|
|
443
|
+
"[op-sqlite][loadFile] Incorrect parameter count");
|
|
442
444
|
return {};
|
|
443
445
|
}
|
|
444
446
|
|
|
@@ -454,18 +456,21 @@ void install(jsi::Runtime &rt,
|
|
|
454
456
|
try {
|
|
455
457
|
const auto importResult = importSQLFile(dbName, sqlFileName);
|
|
456
458
|
|
|
457
|
-
invoker->invokeAsync(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
459
|
+
invoker->invokeAsync([&rt, result = std::move(importResult), resolve,
|
|
460
|
+
reject] {
|
|
461
|
+
if (result.type == SQLiteOk) {
|
|
462
|
+
auto res = jsi::Object(rt);
|
|
463
|
+
res.setProperty(rt, "rowsAffected",
|
|
464
|
+
jsi::Value(result.affectedRows));
|
|
465
|
+
res.setProperty(rt, "commands", jsi::Value(result.commands));
|
|
466
|
+
resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
|
|
467
|
+
} else {
|
|
468
|
+
auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
|
|
469
|
+
auto error = errorCtr.callAsConstructor(
|
|
470
|
+
rt, jsi::String::createFromUtf8(rt, result.message));
|
|
471
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
472
|
+
}
|
|
473
|
+
});
|
|
469
474
|
} catch (std::exception &exc) {
|
|
470
475
|
invoker->invokeAsync(
|
|
471
476
|
[&rt, err = exc.what(), reject] { throw jsi::JSError(rt, err); });
|
|
@@ -489,7 +494,7 @@ void install(jsi::Runtime &rt,
|
|
|
489
494
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
490
495
|
|
|
491
496
|
if (callback->isUndefined() || callback->isNull()) {
|
|
492
|
-
|
|
497
|
+
opsqlite_deregister_update_hook(dbName);
|
|
493
498
|
return {};
|
|
494
499
|
}
|
|
495
500
|
|
|
@@ -501,12 +506,11 @@ void install(jsi::Runtime &rt,
|
|
|
501
506
|
std::vector<DumbHostObject> results;
|
|
502
507
|
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
503
508
|
std::make_shared<std::vector<SmartHostObject>>();
|
|
504
|
-
;
|
|
505
509
|
|
|
506
510
|
if (operation != "DELETE") {
|
|
507
511
|
std::string query = "SELECT * FROM " + tableName +
|
|
508
512
|
" where rowid = " + std::to_string(rowId) + ";";
|
|
509
|
-
|
|
513
|
+
opsqlite_execute(dbName, query, ¶ms, &results, metadata);
|
|
510
514
|
}
|
|
511
515
|
|
|
512
516
|
invoker->invokeAsync(
|
|
@@ -531,7 +535,7 @@ void install(jsi::Runtime &rt,
|
|
|
531
535
|
});
|
|
532
536
|
};
|
|
533
537
|
|
|
534
|
-
|
|
538
|
+
opsqlite_register_update_hook(dbName, std::move(hook));
|
|
535
539
|
|
|
536
540
|
return {};
|
|
537
541
|
});
|
|
@@ -546,7 +550,7 @@ void install(jsi::Runtime &rt,
|
|
|
546
550
|
auto dbName = args[0].asString(rt).utf8(rt);
|
|
547
551
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
548
552
|
if (callback->isUndefined() || callback->isNull()) {
|
|
549
|
-
|
|
553
|
+
opsqlite_deregister_commit_hook(dbName);
|
|
550
554
|
return {};
|
|
551
555
|
}
|
|
552
556
|
commitHooks[dbName] = callback;
|
|
@@ -556,7 +560,7 @@ void install(jsi::Runtime &rt,
|
|
|
556
560
|
[&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
|
|
557
561
|
};
|
|
558
562
|
|
|
559
|
-
|
|
563
|
+
opsqlite_register_commit_hook(dbName, std::move(hook));
|
|
560
564
|
|
|
561
565
|
return {};
|
|
562
566
|
});
|
|
@@ -573,7 +577,7 @@ void install(jsi::Runtime &rt,
|
|
|
573
577
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
574
578
|
|
|
575
579
|
if (callback->isUndefined() || callback->isNull()) {
|
|
576
|
-
|
|
580
|
+
opsqlite_deregister_rollback_hook(dbName);
|
|
577
581
|
return {};
|
|
578
582
|
}
|
|
579
583
|
rollbackHooks[dbName] = callback;
|
|
@@ -583,7 +587,7 @@ void install(jsi::Runtime &rt,
|
|
|
583
587
|
[&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
|
|
584
588
|
};
|
|
585
589
|
|
|
586
|
-
|
|
590
|
+
opsqlite_register_rollback_hook(dbName, std::move(hook));
|
|
587
591
|
return {};
|
|
588
592
|
});
|
|
589
593
|
|
|
@@ -591,7 +595,7 @@ void install(jsi::Runtime &rt,
|
|
|
591
595
|
auto dbName = args[0].asString(rt).utf8(rt);
|
|
592
596
|
auto query = args[1].asString(rt).utf8(rt);
|
|
593
597
|
|
|
594
|
-
sqlite3_stmt *statement =
|
|
598
|
+
sqlite3_stmt *statement = opsqlite_prepare_statement(dbName, query);
|
|
595
599
|
|
|
596
600
|
auto preparedStatementHostObject =
|
|
597
601
|
std::make_shared<PreparedStatementHostObject>(dbName, statement);
|
|
@@ -607,7 +611,7 @@ void install(jsi::Runtime &rt,
|
|
|
607
611
|
entryPoint = args[2].asString(rt).utf8(rt);
|
|
608
612
|
}
|
|
609
613
|
|
|
610
|
-
auto result =
|
|
614
|
+
auto result = opsqlite_load_extension(db_name, path, entryPoint);
|
|
611
615
|
if (result.type == SQLiteError) {
|
|
612
616
|
throw std::runtime_error(result.message);
|
|
613
617
|
}
|