@op-engineering/op-sqlite 15.0.7 → 15.1.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/android/CMakeLists.txt +1 -1
- package/android/build.gradle +1 -1
- package/android/cpp-adapter.cpp +1 -1
- package/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +7 -9
- package/cpp/DBHostObject.cpp +469 -677
- package/cpp/DBHostObject.h +56 -58
- package/cpp/DumbHostObject.cpp +1 -1
- package/cpp/DumbHostObject.h +12 -13
- package/cpp/OPSqlite.cpp +207 -0
- package/cpp/OPThreadPool.cpp +79 -79
- package/cpp/OPThreadPool.h +28 -28
- package/cpp/PreparedStatementHostObject.cpp +87 -136
- package/cpp/PreparedStatementHostObject.h +16 -28
- package/cpp/SmartHostObject.cpp +1 -1
- package/cpp/SmartHostObject.h +6 -7
- package/cpp/bridge.cpp +639 -633
- package/cpp/bridge.h +2 -2
- package/cpp/libsql/LICENSE.txt +9 -0
- package/cpp/libsql/bridge.cpp +2 -2
- package/cpp/libsql/{bridge.h → bridge.hpp} +4 -4
- package/cpp/macros.hpp +21 -0
- package/cpp/sqlcipher/LICENSE.txt +24 -0
- package/cpp/types.hpp +42 -0
- package/cpp/utils.cpp +320 -255
- package/cpp/{utils.h → utils.hpp} +9 -1
- package/ios/OPSQLite.mm +104 -106
- package/lib/module/functions.js +40 -33
- package/lib/module/functions.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/functions.d.ts +5 -1
- package/lib/typescript/src/functions.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +5 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/op-sqlite.podspec +1 -1
- package/package.json +10 -8
- package/src/functions.ts +52 -43
- package/src/index.ts +1 -12
- package/src/types.ts +5 -1
- package/cpp/bindings.cpp +0 -202
- package/cpp/macros.h +0 -15
- package/cpp/types.h +0 -33
- /package/cpp/{bindings.h → OPSqlite.hpp} +0 -0
package/cpp/utils.cpp
CHANGED
|
@@ -1,327 +1,392 @@
|
|
|
1
|
-
#include "utils.
|
|
1
|
+
#include "utils.hpp"
|
|
2
2
|
#include "SmartHostObject.h"
|
|
3
|
+
#include "types.hpp"
|
|
3
4
|
#ifndef OP_SQLITE_USE_LIBSQL
|
|
4
5
|
#include "bridge.h"
|
|
5
6
|
#endif
|
|
7
|
+
#include "OPThreadPool.h"
|
|
6
8
|
#include <fstream>
|
|
7
9
|
#include <sys/stat.h>
|
|
10
|
+
#include <utility>
|
|
8
11
|
|
|
9
12
|
namespace opsqlite {
|
|
10
13
|
|
|
11
14
|
namespace jsi = facebook::jsi;
|
|
15
|
+
namespace react = facebook::react;
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
if (std::holds_alternative<bool>(value)) {
|
|
15
|
-
return std::get<bool>(value);
|
|
16
|
-
} else if (std::holds_alternative<int>(value)) {
|
|
17
|
-
return jsi::Value(std::get<int>(value));
|
|
18
|
-
} else if (std::holds_alternative<long long>(value)) {
|
|
19
|
-
return jsi::Value(static_cast<double>(std::get<long long>(value)));
|
|
20
|
-
} else if (std::holds_alternative<double>(value)) {
|
|
21
|
-
return jsi::Value(std::get<double>(value));
|
|
22
|
-
} else if (std::holds_alternative<std::string>(value)) {
|
|
23
|
-
auto str = std::get<std::string>(value);
|
|
24
|
-
return jsi::String::createFromUtf8(rt, str);
|
|
25
|
-
} else if (std::holds_alternative<ArrayBuffer>(value)) {
|
|
26
|
-
auto jsBuffer = std::get<ArrayBuffer>(value);
|
|
27
|
-
jsi::Function array_buffer_ctor =
|
|
28
|
-
rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
|
|
29
|
-
jsi::Object o =
|
|
30
|
-
array_buffer_ctor.callAsConstructor(rt, (int)jsBuffer.size)
|
|
31
|
-
.getObject(rt);
|
|
32
|
-
jsi::ArrayBuffer buf = o.getArrayBuffer(rt);
|
|
33
|
-
memcpy(buf.data(rt), jsBuffer.data.get(), jsBuffer.size);
|
|
34
|
-
return o;
|
|
35
|
-
}
|
|
17
|
+
auto __thread_pool = std::make_shared<ThreadPool>();
|
|
36
18
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
19
|
+
inline jsi::Value to_jsi(jsi::Runtime &rt, const JSVariant &value) {
|
|
20
|
+
if (std::holds_alternative<bool>(value)) {
|
|
21
|
+
return std::get<bool>(value);
|
|
22
|
+
} else if (std::holds_alternative<int>(value)) {
|
|
23
|
+
return jsi::Value(std::get<int>(value));
|
|
24
|
+
} else if (std::holds_alternative<long long>(value)) {
|
|
25
|
+
return jsi::Value(static_cast<double>(std::get<long long>(value)));
|
|
26
|
+
} else if (std::holds_alternative<double>(value)) {
|
|
27
|
+
return jsi::Value(std::get<double>(value));
|
|
28
|
+
} else if (std::holds_alternative<std::string>(value)) {
|
|
29
|
+
auto str = std::get<std::string>(value);
|
|
30
|
+
return jsi::String::createFromUtf8(rt, str);
|
|
31
|
+
} else if (std::holds_alternative<ArrayBuffer>(value)) {
|
|
32
|
+
auto jsBuffer = std::get<ArrayBuffer>(value);
|
|
33
|
+
jsi::Function array_buffer_ctor =
|
|
34
|
+
rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
|
|
35
|
+
jsi::Object o = array_buffer_ctor.callAsConstructor(rt, (int)jsBuffer.size)
|
|
36
|
+
.getObject(rt);
|
|
37
|
+
jsi::ArrayBuffer buf = o.getArrayBuffer(rt);
|
|
38
|
+
memcpy(buf.data(rt), jsBuffer.data.get(), jsBuffer.size);
|
|
39
|
+
return o;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return jsi::Value::null();
|
|
43
|
+
|
|
44
|
+
// I wanted to use the visitor pattern here but on the ArrayBuffer case it
|
|
45
|
+
// is somehow throwing a pointer exception Somehow the v.size or
|
|
46
|
+
// v.data.get() is loosing the data when called from the lambda I'm guessing
|
|
47
|
+
// the I created the shared pointer wrong and the memory is being freed
|
|
48
|
+
// before the lambda is called
|
|
49
|
+
// return std::visit(
|
|
50
|
+
// [&](auto &&v) -> jsi::Value {
|
|
51
|
+
// using T = std::decay_t<decltype(v)>;
|
|
52
|
+
// if constexpr (std::is_same_v<T, bool>) {
|
|
53
|
+
// return jsi::Value(v);
|
|
54
|
+
// } else if constexpr (std::is_same_v<T, int>) {
|
|
55
|
+
// return jsi::Value(v);
|
|
56
|
+
// } else if constexpr (std::is_same_v<T, long long>) {
|
|
57
|
+
// return jsi::Value(
|
|
58
|
+
// static_cast<double>(v)); // JSI doesn't support long long
|
|
59
|
+
// } else if constexpr (std::is_same_v<T, double>) {
|
|
60
|
+
// return jsi::Value(v);
|
|
61
|
+
// } else if constexpr (std::is_same_v<T, std::string>) {
|
|
62
|
+
// return jsi::String::createFromUtf8(rt, v);
|
|
63
|
+
// } else if constexpr (std::is_same_v<T, ArrayBuffer>) {
|
|
64
|
+
// static jsi::Function buffer_constructor =
|
|
65
|
+
// rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
|
|
66
|
+
// jsi::Object o =
|
|
67
|
+
// buffer_constructor.callAsConstructor(rt,
|
|
68
|
+
// static_cast<int>(v.size))
|
|
69
|
+
// .getObject(rt);
|
|
70
|
+
// jsi::ArrayBuffer buf = o.getArrayBuffer(rt);
|
|
71
|
+
// memcpy(buf.data(rt), v.data.get(), v.size);
|
|
72
|
+
// return o;
|
|
73
|
+
// } else {
|
|
74
|
+
// return jsi::Value::null();
|
|
75
|
+
// }
|
|
76
|
+
// },
|
|
77
|
+
// value);
|
|
73
78
|
}
|
|
74
79
|
|
|
75
80
|
inline JSVariant to_variant(jsi::Runtime &rt, const jsi::Value &value) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
if (value.isNull() || value.isUndefined()) {
|
|
82
|
+
return JSVariant(nullptr);
|
|
83
|
+
} else if (value.isBool()) {
|
|
84
|
+
return JSVariant(value.getBool());
|
|
85
|
+
} else if (value.isNumber()) {
|
|
86
|
+
double doubleVal = value.asNumber();
|
|
87
|
+
int intVal = (int)doubleVal;
|
|
88
|
+
long long longVal = (long)doubleVal;
|
|
89
|
+
if (intVal == doubleVal) {
|
|
90
|
+
return JSVariant(intVal);
|
|
91
|
+
} else if (longVal == doubleVal) {
|
|
92
|
+
return JSVariant(longVal);
|
|
93
|
+
} else {
|
|
94
|
+
return JSVariant(doubleVal);
|
|
95
|
+
}
|
|
96
|
+
} else if (value.isString()) {
|
|
97
|
+
std::string strVal = value.asString(rt).utf8(rt);
|
|
98
|
+
return JSVariant(strVal);
|
|
99
|
+
} else if (value.isObject()) {
|
|
100
|
+
auto obj = value.asObject(rt);
|
|
101
|
+
|
|
102
|
+
if (!obj.isArrayBuffer(rt)) {
|
|
103
|
+
throw std::runtime_error(
|
|
104
|
+
"Object is not an ArrayBuffer, cannot bind to SQLite");
|
|
105
|
+
}
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
auto buffer = obj.getArrayBuffer(rt);
|
|
108
|
+
uint8_t *data = new uint8_t[buffer.size(rt)];
|
|
109
|
+
memcpy(data, buffer.data(rt), buffer.size(rt));
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
return JSVariant(ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
112
|
+
.size = buffer.size(rt)});
|
|
113
|
+
}
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
throw std::runtime_error("Cannot convert JSI value to C++ Variant value");
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
std::vector<std::string> to_string_vec(jsi::Runtime &rt, jsi::Value const &xs) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return res;
|
|
119
|
+
jsi::Array values = xs.asObject(rt).asArray(rt);
|
|
120
|
+
std::vector<std::string> res;
|
|
121
|
+
for (int ii = 0; ii < values.length(rt); ii++) {
|
|
122
|
+
std::string value = values.getValueAtIndex(rt, ii).asString(rt).utf8(rt);
|
|
123
|
+
res.emplace_back(value);
|
|
124
|
+
}
|
|
125
|
+
return res;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
std::vector<int> to_int_vec(jsi::Runtime &rt, jsi::Value const &xs) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
jsi::Array values = xs.asObject(rt).asArray(rt);
|
|
130
|
+
std::vector<int> res;
|
|
131
|
+
for (int ii = 0; ii < values.length(rt); ii++) {
|
|
132
|
+
int value = static_cast<int>(values.getValueAtIndex(rt, ii).asNumber());
|
|
133
|
+
res.emplace_back(value);
|
|
134
|
+
}
|
|
135
|
+
return res;
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
std::vector<JSVariant> to_variant_vec(jsi::Runtime &rt, jsi::Value const &xs) {
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
std::vector<JSVariant> res;
|
|
140
|
+
jsi::Array values = xs.asObject(rt).asArray(rt);
|
|
137
141
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
for (int ii = 0; ii < values.length(rt); ii++) {
|
|
143
|
+
jsi::Value value = values.getValueAtIndex(rt, ii);
|
|
144
|
+
res.emplace_back(to_variant(rt, value));
|
|
145
|
+
}
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
return res;
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
jsi::Value create_js_rows(jsi::Runtime &rt, const BridgeResult &status) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
151
|
+
jsi::Object res = jsi::Object(rt);
|
|
152
|
+
|
|
153
|
+
res.setProperty(rt, "rowsAffected", status.affectedRows);
|
|
154
|
+
if (status.affectedRows > 0 && status.insertId != 0) {
|
|
155
|
+
res.setProperty(rt, "insertId", jsi::Value(status.insertId));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
size_t row_count = status.rows.size();
|
|
159
|
+
size_t column_count = status.column_names.size();
|
|
160
|
+
|
|
161
|
+
std::vector<jsi::PropNameID> column_prop_ids;
|
|
162
|
+
column_prop_ids.reserve(column_count);
|
|
163
|
+
for (size_t i = 0; i < column_count; i++) {
|
|
164
|
+
column_prop_ids.emplace_back(
|
|
165
|
+
jsi::PropNameID::forUtf8(rt, status.column_names[i]));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
auto rows = jsi::Array(rt, row_count);
|
|
169
|
+
for (int i = 0; i < row_count; i++) {
|
|
170
|
+
auto row = jsi::Object(rt);
|
|
171
|
+
for (int j = 0; j < column_count; j++) {
|
|
172
|
+
row.setProperty(rt, column_prop_ids[j], to_jsi(rt, status.rows[i][j]));
|
|
167
173
|
}
|
|
168
|
-
|
|
174
|
+
rows.setValueAtIndex(rt, i, std::move(row));
|
|
175
|
+
}
|
|
176
|
+
res.setProperty(rt, "rows", std::move(rows));
|
|
169
177
|
|
|
170
|
-
|
|
171
|
-
auto column_array = jsi::Array(rt, column_count);
|
|
172
|
-
for (int i = 0; i < column_count; i++) {
|
|
173
|
-
auto column = status.column_names.at(i);
|
|
174
|
-
column_array.setValueAtIndex(rt, i, to_jsi(rt, column));
|
|
175
|
-
}
|
|
176
|
-
res.setProperty(rt, "columnNames", std::move(column_array));
|
|
177
|
-
return res;
|
|
178
|
+
return res;
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
jsi::Value
|
|
181
182
|
create_result(jsi::Runtime &rt, const BridgeResult &status,
|
|
182
183
|
std::vector<DumbHostObject> *results,
|
|
183
184
|
std::shared_ptr<std::vector<SmartHostObject>> metadata) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
185
|
+
jsi::Object res = jsi::Object(rt);
|
|
186
|
+
|
|
187
|
+
res.setProperty(rt, "rowsAffected", status.affectedRows);
|
|
188
|
+
if (status.affectedRows > 0 && status.insertId != 0) {
|
|
189
|
+
res.setProperty(rt, "insertId", jsi::Value(status.insertId));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
size_t rowCount = results->size();
|
|
193
|
+
|
|
194
|
+
auto array = jsi::Array(rt, rowCount);
|
|
195
|
+
for (int i = 0; i < rowCount; i++) {
|
|
196
|
+
auto obj = results->at(i);
|
|
197
|
+
array.setValueAtIndex(rt, i,
|
|
198
|
+
jsi::Object::createFromHostObject(
|
|
199
|
+
rt, std::make_shared<DumbHostObject>(obj)));
|
|
200
|
+
}
|
|
201
|
+
res.setProperty(rt, "rows", std::move(array));
|
|
202
|
+
|
|
203
|
+
size_t column_count = metadata->size();
|
|
204
|
+
auto column_array = jsi::Array(rt, column_count);
|
|
205
|
+
for (int i = 0; i < column_count; i++) {
|
|
206
|
+
auto column = metadata->at(i);
|
|
207
|
+
column_array.setValueAtIndex(
|
|
208
|
+
rt, i,
|
|
209
|
+
jsi::Object::createFromHostObject(
|
|
210
|
+
rt, std::make_shared<SmartHostObject>(column)));
|
|
211
|
+
}
|
|
212
|
+
res.setProperty(rt, "metadata", std::move(column_array));
|
|
213
|
+
|
|
214
|
+
return std::move(res);
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
jsi::Value
|
|
217
218
|
create_raw_result(jsi::Runtime &rt, const BridgeResult &status,
|
|
218
219
|
const std::vector<std::vector<JSVariant>> *results) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
res.setValueAtIndex(rt, i, array);
|
|
220
|
+
size_t row_count = results->size();
|
|
221
|
+
jsi::Array res = jsi::Array(rt, row_count);
|
|
222
|
+
for (int i = 0; i < row_count; i++) {
|
|
223
|
+
auto row = results->at(i);
|
|
224
|
+
auto array = jsi::Array(rt, row.size());
|
|
225
|
+
for (int j = 0; j < row.size(); j++) {
|
|
226
|
+
array.setValueAtIndex(rt, j, to_jsi(rt, row[j]));
|
|
228
227
|
}
|
|
229
|
-
|
|
228
|
+
res.setValueAtIndex(rt, i, array);
|
|
229
|
+
}
|
|
230
|
+
return res;
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
void to_batch_arguments(jsi::Runtime &rt, jsi::Array const &tuples,
|
|
233
234
|
std::vector<BatchArguments> *commands) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
235
|
+
for (int i = 0; i < tuples.length(rt); i++) {
|
|
236
|
+
const jsi::Array &tuple =
|
|
237
|
+
tuples.getValueAtIndex(rt, i).asObject(rt).asArray(rt);
|
|
238
|
+
const size_t length = tuple.length(rt);
|
|
239
|
+
if (length == 0) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
241
242
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
243
|
+
const std::string query =
|
|
244
|
+
tuple.getValueAtIndex(rt, 0).asString(rt).utf8(rt);
|
|
245
|
+
if (length == 1) {
|
|
246
|
+
commands->push_back({query});
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
248
249
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
auto params =
|
|
269
|
-
std::vector<JSVariant>(to_variant_vec(rt, tuple_params));
|
|
270
|
-
commands->push_back({query, params});
|
|
271
|
-
}
|
|
250
|
+
const jsi::Value &tuple_params = tuple.getValueAtIndex(rt, 1);
|
|
251
|
+
|
|
252
|
+
if (!tuple_params.isUndefined() && tuple_params.asObject(rt).isArray(rt) &&
|
|
253
|
+
tuple_params.asObject(rt).asArray(rt).length(rt) > 0 &&
|
|
254
|
+
tuple_params.asObject(rt)
|
|
255
|
+
.asArray(rt)
|
|
256
|
+
.getValueAtIndex(rt, 0)
|
|
257
|
+
.isObject()) {
|
|
258
|
+
// The params for this tuple is an array itself
|
|
259
|
+
// The query should repeat for each element in the array
|
|
260
|
+
const jsi::Array ¶ms_array = tuple_params.asObject(rt).asArray(rt);
|
|
261
|
+
for (int x = 0; x < params_array.length(rt); x++) {
|
|
262
|
+
const jsi::Value &p = params_array.getValueAtIndex(rt, x);
|
|
263
|
+
auto params = std::vector<JSVariant>(to_variant_vec(rt, p));
|
|
264
|
+
commands->push_back({query, params});
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
auto params = std::vector<JSVariant>(to_variant_vec(rt, tuple_params));
|
|
268
|
+
commands->push_back({query, params});
|
|
272
269
|
}
|
|
270
|
+
}
|
|
273
271
|
}
|
|
274
272
|
|
|
275
273
|
#ifndef OP_SQLITE_USE_LIBSQL
|
|
276
274
|
BatchResult import_sql_file(sqlite3 *db, std::string path) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
}
|
|
275
|
+
std::string line;
|
|
276
|
+
std::ifstream sqFile(path);
|
|
277
|
+
if (!sqFile.is_open()) {
|
|
278
|
+
throw std::runtime_error("Could not open file: " + path);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
try {
|
|
282
|
+
int affectedRows = 0;
|
|
283
|
+
int commands = 0;
|
|
284
|
+
opsqlite_execute(db, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
|
|
285
|
+
while (std::getline(sqFile, line, '\n')) {
|
|
286
|
+
if (!line.empty()) {
|
|
287
|
+
try {
|
|
288
|
+
auto result = opsqlite_execute(db, line, nullptr);
|
|
289
|
+
affectedRows += result.affectedRows;
|
|
290
|
+
commands++;
|
|
291
|
+
} catch (std::exception &exc) {
|
|
292
|
+
opsqlite_execute(db, "ROLLBACK", nullptr);
|
|
293
|
+
sqFile.close();
|
|
294
|
+
throw exc;
|
|
299
295
|
}
|
|
300
|
-
|
|
301
|
-
opsqlite_execute(db, "COMMIT", nullptr);
|
|
302
|
-
return {"", affectedRows, commands};
|
|
303
|
-
} catch (std::exception &exc) {
|
|
304
|
-
sqFile.close();
|
|
305
|
-
opsqlite_execute(db, "ROLLBACK", nullptr);
|
|
306
|
-
throw exc;
|
|
296
|
+
}
|
|
307
297
|
}
|
|
298
|
+
sqFile.close();
|
|
299
|
+
opsqlite_execute(db, "COMMIT", nullptr);
|
|
300
|
+
return {"", affectedRows, commands};
|
|
301
|
+
} catch (std::exception &exc) {
|
|
302
|
+
sqFile.close();
|
|
303
|
+
opsqlite_execute(db, "ROLLBACK", nullptr);
|
|
304
|
+
throw exc;
|
|
305
|
+
}
|
|
308
306
|
}
|
|
309
307
|
#endif
|
|
310
308
|
|
|
311
309
|
bool folder_exists(const std::string &name) {
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
struct stat buffer;
|
|
311
|
+
return (stat(name.c_str(), &buffer) == 0);
|
|
314
312
|
}
|
|
315
313
|
|
|
316
314
|
bool file_exists(const std::string &path) {
|
|
317
|
-
|
|
318
|
-
|
|
315
|
+
struct stat buffer;
|
|
316
|
+
return (stat(path.c_str(), &buffer) == 0);
|
|
319
317
|
}
|
|
320
318
|
|
|
321
319
|
void log_to_console(jsi::Runtime &runtime, const std::string &message) {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
320
|
+
auto console = runtime.global().getPropertyAsObject(runtime, "console");
|
|
321
|
+
auto log = console.getPropertyAsFunction(runtime, "log");
|
|
322
|
+
log.call(runtime, jsi::String::createFromUtf8(runtime, message));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
inline jsi::Function host_fn(jsi::Runtime &rt, jsi::HostFunctionType lambda) {
|
|
326
|
+
return jsi::Function::createFromHostFunction(
|
|
327
|
+
rt, jsi::PropNameID::forAscii(rt, ""), 0, std::move(lambda));
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
jsi::Value
|
|
331
|
+
promisify(jsi::Runtime &rt, std::function<std::any()> lambda,
|
|
332
|
+
std::function<jsi::Value(jsi::Runtime &rt, std::any result)>
|
|
333
|
+
resolve_callback) {
|
|
334
|
+
auto promise_constructor = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
335
|
+
|
|
336
|
+
auto executor = host_fn(rt, [lambda = std::move(lambda),
|
|
337
|
+
resolve_callback = std::move(resolve_callback)](
|
|
338
|
+
jsi::Runtime &rt, const jsi::Value &thiz,
|
|
339
|
+
const jsi::Value *args, size_t count) {
|
|
340
|
+
auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
|
|
341
|
+
auto reject = std::make_shared<jsi::Value>(rt, args[1]);
|
|
342
|
+
|
|
343
|
+
auto task = [lambda = lambda, resolve_callback = resolve_callback,
|
|
344
|
+
resolve = std::move(resolve), reject = std::move(reject)]() {
|
|
345
|
+
try {
|
|
346
|
+
std::any result = lambda();
|
|
347
|
+
|
|
348
|
+
if (opsqlite::invalidated) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
opsqlite::invoker->invokeAsync(
|
|
353
|
+
[result = std::move(result), resolve = resolve,
|
|
354
|
+
resolve_callback = resolve_callback](jsi::Runtime &rt) {
|
|
355
|
+
auto jsi_result = resolve_callback(rt, result);
|
|
356
|
+
resolve->asObject(rt).asFunction(rt).call(rt, jsi_result);
|
|
357
|
+
});
|
|
358
|
+
} catch (std::runtime_error &e) {
|
|
359
|
+
// On Android RN is broken and does not correctly match
|
|
360
|
+
// runtime_error to the generic exception We have to
|
|
361
|
+
// explicitly catch it
|
|
362
|
+
// https://github.com/facebook/react-native/issues/48027
|
|
363
|
+
auto what = e.what();
|
|
364
|
+
opsqlite::invoker->invokeAsync(
|
|
365
|
+
[what = std::string(what), reject = reject](jsi::Runtime &rt) {
|
|
366
|
+
auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
|
|
367
|
+
auto error = errorCtr.callAsConstructor(
|
|
368
|
+
rt, jsi::String::createFromAscii(rt, what));
|
|
369
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
370
|
+
});
|
|
371
|
+
} catch (std::exception &exc) {
|
|
372
|
+
auto what = exc.what();
|
|
373
|
+
opsqlite::invoker->invokeAsync(
|
|
374
|
+
[what = std::string(what), reject = reject](jsi::Runtime &rt) {
|
|
375
|
+
auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
|
|
376
|
+
auto error = errorCtr.callAsConstructor(
|
|
377
|
+
rt, jsi::String::createFromAscii(rt, what));
|
|
378
|
+
reject->asObject(rt).asFunction(rt).call(rt, error);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
__thread_pool->queueWork(task);
|
|
384
|
+
|
|
385
|
+
return jsi::Value(nullptr);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
auto promise = promise_constructor.callAsConstructor(rt, executor);
|
|
389
|
+
return promise;
|
|
325
390
|
}
|
|
326
391
|
|
|
327
392
|
} // namespace opsqlite
|