@op-engineering/op-sqlite 0.0.0-resolution-test
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/LICENSE +7 -0
- package/README.md +31 -0
- package/android/.project +17 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
- package/android/CMakeLists.txt +141 -0
- package/android/build.gradle +266 -0
- package/android/c_sources/tokenizers.cpp +88 -0
- package/android/c_sources/tokenizers.h +15 -0
- package/android/cpp-adapter.cpp +46 -0
- package/android/gradle.properties +1 -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/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt +37 -0
- package/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +119 -0
- package/android/src/main/java/com/op/sqlite/OPSQLitePackage.kt +18 -0
- package/android/src/main/jniLibs/arm64-v8a/libcrsqlite.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libcrsqlite.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/x86/libcrsqlite.so +0 -0
- package/android/src/main/jniLibs/x86/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/x86_64/libcrsqlite.so +0 -0
- package/android/src/main/jniLibs/x86_64/libsqlite_vec.so +0 -0
- package/android/src/paper/java/com/op/sqlite/NativeOPSQLiteSpec.java +77 -0
- package/cpp/DBHostObject.cpp +852 -0
- package/cpp/DBHostObject.h +99 -0
- package/cpp/DumbHostObject.cpp +72 -0
- package/cpp/DumbHostObject.h +36 -0
- package/cpp/OPThreadPool.cpp +120 -0
- package/cpp/OPThreadPool.h +44 -0
- package/cpp/PreparedStatementHostObject.cpp +151 -0
- package/cpp/PreparedStatementHostObject.h +59 -0
- package/cpp/SmartHostObject.cpp +34 -0
- package/cpp/SmartHostObject.h +24 -0
- package/cpp/bindings.cpp +182 -0
- package/cpp/bindings.h +19 -0
- package/cpp/bridge.cpp +873 -0
- package/cpp/bridge.h +80 -0
- package/cpp/libsql/bridge.cpp +738 -0
- package/cpp/libsql/bridge.h +85 -0
- package/cpp/libsql/libsql.h +172 -0
- package/cpp/logs.h +40 -0
- package/cpp/macros.h +15 -0
- package/cpp/sqlcipher/sqlite3.c +262970 -0
- package/cpp/sqlcipher/sqlite3.h +13485 -0
- package/cpp/sqlite3.c +261454 -0
- package/cpp/sqlite3.h +13715 -0
- package/cpp/types.h +33 -0
- package/cpp/utils.cpp +327 -0
- package/cpp/utils.h +47 -0
- package/generate_tokenizers_header_file.rb +29 -0
- package/ios/OPSQLite.h +7 -0
- package/ios/OPSQLite.mm +157 -0
- package/ios/OPSQLite.xcodeproj/project.pbxproj +275 -0
- package/ios/crsqlite.xcframework/Info.plist +46 -0
- package/ios/crsqlite.xcframework/ios-arm64/crsqlite.framework/Info.plist +24 -0
- package/ios/crsqlite.xcframework/ios-arm64/crsqlite.framework/crsqlite +0 -0
- package/ios/crsqlite.xcframework/ios-arm64_x86_64-simulator/crsqlite.framework/Info.plist +24 -0
- package/ios/crsqlite.xcframework/ios-arm64_x86_64-simulator/crsqlite.framework/crsqlite +0 -0
- package/ios/libsql.xcframework/Info.plist +48 -0
- package/ios/libsql.xcframework/ios-arm64/Headers/libsql.h +172 -0
- package/ios/libsql.xcframework/ios-arm64/libsql_experimental.a +0 -0
- package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/Headers/libsql.h +172 -0
- package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/libsql_experimental.a +0 -0
- package/ios/sqlitevec.xcframework/Info.plist +71 -0
- package/ios/sqlitevec.xcframework/ios-arm64/sqlitevec.framework/Info.plist +24 -0
- package/ios/sqlitevec.xcframework/ios-arm64/sqlitevec.framework/sqlitevec +0 -0
- package/ios/sqlitevec.xcframework/ios-arm64_x86_64-simulator/sqlitevec.framework/Info.plist +24 -0
- package/ios/sqlitevec.xcframework/ios-arm64_x86_64-simulator/sqlitevec.framework/sqlitevec +0 -0
- package/ios/sqlitevec.xcframework/tvos-arm64/sqlitevec.framework/Info.plist +24 -0
- package/ios/sqlitevec.xcframework/tvos-arm64/sqlitevec.framework/sqlitevec +0 -0
- package/ios/sqlitevec.xcframework/tvos-arm64_x86_64-simulator/sqlitevec.framework/Info.plist +24 -0
- package/ios/sqlitevec.xcframework/tvos-arm64_x86_64-simulator/sqlitevec.framework/sqlitevec +0 -0
- package/lib/commonjs/NativeOPSQLite.js +9 -0
- package/lib/commonjs/NativeOPSQLite.js.map +1 -0
- package/lib/commonjs/Storage.js +60 -0
- package/lib/commonjs/Storage.js.map +1 -0
- package/lib/commonjs/index.js +365 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/NativeOPSQLite.js +3 -0
- package/lib/module/NativeOPSQLite.js.map +1 -0
- package/lib/module/Storage.js +53 -0
- package/lib/module/Storage.js.map +1 -0
- package/lib/module/index.js +340 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/src/NativeOPSQLite.d.ts +15 -0
- package/lib/typescript/src/NativeOPSQLite.d.ts.map +1 -0
- 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 +319 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/op-sqlite.podspec +212 -0
- package/package.json +85 -0
- package/src/NativeOPSQLite.ts +17 -0
- package/src/Storage.ts +85 -0
- package/src/index.ts +722 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "OPThreadPool.h"
|
|
4
|
+
#include "types.h"
|
|
5
|
+
#include <ReactCommon/CallInvoker.h>
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
#include <set>
|
|
8
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
9
|
+
#include "libsql/bridge.h"
|
|
10
|
+
#else
|
|
11
|
+
#include <sqlite3.h>
|
|
12
|
+
#endif
|
|
13
|
+
#include <unordered_map>
|
|
14
|
+
#include <vector>
|
|
15
|
+
|
|
16
|
+
namespace opsqlite {
|
|
17
|
+
|
|
18
|
+
namespace jsi = facebook::jsi;
|
|
19
|
+
namespace react = facebook::react;
|
|
20
|
+
|
|
21
|
+
struct PendingReactiveInvocation {
|
|
22
|
+
std::string db_name;
|
|
23
|
+
std::string table;
|
|
24
|
+
std::string rowid;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
struct TableRowDiscriminator {
|
|
28
|
+
std::string table;
|
|
29
|
+
std::vector<int> ids;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
struct ReactiveQuery {
|
|
33
|
+
#ifndef OP_SQLITE_USE_LIBSQL
|
|
34
|
+
sqlite3_stmt *stmt;
|
|
35
|
+
#endif
|
|
36
|
+
std::vector<TableRowDiscriminator> discriminators;
|
|
37
|
+
std::shared_ptr<jsi::Value> callback;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
class JSI_EXPORT DBHostObject : public jsi::HostObject {
|
|
41
|
+
public:
|
|
42
|
+
// Normal constructor shared between all backends
|
|
43
|
+
DBHostObject(jsi::Runtime &rt, std::string &base_path,
|
|
44
|
+
std::shared_ptr<react::CallInvoker> invoker,
|
|
45
|
+
std::string &db_name, std::string &path,
|
|
46
|
+
std::string &crsqlite_path, std::string &sqlite_vec_path,
|
|
47
|
+
std::string &encryption_key);
|
|
48
|
+
|
|
49
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
50
|
+
// Constructor for remoteOpen, purely for remote databases
|
|
51
|
+
DBHostObject(jsi::Runtime &rt, std::string &url, std::string &auth_token,
|
|
52
|
+
std::shared_ptr<react::CallInvoker> invoker);
|
|
53
|
+
|
|
54
|
+
// Constructor for a local database with remote sync
|
|
55
|
+
DBHostObject(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
56
|
+
std::string &db_name, std::string &path, std::string &url,
|
|
57
|
+
std::string &auth_token, int sync_interval);
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
61
|
+
jsi::Value get(jsi::Runtime &rt,
|
|
62
|
+
const jsi::PropNameID &propNameID) override;
|
|
63
|
+
void set(jsi::Runtime &rt, const jsi::PropNameID &name,
|
|
64
|
+
const jsi::Value &value) override;
|
|
65
|
+
void on_update(const std::string &table, const std::string &operation,
|
|
66
|
+
long long row_id);
|
|
67
|
+
void on_commit();
|
|
68
|
+
void on_rollback();
|
|
69
|
+
void invalidate();
|
|
70
|
+
~DBHostObject() override;
|
|
71
|
+
|
|
72
|
+
private:
|
|
73
|
+
std::set<std::shared_ptr<ReactiveQuery>> pending_reactive_queries;
|
|
74
|
+
void auto_register_update_hook();
|
|
75
|
+
void create_jsi_functions();
|
|
76
|
+
void
|
|
77
|
+
flush_pending_reactive_queries(const std::shared_ptr<jsi::Value> &resolve);
|
|
78
|
+
|
|
79
|
+
std::unordered_map<std::string, jsi::Value> function_map;
|
|
80
|
+
std::string base_path;
|
|
81
|
+
std::shared_ptr<react::CallInvoker> invoker;
|
|
82
|
+
std::shared_ptr<ThreadPool> _thread_pool;
|
|
83
|
+
std::string db_name;
|
|
84
|
+
std::shared_ptr<jsi::Value> update_hook_callback;
|
|
85
|
+
std::shared_ptr<jsi::Value> commit_hook_callback;
|
|
86
|
+
std::shared_ptr<jsi::Value> rollback_hook_callback;
|
|
87
|
+
jsi::Runtime &rt;
|
|
88
|
+
std::vector<std::shared_ptr<ReactiveQuery>> reactive_queries;
|
|
89
|
+
std::vector<PendingReactiveInvocation> pending_reactive_invocations;
|
|
90
|
+
bool is_update_hook_registered = false;
|
|
91
|
+
bool invalidated = false;
|
|
92
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
93
|
+
DB db;
|
|
94
|
+
#else
|
|
95
|
+
sqlite3 *db;
|
|
96
|
+
#endif
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#include "DumbHostObject.h"
|
|
2
|
+
#include "SmartHostObject.h"
|
|
3
|
+
#include "utils.h"
|
|
4
|
+
#include <iostream>
|
|
5
|
+
|
|
6
|
+
namespace opsqlite {
|
|
7
|
+
|
|
8
|
+
namespace jsi = facebook::jsi;
|
|
9
|
+
|
|
10
|
+
DumbHostObject::DumbHostObject(
|
|
11
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata) {
|
|
12
|
+
this->metadata = metadata;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
std::vector<jsi::PropNameID>
|
|
16
|
+
DumbHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
17
|
+
std::vector<jsi::PropNameID> keys;
|
|
18
|
+
|
|
19
|
+
for (auto field : *metadata) {
|
|
20
|
+
// TODO improve this by generating the propName once on metadata
|
|
21
|
+
// creation
|
|
22
|
+
keys.push_back(jsi::PropNameID::forAscii(
|
|
23
|
+
rt, std::get<std::string>(field.fields[0].second)));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return keys;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
jsi::Value DumbHostObject::get(jsi::Runtime &rt,
|
|
30
|
+
const jsi::PropNameID &propNameID) {
|
|
31
|
+
|
|
32
|
+
auto name = propNameID.utf8(rt);
|
|
33
|
+
auto fields = metadata.get();
|
|
34
|
+
for (int i = 0; i < fields->size(); i++) {
|
|
35
|
+
auto fieldName = std::get<std::string>(fields->at(i).fields[0].second);
|
|
36
|
+
if (fieldName == name) {
|
|
37
|
+
return to_jsi(rt, values.at(i));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (auto pairField : ownValues) {
|
|
42
|
+
if (name == pairField.first) {
|
|
43
|
+
return to_jsi(rt, pairField.second);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void DumbHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
|
|
51
|
+
const jsi::Value &value) {
|
|
52
|
+
auto key = name.utf8(rt);
|
|
53
|
+
auto fields = metadata.get();
|
|
54
|
+
for (int i = 0; i < fields->size(); i++) {
|
|
55
|
+
auto fieldName = std::get<std::string>(fields->at(i).fields[0].second);
|
|
56
|
+
if (fieldName == key) {
|
|
57
|
+
values[i] = to_variant(rt, value);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
for (auto pairField : ownValues) {
|
|
63
|
+
if (key == pairField.first) {
|
|
64
|
+
pairField.second = to_variant(rt, value);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
ownValues.push_back(std::make_pair(key, to_variant(rt, value)));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "SmartHostObject.h"
|
|
4
|
+
#include "types.h"
|
|
5
|
+
#include <any>
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
namespace opsqlite {
|
|
11
|
+
|
|
12
|
+
namespace jsi = facebook::jsi;
|
|
13
|
+
|
|
14
|
+
class JSI_EXPORT DumbHostObject : public jsi::HostObject {
|
|
15
|
+
public:
|
|
16
|
+
DumbHostObject() = default;
|
|
17
|
+
|
|
18
|
+
explicit DumbHostObject(
|
|
19
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata);
|
|
20
|
+
|
|
21
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
22
|
+
|
|
23
|
+
jsi::Value get(jsi::Runtime &rt,
|
|
24
|
+
const jsi::PropNameID &propNameID) override;
|
|
25
|
+
|
|
26
|
+
void set(jsi::Runtime &rt, const jsi::PropNameID &name,
|
|
27
|
+
const jsi::Value &value) override;
|
|
28
|
+
|
|
29
|
+
std::vector<JSVariant> values;
|
|
30
|
+
|
|
31
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata;
|
|
32
|
+
|
|
33
|
+
std::vector<std::pair<std::string, JSVariant>> ownValues;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#include "OPThreadPool.h"
|
|
2
|
+
|
|
3
|
+
namespace opsqlite {
|
|
4
|
+
|
|
5
|
+
ThreadPool::ThreadPool() : done(false) {
|
|
6
|
+
// This returns the number of threads supported by the system. If the
|
|
7
|
+
// function can't figure out this information, it returns 0. 0 is not good,
|
|
8
|
+
// so we create at least 1
|
|
9
|
+
// auto numberOfThreads = std::thread::hardware_concurrency();
|
|
10
|
+
// if (numberOfThreads == 0) {
|
|
11
|
+
// numberOfThreads = 1;
|
|
12
|
+
// }
|
|
13
|
+
|
|
14
|
+
auto numberOfThreads = 1;
|
|
15
|
+
for (unsigned i = 0; i < numberOfThreads; ++i) {
|
|
16
|
+
// The threads will execute the private member `doWork`. Note that we
|
|
17
|
+
// need to pass a reference to the function (namespaced with the class
|
|
18
|
+
// name) as the first argument, and the current object as second
|
|
19
|
+
// argument
|
|
20
|
+
threads.emplace_back(&ThreadPool::doWork, this);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// The destructor joins all the threads so the program can exit gracefully.
|
|
25
|
+
// This will be executed if there is any exception (e.g. creating the threads)
|
|
26
|
+
ThreadPool::~ThreadPool() {
|
|
27
|
+
// So threads know it's time to shut down
|
|
28
|
+
done = true;
|
|
29
|
+
|
|
30
|
+
// Wake up all the threads, so they can finish and be joined
|
|
31
|
+
workQueueConditionVariable.notify_all();
|
|
32
|
+
|
|
33
|
+
for (auto &thread : threads) {
|
|
34
|
+
if (thread.joinable()) {
|
|
35
|
+
thread.join();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
threads.clear();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// This function will be called by the server every time there is a request
|
|
43
|
+
// that needs to be processed by the thread pool
|
|
44
|
+
void ThreadPool::queueWork(const std::function<void(void)> &task) {
|
|
45
|
+
// Grab the mutex
|
|
46
|
+
std::lock_guard<std::mutex> g(workQueueMutex);
|
|
47
|
+
|
|
48
|
+
// Push the request to the queue
|
|
49
|
+
workQueue.push(task);
|
|
50
|
+
|
|
51
|
+
// Notify one thread that there are requests to process
|
|
52
|
+
workQueueConditionVariable.notify_one();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Function used by the threads to grab work from the queue
|
|
56
|
+
void ThreadPool::doWork() {
|
|
57
|
+
// Loop while the queue is not destructing
|
|
58
|
+
while (!done) {
|
|
59
|
+
std::function<void(void)> task;
|
|
60
|
+
|
|
61
|
+
// Create a scope, so we don't lock the queue for longer than necessary
|
|
62
|
+
{
|
|
63
|
+
std::unique_lock<std::mutex> g(workQueueMutex);
|
|
64
|
+
workQueueConditionVariable.wait(g, [&] {
|
|
65
|
+
// Only wake up if there are elements in the queue or the
|
|
66
|
+
// program is shutting down
|
|
67
|
+
return !workQueue.empty() || done;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// If we are shutting down exit without trying to process more work
|
|
71
|
+
if (done) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
task = workQueue.front();
|
|
76
|
+
workQueue.pop();
|
|
77
|
+
}
|
|
78
|
+
++busy;
|
|
79
|
+
task();
|
|
80
|
+
--busy;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void ThreadPool::waitFinished() {
|
|
85
|
+
std::unique_lock<std::mutex> g(workQueueMutex);
|
|
86
|
+
workQueueConditionVariable.wait(
|
|
87
|
+
g, [&] { return workQueue.empty() && (busy == 0); });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void ThreadPool::restartPool() {
|
|
91
|
+
// So threads know it's time to shut down
|
|
92
|
+
done = true;
|
|
93
|
+
|
|
94
|
+
// Wake up all the threads, so they can finish and be joined
|
|
95
|
+
workQueueConditionVariable.notify_all();
|
|
96
|
+
|
|
97
|
+
for (auto &thread : threads) {
|
|
98
|
+
if (thread.joinable()) {
|
|
99
|
+
thread.join();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
threads.clear();
|
|
104
|
+
|
|
105
|
+
auto numberOfThreads = std::thread::hardware_concurrency();
|
|
106
|
+
if (numberOfThreads == 0) {
|
|
107
|
+
numberOfThreads = 1;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
for (unsigned i = 0; i < numberOfThreads; ++i) {
|
|
111
|
+
// The threads will execute the private member `doWork`. Note that we
|
|
112
|
+
// need to pass a reference to the function (namespaced with the class
|
|
113
|
+
// name) as the first argument, and the current object as second
|
|
114
|
+
// argument
|
|
115
|
+
threads.emplace_back(&ThreadPool::doWork, this);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
done = false;
|
|
119
|
+
}
|
|
120
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <condition_variable>
|
|
4
|
+
#include <exception>
|
|
5
|
+
#include <mutex>
|
|
6
|
+
#include <queue>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <thread>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
namespace opsqlite {
|
|
12
|
+
|
|
13
|
+
class ThreadPool {
|
|
14
|
+
public:
|
|
15
|
+
ThreadPool();
|
|
16
|
+
~ThreadPool();
|
|
17
|
+
void queueWork(const std::function<void(void)> &task);
|
|
18
|
+
void waitFinished();
|
|
19
|
+
void restartPool();
|
|
20
|
+
|
|
21
|
+
private:
|
|
22
|
+
unsigned int busy{};
|
|
23
|
+
// This condition variable is used for the threads to wait until there is
|
|
24
|
+
// work to do
|
|
25
|
+
std::condition_variable_any workQueueConditionVariable;
|
|
26
|
+
|
|
27
|
+
// We store the threads in a vector, so we can later stop them gracefully
|
|
28
|
+
std::vector<std::thread> threads;
|
|
29
|
+
|
|
30
|
+
// Mutex to protect workQueue
|
|
31
|
+
std::mutex workQueueMutex;
|
|
32
|
+
|
|
33
|
+
// Queue of requests waiting to be processed
|
|
34
|
+
std::queue<std::function<void(void)>> workQueue;
|
|
35
|
+
|
|
36
|
+
// This will be set to true when the thread pool is shutting down. This
|
|
37
|
+
// tells the threads to stop looping and finish
|
|
38
|
+
bool done;
|
|
39
|
+
|
|
40
|
+
// Function used by the threads to grab work from the queue
|
|
41
|
+
void doWork();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#include "PreparedStatementHostObject.h"
|
|
2
|
+
#if OP_SQLITE_USE_LIBSQL
|
|
3
|
+
#include "libsql/bridge.h"
|
|
4
|
+
#else
|
|
5
|
+
#include "bridge.h"
|
|
6
|
+
#endif
|
|
7
|
+
#include "macros.h"
|
|
8
|
+
#include "utils.h"
|
|
9
|
+
|
|
10
|
+
namespace opsqlite {
|
|
11
|
+
|
|
12
|
+
namespace jsi = facebook::jsi;
|
|
13
|
+
|
|
14
|
+
std::vector<jsi::PropNameID>
|
|
15
|
+
PreparedStatementHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
16
|
+
std::vector<jsi::PropNameID> keys;
|
|
17
|
+
|
|
18
|
+
return keys;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt,
|
|
22
|
+
const jsi::PropNameID &propNameID) {
|
|
23
|
+
auto name = propNameID.utf8(rt);
|
|
24
|
+
|
|
25
|
+
if (name == "bind") {
|
|
26
|
+
return HOSTFN("bind") {
|
|
27
|
+
if (_stmt == nullptr) {
|
|
28
|
+
throw std::runtime_error("statement has been freed");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const jsi::Value &js_params = args[0];
|
|
32
|
+
std::vector<JSVariant> params = to_variant_vec(rt, js_params);
|
|
33
|
+
|
|
34
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
35
|
+
auto promise = promiseCtr.callAsConstructor(
|
|
36
|
+
rt, HOSTFN("executor") {
|
|
37
|
+
auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
|
|
38
|
+
auto reject = std::make_shared<jsi::Value>(rt, args[1]);
|
|
39
|
+
auto task = [&rt, this, resolve, reject,
|
|
40
|
+
invoker = this->_js_call_invoker, params]() {
|
|
41
|
+
try {
|
|
42
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
43
|
+
opsqlite_libsql_bind_statement(_stmt, ¶ms);
|
|
44
|
+
#else
|
|
45
|
+
opsqlite_bind_statement(_stmt, ¶ms);
|
|
46
|
+
#endif
|
|
47
|
+
invoker->invokeAsync([&rt, resolve] {
|
|
48
|
+
resolve->asObject(rt).asFunction(rt).call(rt, {});
|
|
49
|
+
});
|
|
50
|
+
} catch (const std::runtime_error &e) {
|
|
51
|
+
invoker->invokeAsync([&rt, e, reject] {
|
|
52
|
+
auto errorCtr =
|
|
53
|
+
rt.global().getPropertyAsFunction(rt, "Error");
|
|
54
|
+
auto error = errorCtr.callAsConstructor(
|
|
55
|
+
rt, jsi::String::createFromUtf8(rt, e.what()));
|
|
56
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
57
|
+
});
|
|
58
|
+
} catch (const std::exception &e) {
|
|
59
|
+
invoker->invokeAsync([&rt, e, reject] {
|
|
60
|
+
auto errorCtr =
|
|
61
|
+
rt.global().getPropertyAsFunction(rt, "Error");
|
|
62
|
+
auto error = errorCtr.callAsConstructor(
|
|
63
|
+
rt, jsi::String::createFromUtf8(rt, e.what()));
|
|
64
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
_thread_pool->queueWork(task);
|
|
70
|
+
|
|
71
|
+
return {};
|
|
72
|
+
}));
|
|
73
|
+
return promise;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (name == "execute") {
|
|
78
|
+
return HOSTFN("execute") {
|
|
79
|
+
if (_stmt == nullptr) {
|
|
80
|
+
throw std::runtime_error("statement has been freed");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
84
|
+
auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
|
|
85
|
+
auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
|
|
86
|
+
auto reject = std::make_shared<jsi::Value>(rt, args[1]);
|
|
87
|
+
|
|
88
|
+
auto task = [&rt, this, resolve, reject,
|
|
89
|
+
invoker = this->_js_call_invoker]() {
|
|
90
|
+
std::vector<DumbHostObject> results;
|
|
91
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
92
|
+
std::make_shared<std::vector<SmartHostObject>>();
|
|
93
|
+
try {
|
|
94
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
95
|
+
auto status =
|
|
96
|
+
opsqlite_libsql_execute_prepared_statement(
|
|
97
|
+
_db, _stmt, &results, metadata);
|
|
98
|
+
#else
|
|
99
|
+
auto status = opsqlite_execute_prepared_statement(
|
|
100
|
+
_db, _stmt, &results, metadata);
|
|
101
|
+
#endif
|
|
102
|
+
invoker->invokeAsync(
|
|
103
|
+
[&rt, status = std::move(status),
|
|
104
|
+
results =
|
|
105
|
+
std::make_shared<std::vector<DumbHostObject>>(
|
|
106
|
+
results),
|
|
107
|
+
metadata, resolve] {
|
|
108
|
+
auto jsiResult = create_result(
|
|
109
|
+
rt, status, results.get(), metadata);
|
|
110
|
+
resolve->asObject(rt).asFunction(rt).call(
|
|
111
|
+
rt, std::move(jsiResult));
|
|
112
|
+
});
|
|
113
|
+
} catch (std::exception &exc) {
|
|
114
|
+
invoker->invokeAsync([&rt, &exc, reject] {
|
|
115
|
+
auto errorCtr =
|
|
116
|
+
rt.global().getPropertyAsFunction(rt, "Error");
|
|
117
|
+
auto error = errorCtr.callAsConstructor(
|
|
118
|
+
rt,
|
|
119
|
+
jsi::String::createFromUtf8(rt, exc.what()));
|
|
120
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
_thread_pool->queueWork(task);
|
|
126
|
+
|
|
127
|
+
return {};
|
|
128
|
+
}));
|
|
129
|
+
|
|
130
|
+
return promise;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
PreparedStatementHostObject::~PreparedStatementHostObject() {
|
|
138
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
139
|
+
if (_stmt != nullptr) {
|
|
140
|
+
libsql_free_stmt(_stmt);
|
|
141
|
+
_stmt = nullptr;
|
|
142
|
+
}
|
|
143
|
+
#else
|
|
144
|
+
if (_stmt != nullptr) {
|
|
145
|
+
// sqlite3_finalize(_stmt);
|
|
146
|
+
_stmt = nullptr;
|
|
147
|
+
}
|
|
148
|
+
#endif
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <ReactCommon/CallInvoker.h>
|
|
4
|
+
#include <jsi/jsi.h>
|
|
5
|
+
#include <memory>
|
|
6
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
7
|
+
#include "libsql.h"
|
|
8
|
+
#include "libsql/bridge.h"
|
|
9
|
+
#else
|
|
10
|
+
#include <sqlite3.h>
|
|
11
|
+
#endif
|
|
12
|
+
#include "OPThreadPool.h"
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <utility>
|
|
15
|
+
|
|
16
|
+
namespace opsqlite {
|
|
17
|
+
namespace jsi = facebook::jsi;
|
|
18
|
+
namespace react = facebook::react;
|
|
19
|
+
|
|
20
|
+
class PreparedStatementHostObject : public jsi::HostObject {
|
|
21
|
+
public:
|
|
22
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
23
|
+
PreparedStatementHostObject(
|
|
24
|
+
DB const &db, std::string name, libsql_stmt_t stmt,
|
|
25
|
+
std::shared_ptr<react::CallInvoker> js_call_invoker,
|
|
26
|
+
std::shared_ptr<ThreadPool> thread_pool)
|
|
27
|
+
: _db(db), _name(std::move(name)), _stmt(stmt),
|
|
28
|
+
_js_call_invoker(js_call_invoker), _thread_pool(thread_pool) {};
|
|
29
|
+
#else
|
|
30
|
+
PreparedStatementHostObject(
|
|
31
|
+
sqlite3 *db, std::string name, sqlite3_stmt *stmt,
|
|
32
|
+
std::shared_ptr<react::CallInvoker> js_call_invoker,
|
|
33
|
+
std::shared_ptr<ThreadPool> thread_pool)
|
|
34
|
+
: _db(db), _name(std::move(name)), _stmt(stmt),
|
|
35
|
+
_js_call_invoker(std::move(js_call_invoker)),
|
|
36
|
+
_thread_pool(std::move(thread_pool)) {};
|
|
37
|
+
#endif
|
|
38
|
+
~PreparedStatementHostObject() override;
|
|
39
|
+
|
|
40
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
41
|
+
|
|
42
|
+
jsi::Value get(jsi::Runtime &rt,
|
|
43
|
+
const jsi::PropNameID &propNameID) override;
|
|
44
|
+
|
|
45
|
+
private:
|
|
46
|
+
std::string _name;
|
|
47
|
+
#ifdef OP_SQLITE_USE_LIBSQL
|
|
48
|
+
DB _db;
|
|
49
|
+
libsql_stmt_t _stmt;
|
|
50
|
+
#else
|
|
51
|
+
sqlite3 *_db;
|
|
52
|
+
// This shouldn't be de-allocated until sqlite3_finalize is called on it
|
|
53
|
+
sqlite3_stmt *_stmt;
|
|
54
|
+
#endif
|
|
55
|
+
std::shared_ptr<react::CallInvoker> _js_call_invoker;
|
|
56
|
+
std::shared_ptr<ThreadPool> _thread_pool;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#include "SmartHostObject.h"
|
|
2
|
+
#include "utils.h"
|
|
3
|
+
|
|
4
|
+
namespace opsqlite {
|
|
5
|
+
|
|
6
|
+
namespace jsi = facebook::jsi;
|
|
7
|
+
|
|
8
|
+
std::vector<jsi::PropNameID>
|
|
9
|
+
SmartHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
10
|
+
std::vector<jsi::PropNameID> keys;
|
|
11
|
+
|
|
12
|
+
keys.reserve(fields.size());
|
|
13
|
+
for (const auto &field : fields) {
|
|
14
|
+
keys.emplace_back(jsi::PropNameID::forAscii(rt, field.first));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return keys;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
jsi::Value SmartHostObject::get(jsi::Runtime &rt,
|
|
21
|
+
const jsi::PropNameID &propNameID) {
|
|
22
|
+
auto name = propNameID.utf8(rt);
|
|
23
|
+
|
|
24
|
+
for (const auto &field : fields) {
|
|
25
|
+
auto fieldName = field.first;
|
|
26
|
+
if (fieldName == name) {
|
|
27
|
+
return to_jsi(rt, field.second);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.h"
|
|
4
|
+
#include <any>
|
|
5
|
+
#include <jsi/jsi.h>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
namespace opsqlite {
|
|
9
|
+
|
|
10
|
+
namespace jsi = facebook::jsi;
|
|
11
|
+
|
|
12
|
+
class JSI_EXPORT SmartHostObject : public jsi::HostObject {
|
|
13
|
+
public:
|
|
14
|
+
SmartHostObject() = default;
|
|
15
|
+
|
|
16
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
17
|
+
|
|
18
|
+
jsi::Value get(jsi::Runtime &rt,
|
|
19
|
+
const jsi::PropNameID &propNameID) override;
|
|
20
|
+
|
|
21
|
+
std::vector<std::pair<std::string, JSVariant>> fields;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
} // namespace opsqlite
|