@op-engineering/op-sqlite 3.0.1 → 3.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 +22 -11
- package/cpp/bridge.cpp +96 -99
- package/cpp/bridge.h +6 -3
- package/cpp/types.h +1 -0
- package/cpp/utils.cpp +37 -0
- package/cpp/utils.h +4 -0
- package/op-sqlite.podspec +1 -1
- package/package.json +1 -1
package/cpp/bindings.cpp
CHANGED
|
@@ -511,8 +511,7 @@ void install(jsi::Runtime &rt,
|
|
|
511
511
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
512
512
|
|
|
513
513
|
if (callback->isUndefined() || callback->isNull()) {
|
|
514
|
-
|
|
515
|
-
return {};
|
|
514
|
+
throw std::runtime_error("[op-sqlite][updateHook] callback is required");
|
|
516
515
|
}
|
|
517
516
|
|
|
518
517
|
updateHooks[dbName] = callback;
|
|
@@ -552,9 +551,13 @@ void install(jsi::Runtime &rt,
|
|
|
552
551
|
});
|
|
553
552
|
};
|
|
554
553
|
|
|
555
|
-
|
|
554
|
+
auto register_result =
|
|
555
|
+
opsqlite_register_update_hook(dbName, std::move(hook));
|
|
556
556
|
|
|
557
|
-
return {
|
|
557
|
+
return HOSTFN("remove", 0) {
|
|
558
|
+
opsqlite_deregister_update_hook(dbName, register_result.identifier);
|
|
559
|
+
return {};
|
|
560
|
+
});
|
|
558
561
|
});
|
|
559
562
|
|
|
560
563
|
auto commit_hook = HOSTFN("commitHook", 2) {
|
|
@@ -567,8 +570,7 @@ void install(jsi::Runtime &rt,
|
|
|
567
570
|
auto dbName = args[0].asString(rt).utf8(rt);
|
|
568
571
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
569
572
|
if (callback->isUndefined() || callback->isNull()) {
|
|
570
|
-
|
|
571
|
-
return {};
|
|
573
|
+
throw std::runtime_error("Callback is needed");
|
|
572
574
|
}
|
|
573
575
|
commitHooks[dbName] = callback;
|
|
574
576
|
|
|
@@ -577,9 +579,13 @@ void install(jsi::Runtime &rt,
|
|
|
577
579
|
[&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
|
|
578
580
|
};
|
|
579
581
|
|
|
580
|
-
|
|
582
|
+
auto register_result =
|
|
583
|
+
opsqlite_register_commit_hook(dbName, std::move(hook));
|
|
581
584
|
|
|
582
|
-
return {
|
|
585
|
+
return HOSTFN("remove", 0) {
|
|
586
|
+
opsqlite_deregister_commit_hook(dbName, register_result.identifier);
|
|
587
|
+
return {};
|
|
588
|
+
});
|
|
583
589
|
});
|
|
584
590
|
|
|
585
591
|
auto rollback_hook = HOSTFN("rollbackHook", 2) {
|
|
@@ -594,7 +600,7 @@ void install(jsi::Runtime &rt,
|
|
|
594
600
|
auto callback = std::make_shared<jsi::Value>(rt, args[1]);
|
|
595
601
|
|
|
596
602
|
if (callback->isUndefined() || callback->isNull()) {
|
|
597
|
-
|
|
603
|
+
throw std::runtime_error("Callback is needed");
|
|
598
604
|
return {};
|
|
599
605
|
}
|
|
600
606
|
rollbackHooks[dbName] = callback;
|
|
@@ -604,8 +610,13 @@ void install(jsi::Runtime &rt,
|
|
|
604
610
|
[&rt, callback] { callback->asObject(rt).asFunction(rt).call(rt); });
|
|
605
611
|
};
|
|
606
612
|
|
|
607
|
-
|
|
608
|
-
|
|
613
|
+
auto register_result =
|
|
614
|
+
opsqlite_register_rollback_hook(dbName, std::move(hook));
|
|
615
|
+
|
|
616
|
+
return HOSTFN("remove", 0) {
|
|
617
|
+
opsqlite_deregister_rollback_hook(dbName, register_result.identifier);
|
|
618
|
+
return {};
|
|
619
|
+
});
|
|
609
620
|
});
|
|
610
621
|
|
|
611
622
|
auto prepare_statement = HOSTFN("prepareStatement", 1) {
|
package/cpp/bridge.cpp
CHANGED
|
@@ -8,17 +8,25 @@
|
|
|
8
8
|
|
|
9
9
|
namespace opsqlite {
|
|
10
10
|
|
|
11
|
+
// TODO this has gotten unweildy, using a HostObject abstraction would be better
|
|
11
12
|
/// Maps to hold the different objects
|
|
12
13
|
std::unordered_map<std::string, sqlite3 *> dbMap =
|
|
13
14
|
std::unordered_map<std::string, sqlite3 *>();
|
|
14
|
-
std::unordered_map<std::string, UpdateCallback
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
std::unordered_map<std::string,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
std::unordered_map<std::string, std::unordered_map<std::string, UpdateCallback>>
|
|
16
|
+
updateCallbackMap =
|
|
17
|
+
std::unordered_map<std::string,
|
|
18
|
+
std::unordered_map<std::string, UpdateCallback>>();
|
|
19
|
+
|
|
20
|
+
std::unordered_map<std::string, std::unordered_map<std::string, CommitCallback>>
|
|
21
|
+
commitCallbackMap =
|
|
22
|
+
std::unordered_map<std::string,
|
|
23
|
+
std::unordered_map<std::string, CommitCallback>>();
|
|
24
|
+
|
|
25
|
+
std::unordered_map<std::string,
|
|
26
|
+
std::unordered_map<std::string, RollbackCallback>>
|
|
27
|
+
rollbackCallbackMap =
|
|
28
|
+
std::unordered_map<std::string,
|
|
29
|
+
std::unordered_map<std::string, RollbackCallback>>();
|
|
22
30
|
|
|
23
31
|
inline void check_db_open(std::string const &db_name) {
|
|
24
32
|
if (dbMap.count(db_name) == 0) {
|
|
@@ -26,6 +34,38 @@ inline void check_db_open(std::string const &db_name) {
|
|
|
26
34
|
}
|
|
27
35
|
}
|
|
28
36
|
|
|
37
|
+
// Hook native callbacks
|
|
38
|
+
void update_callback(void *user_data, int operation_type, char const *database,
|
|
39
|
+
char const *table, sqlite3_int64 rowid) {
|
|
40
|
+
std::string db_name(database);
|
|
41
|
+
auto callbacks = updateCallbackMap[db_name];
|
|
42
|
+
// iterate over the callback map and call them
|
|
43
|
+
|
|
44
|
+
for (auto &cb : callbacks) {
|
|
45
|
+
cb.second(db_name, std::string(table),
|
|
46
|
+
sqlite_operation_to_string(operation_type),
|
|
47
|
+
static_cast<long long>(rowid));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
int commit_callback(void *database) {
|
|
52
|
+
std::string db_name(static_cast<char const *>(database));
|
|
53
|
+
auto callbacks = commitCallbackMap[db_name];
|
|
54
|
+
for (auto &cb : callbacks) {
|
|
55
|
+
cb.second(db_name);
|
|
56
|
+
}
|
|
57
|
+
// You need to return 0 to allow commits to continue
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void rollback_callback(void *database) {
|
|
62
|
+
std::string db_name(static_cast<char const *>(database));
|
|
63
|
+
auto callbacks = rollbackCallbackMap[db_name];
|
|
64
|
+
for (auto &cb : callbacks) {
|
|
65
|
+
cb.second(db_name);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
29
69
|
/// Start of api
|
|
30
70
|
|
|
31
71
|
/// Returns the completely formed db path, but it also creates any sub-folders
|
|
@@ -69,6 +109,12 @@ BridgeResult opsqlite_open(std::string const &dbName,
|
|
|
69
109
|
nullptr, nullptr);
|
|
70
110
|
#endif
|
|
71
111
|
|
|
112
|
+
// On connection we register the native hooks, so on JS people can create
|
|
113
|
+
// reactive queries and their own hooks
|
|
114
|
+
sqlite3_update_hook(db, &update_callback, nullptr);
|
|
115
|
+
sqlite3_commit_hook(db, &commit_callback, nullptr);
|
|
116
|
+
sqlite3_rollback_hook(db, &rollback_callback, nullptr);
|
|
117
|
+
|
|
72
118
|
return BridgeResult{.type = SQLiteOk, .affectedRows = 0};
|
|
73
119
|
}
|
|
74
120
|
|
|
@@ -684,132 +730,83 @@ void opsqlite_close_all() {
|
|
|
684
730
|
commitCallbackMap.clear();
|
|
685
731
|
}
|
|
686
732
|
|
|
687
|
-
std::string
|
|
688
|
-
switch (operation_type) {
|
|
689
|
-
case SQLITE_INSERT:
|
|
690
|
-
return "INSERT";
|
|
691
|
-
|
|
692
|
-
case SQLITE_DELETE:
|
|
693
|
-
return "DELETE";
|
|
694
|
-
|
|
695
|
-
case SQLITE_UPDATE:
|
|
696
|
-
return "UPDATE";
|
|
697
|
-
|
|
698
|
-
default:
|
|
699
|
-
throw std::invalid_argument("Uknown SQLite operation on hook");
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
void update_callback(void *dbName, int operation_type, char const *database,
|
|
704
|
-
char const *table, sqlite3_int64 rowid) {
|
|
705
|
-
std::string &strDbName = *(static_cast<std::string *>(dbName));
|
|
706
|
-
auto callback = updateCallbackMap[strDbName];
|
|
707
|
-
callback(strDbName, std::string(table), operation_to_string(operation_type),
|
|
708
|
-
static_cast<int>(rowid));
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
BridgeResult opsqlite_register_update_hook(std::string const &dbName,
|
|
733
|
+
BridgeResult opsqlite_register_update_hook(std::string const &db_name,
|
|
712
734
|
UpdateCallback const callback) {
|
|
713
|
-
check_db_open(
|
|
735
|
+
check_db_open(db_name);
|
|
714
736
|
|
|
715
|
-
sqlite3 *db = dbMap[
|
|
716
|
-
|
|
717
|
-
const std::string *key = nullptr;
|
|
737
|
+
sqlite3 *db = dbMap[db_name];
|
|
738
|
+
std::string id = get_uuid();
|
|
718
739
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
key = &element.first;
|
|
723
|
-
}
|
|
740
|
+
if (!updateCallbackMap.count(db_name)) {
|
|
741
|
+
updateCallbackMap[db_name] =
|
|
742
|
+
std::unordered_map<std::string, UpdateCallback>();
|
|
724
743
|
}
|
|
725
744
|
|
|
726
|
-
|
|
745
|
+
updateCallbackMap[db_name][id] = callback;
|
|
727
746
|
|
|
728
|
-
return {SQLiteOk};
|
|
747
|
+
return {.type = SQLiteOk, .identifier = id};
|
|
729
748
|
}
|
|
730
749
|
|
|
731
|
-
BridgeResult opsqlite_deregister_update_hook(std::string const &
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
updateCallbackMap.erase(dbName);
|
|
736
|
-
|
|
737
|
-
sqlite3_update_hook(db, NULL, NULL);
|
|
750
|
+
BridgeResult opsqlite_deregister_update_hook(std::string const &db_name,
|
|
751
|
+
std::string const &id) {
|
|
752
|
+
check_db_open(db_name);
|
|
753
|
+
updateCallbackMap[db_name].erase(id);
|
|
738
754
|
|
|
739
755
|
return {SQLiteOk};
|
|
740
756
|
}
|
|
741
757
|
|
|
742
|
-
|
|
743
|
-
std::string &strDbName = *(static_cast<std::string *>(dbName));
|
|
744
|
-
auto callback = commitCallbackMap[strDbName];
|
|
745
|
-
callback(strDbName);
|
|
746
|
-
// You need to return 0 to allow commits to continue
|
|
747
|
-
return 0;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
BridgeResult opsqlite_register_commit_hook(std::string const &dbName,
|
|
758
|
+
BridgeResult opsqlite_register_commit_hook(std::string const &db_name,
|
|
751
759
|
CommitCallback const callback) {
|
|
752
|
-
check_db_open(
|
|
760
|
+
check_db_open(db_name);
|
|
753
761
|
|
|
754
|
-
sqlite3 *db = dbMap[
|
|
755
|
-
|
|
756
|
-
const std::string *key = nullptr;
|
|
762
|
+
sqlite3 *db = dbMap[db_name];
|
|
763
|
+
std::string id = get_uuid();
|
|
757
764
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
key = &element.first;
|
|
762
|
-
}
|
|
765
|
+
if (!commitCallbackMap.count(db_name)) {
|
|
766
|
+
commitCallbackMap[db_name] =
|
|
767
|
+
std::unordered_map<std::string, CommitCallback>();
|
|
763
768
|
}
|
|
764
769
|
|
|
765
|
-
|
|
770
|
+
commitCallbackMap[db_name][id] = callback;
|
|
766
771
|
|
|
767
|
-
return {SQLiteOk};
|
|
772
|
+
return {.type = SQLiteOk, .identifier = id};
|
|
768
773
|
}
|
|
769
774
|
|
|
770
|
-
BridgeResult opsqlite_deregister_commit_hook(std::string const &
|
|
771
|
-
|
|
775
|
+
BridgeResult opsqlite_deregister_commit_hook(std::string const &db_name,
|
|
776
|
+
std::string const &id) {
|
|
777
|
+
check_db_open(db_name);
|
|
772
778
|
|
|
773
|
-
sqlite3 *db = dbMap[
|
|
774
|
-
commitCallbackMap.erase(
|
|
779
|
+
sqlite3 *db = dbMap[db_name];
|
|
780
|
+
commitCallbackMap[db_name].erase(id);
|
|
775
781
|
sqlite3_commit_hook(db, NULL, NULL);
|
|
776
782
|
|
|
777
783
|
return {SQLiteOk};
|
|
778
784
|
}
|
|
779
785
|
|
|
780
|
-
|
|
781
|
-
std::string &strDbName = *(static_cast<std::string *>(dbName));
|
|
782
|
-
auto callback = rollbackCallbackMap[strDbName];
|
|
783
|
-
callback(strDbName);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
BridgeResult opsqlite_register_rollback_hook(std::string const &dbName,
|
|
786
|
+
BridgeResult opsqlite_register_rollback_hook(std::string const &db_name,
|
|
787
787
|
RollbackCallback const callback) {
|
|
788
|
-
check_db_open(
|
|
788
|
+
check_db_open(db_name);
|
|
789
789
|
|
|
790
|
-
sqlite3 *db = dbMap[
|
|
791
|
-
|
|
792
|
-
const std::string *key = nullptr;
|
|
790
|
+
sqlite3 *db = dbMap[db_name];
|
|
791
|
+
std::string id = get_uuid();
|
|
793
792
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
key = &element.first;
|
|
798
|
-
}
|
|
793
|
+
if (!rollbackCallbackMap.count(db_name)) {
|
|
794
|
+
rollbackCallbackMap[db_name] =
|
|
795
|
+
std::unordered_map<std::string, RollbackCallback>();
|
|
799
796
|
}
|
|
800
797
|
|
|
801
|
-
|
|
798
|
+
rollbackCallbackMap[db_name][id] = callback;
|
|
802
799
|
|
|
803
|
-
return {SQLiteOk};
|
|
800
|
+
return {.type = SQLiteOk, .identifier = id};
|
|
804
801
|
}
|
|
805
802
|
|
|
806
|
-
BridgeResult opsqlite_deregister_rollback_hook(std::string const &
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
sqlite3 *db = dbMap[dbName];
|
|
810
|
-
rollbackCallbackMap.erase(dbName);
|
|
803
|
+
BridgeResult opsqlite_deregister_rollback_hook(std::string const &db_name,
|
|
804
|
+
std::string const &id) {
|
|
805
|
+
check_db_open(db_name);
|
|
811
806
|
|
|
812
|
-
|
|
807
|
+
sqlite3 *db = dbMap[db_name];
|
|
808
|
+
rollbackCallbackMap[db_name].erase(id);
|
|
809
|
+
sqlite3_commit_hook(db, NULL, NULL);
|
|
813
810
|
|
|
814
811
|
return {SQLiteOk};
|
|
815
812
|
}
|
package/cpp/bridge.h
CHANGED
|
@@ -58,13 +58,16 @@ void opsqlite_close_all();
|
|
|
58
58
|
|
|
59
59
|
BridgeResult opsqlite_register_update_hook(std::string const &dbName,
|
|
60
60
|
UpdateCallback const callback);
|
|
61
|
-
BridgeResult opsqlite_deregister_update_hook(std::string const &dbName
|
|
61
|
+
BridgeResult opsqlite_deregister_update_hook(std::string const &dbName,
|
|
62
|
+
std::string const &id);
|
|
62
63
|
BridgeResult opsqlite_register_commit_hook(std::string const &dbName,
|
|
63
64
|
CommitCallback const callback);
|
|
64
|
-
BridgeResult opsqlite_deregister_commit_hook(std::string const &dbName
|
|
65
|
+
BridgeResult opsqlite_deregister_commit_hook(std::string const &dbName,
|
|
66
|
+
std::string const &id);
|
|
65
67
|
BridgeResult opsqlite_register_rollback_hook(std::string const &dbName,
|
|
66
68
|
RollbackCallback const callback);
|
|
67
|
-
BridgeResult opsqlite_deregister_rollback_hook(std::string const &dbName
|
|
69
|
+
BridgeResult opsqlite_deregister_rollback_hook(std::string const &dbName,
|
|
70
|
+
std::string const &id);
|
|
68
71
|
|
|
69
72
|
sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
|
|
70
73
|
std::string const &query);
|
package/cpp/types.h
CHANGED
package/cpp/utils.cpp
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include "bridge.h"
|
|
4
4
|
#include <fstream>
|
|
5
5
|
#include <iostream>
|
|
6
|
+
#include <random>
|
|
6
7
|
#include <sstream>
|
|
7
8
|
#include <sys/stat.h>
|
|
8
9
|
#include <unistd.h>
|
|
@@ -252,4 +253,40 @@ int mkdir(std::string const &path) {
|
|
|
252
253
|
return 0;
|
|
253
254
|
}
|
|
254
255
|
|
|
256
|
+
// Semi random function, more than enough for our purposes
|
|
257
|
+
std::string get_uuid() {
|
|
258
|
+
static std::random_device dev;
|
|
259
|
+
static std::mt19937 rng(dev());
|
|
260
|
+
|
|
261
|
+
std::uniform_int_distribution<int> dist(0, 15);
|
|
262
|
+
|
|
263
|
+
const char *v = "0123456789abcdef";
|
|
264
|
+
const bool dash[] = {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0};
|
|
265
|
+
|
|
266
|
+
std::string res;
|
|
267
|
+
for (int i = 0; i < 16; i++) {
|
|
268
|
+
if (dash[i])
|
|
269
|
+
res += "-";
|
|
270
|
+
res += v[dist(rng)];
|
|
271
|
+
res += v[dist(rng)];
|
|
272
|
+
}
|
|
273
|
+
return res;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
std::string sqlite_operation_to_string(int operation_type) {
|
|
277
|
+
switch (operation_type) {
|
|
278
|
+
case SQLITE_INSERT:
|
|
279
|
+
return "INSERT";
|
|
280
|
+
|
|
281
|
+
case SQLITE_DELETE:
|
|
282
|
+
return "DELETE";
|
|
283
|
+
|
|
284
|
+
case SQLITE_UPDATE:
|
|
285
|
+
return "UPDATE";
|
|
286
|
+
|
|
287
|
+
default:
|
|
288
|
+
throw std::invalid_argument("Uknown SQLite operation on hook");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
255
292
|
} // namespace opsqlite
|
package/cpp/utils.h
CHANGED
package/op-sqlite.podspec
CHANGED
|
@@ -28,7 +28,7 @@ Pod::Spec.new do |s|
|
|
|
28
28
|
if ENV['OP_SQLITE_USE_SQLCIPHER'] == '1' then
|
|
29
29
|
puts "OP-SQLITE using SQLCipher! 🔒\n"
|
|
30
30
|
s.exclude_files = "cpp/sqlite3.c", "cpp/sqlite3.h"
|
|
31
|
-
xcconfig[:GCC_PREPROCESSOR_DEFINITIONS] += " OP_SQLITE_USE_SQLCIPHER=1"
|
|
31
|
+
xcconfig[:GCC_PREPROCESSOR_DEFINITIONS] += " OP_SQLITE_USE_SQLCIPHER=1 SQLITE_HAS_CODEC SQLITE_TEMP_STORE=2"
|
|
32
32
|
else
|
|
33
33
|
puts "OP-SQLITE using SQLite! 📦\n"
|
|
34
34
|
s.exclude_files = "cpp/sqlcipher/sqlite3.c", "cpp/sqlcipher/sqlite3.h"
|