@op-engineering/op-sqlite 7.3.0 → 8.0.0-beta0
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 +11 -3
- package/android/CMakeLists.txt +6 -0
- package/android/build.gradle +20 -1
- package/android/cpp-adapter.cpp +1 -1
- package/android/src/main/jniLibs/arm64-v8a/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/x86/libsqlite_vec.so +0 -0
- package/android/src/main/jniLibs/x86_64/libsqlite_vec.so +0 -0
- package/cpp/DBHostObject.cpp +104 -107
- package/cpp/DBHostObject.h +1 -1
- package/cpp/PreparedStatementHostObject.cpp +39 -14
- package/cpp/PreparedStatementHostObject.h +17 -4
- package/cpp/bindings.cpp +12 -9
- package/cpp/bindings.h +2 -1
- package/cpp/bridge.cpp +229 -91
- package/cpp/bridge.h +13 -9
- package/cpp/libsql/bridge.cpp +212 -92
- package/cpp/libsql/bridge.h +7 -3
- package/cpp/macros.h +2 -2
- package/cpp/types.h +11 -8
- package/cpp/utils.cpp +43 -7
- package/cpp/utils.h +2 -0
- package/ios/OPSQLite.mm +15 -5
- package/ios/sqlitevec.xcframework/Info.plist +46 -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/lib/commonjs/index.js +53 -30
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- package/lib/module/NativeOPSQLite.js +2 -0
- package/lib/module/NativeOPSQLite.js.map +1 -1
- package/lib/module/index.js +55 -29
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/NativeOPSQLite.d.ts.map +1 -0
- package/lib/typescript/{src → commonjs/src}/index.d.ts +11 -11
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/NativeOPSQLite.d.ts +15 -0
- package/lib/typescript/module/src/NativeOPSQLite.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +163 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/op-sqlite.podspec +13 -4
- package/package.json +45 -15
- package/src/index.ts +80 -46
- package/android/.project +0 -17
- package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
- package/lib/typescript/src/NativeOPSQLite.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts.map +0 -1
- /package/lib/typescript/{src → commonjs/src}/NativeOPSQLite.d.ts +0 -0
package/cpp/bridge.cpp
CHANGED
|
@@ -51,12 +51,14 @@ std::string opsqlite_get_db_path(std::string const &db_name,
|
|
|
51
51
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
52
52
|
BridgeResult opsqlite_open(std::string const &dbName,
|
|
53
53
|
std::string const &last_path,
|
|
54
|
-
std::string const &
|
|
54
|
+
std::string const &crsqlite_path,
|
|
55
|
+
std::string const &sqlite_vec_path,
|
|
55
56
|
std::string const &encryptionKey) {
|
|
56
57
|
#else
|
|
57
58
|
BridgeResult opsqlite_open(std::string const &dbName,
|
|
58
59
|
std::string const &last_path,
|
|
59
|
-
std::string const &
|
|
60
|
+
std::string const &crsqlite_path,
|
|
61
|
+
std::string const &sqlite_vec_path) {
|
|
60
62
|
#endif
|
|
61
63
|
std::string dbPath = opsqlite_get_db_path(dbName, last_path);
|
|
62
64
|
|
|
@@ -74,17 +76,18 @@ BridgeResult opsqlite_open(std::string const &dbName,
|
|
|
74
76
|
dbMap[dbName] = db;
|
|
75
77
|
|
|
76
78
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
77
|
-
opsqlite_execute(dbName, "PRAGMA key = '" + encryptionKey + "'", nullptr
|
|
78
|
-
nullptr, nullptr);
|
|
79
|
+
opsqlite_execute(dbName, "PRAGMA key = '" + encryptionKey + "'", nullptr);
|
|
79
80
|
#endif
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
sqlite3_enable_load_extension(db, 1);
|
|
83
|
+
|
|
82
84
|
char *errMsg;
|
|
83
|
-
const char *crsqliteEntryPoint = "sqlite3_crsqlite_init";
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
#ifdef OP_SQLITE_USE_CRSQLITE
|
|
87
|
+
const char *crsqliteEntryPoint = "sqlite3_crsqlite_init";
|
|
86
88
|
|
|
87
|
-
sqlite3_load_extension(db,
|
|
89
|
+
sqlite3_load_extension(db, crsqlite_path.c_str(), crsqliteEntryPoint,
|
|
90
|
+
&errMsg);
|
|
88
91
|
|
|
89
92
|
if (errMsg != nullptr) {
|
|
90
93
|
return {.type = SQLiteError, .message = errMsg};
|
|
@@ -93,6 +96,19 @@ BridgeResult opsqlite_open(std::string const &dbName,
|
|
|
93
96
|
}
|
|
94
97
|
#endif
|
|
95
98
|
|
|
99
|
+
#ifdef OP_SQLITE_USE_SQLITE_VEC
|
|
100
|
+
const char *vec_entry_point = "sqlite3_vec_init";
|
|
101
|
+
|
|
102
|
+
sqlite3_load_extension(db, sqlite_vec_path.c_str(), vec_entry_point, &errMsg);
|
|
103
|
+
|
|
104
|
+
if (errMsg != nullptr) {
|
|
105
|
+
return {.type = SQLiteError, .message = errMsg};
|
|
106
|
+
} else {
|
|
107
|
+
LOGI("Loaded sqlite-vec successfully");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#endif
|
|
111
|
+
|
|
96
112
|
return {.type = SQLiteOk, .affectedRows = 0};
|
|
97
113
|
}
|
|
98
114
|
|
|
@@ -103,8 +119,7 @@ BridgeResult opsqlite_close(std::string const &dbName) {
|
|
|
103
119
|
sqlite3 *db = dbMap[dbName];
|
|
104
120
|
|
|
105
121
|
#ifdef OP_SQLITE_USE_CRSQLITE
|
|
106
|
-
opsqlite_execute(dbName, "select crsql_finalize();", nullptr
|
|
107
|
-
nullptr);
|
|
122
|
+
opsqlite_execute(dbName, "select crsql_finalize();", nullptr);
|
|
108
123
|
#endif
|
|
109
124
|
|
|
110
125
|
sqlite3_close_v2(db);
|
|
@@ -123,8 +138,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
123
138
|
std::string dbPath = opsqlite_get_db_path(databaseToAttach, docPath);
|
|
124
139
|
std::string statement = "ATTACH DATABASE '" + dbPath + "' AS " + alias;
|
|
125
140
|
|
|
126
|
-
BridgeResult result =
|
|
127
|
-
opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
|
|
141
|
+
BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
|
|
128
142
|
|
|
129
143
|
if (result.type == SQLiteError) {
|
|
130
144
|
return {
|
|
@@ -141,8 +155,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
141
155
|
BridgeResult opsqlite_detach(std::string const &mainDBName,
|
|
142
156
|
std::string const &alias) {
|
|
143
157
|
std::string statement = "DETACH DATABASE " + alias;
|
|
144
|
-
BridgeResult result =
|
|
145
|
-
opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
|
|
158
|
+
BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
|
|
146
159
|
if (result.type == SQLiteError) {
|
|
147
160
|
return BridgeResult{
|
|
148
161
|
.type = SQLiteError,
|
|
@@ -189,22 +202,22 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
189
202
|
int sqIndex = ii + 1;
|
|
190
203
|
JSVariant value = values->at(ii);
|
|
191
204
|
|
|
192
|
-
if (std::holds_alternative<bool>(value)
|
|
193
|
-
|
|
194
|
-
} else if (std::holds_alternative<int>(value)) {
|
|
205
|
+
if (std::holds_alternative<bool>(value) ||
|
|
206
|
+
std::holds_alternative<int>(value)) {
|
|
195
207
|
sqlite3_bind_int(statement, sqIndex, std::get<int>(value));
|
|
196
208
|
} else if (std::holds_alternative<long long>(value)) {
|
|
197
|
-
sqlite3_bind_double(statement, sqIndex,
|
|
209
|
+
sqlite3_bind_double(statement, sqIndex,
|
|
210
|
+
static_cast<double>(std::get<long long>(value)));
|
|
198
211
|
} else if (std::holds_alternative<double>(value)) {
|
|
199
212
|
sqlite3_bind_double(statement, sqIndex, std::get<double>(value));
|
|
200
213
|
} else if (std::holds_alternative<std::string>(value)) {
|
|
201
214
|
std::string str = std::get<std::string>(value);
|
|
202
|
-
sqlite3_bind_text(statement, sqIndex, str.c_str(),
|
|
203
|
-
SQLITE_TRANSIENT);
|
|
215
|
+
sqlite3_bind_text(statement, sqIndex, str.c_str(),
|
|
216
|
+
static_cast<int>(str.length()), SQLITE_TRANSIENT);
|
|
204
217
|
} else if (std::holds_alternative<ArrayBuffer>(value)) {
|
|
205
218
|
ArrayBuffer buffer = std::get<ArrayBuffer>(value);
|
|
206
|
-
sqlite3_bind_blob(statement, sqIndex, buffer.data.get(),
|
|
207
|
-
SQLITE_TRANSIENT);
|
|
219
|
+
sqlite3_bind_blob(statement, sqIndex, buffer.data.get(),
|
|
220
|
+
static_cast<int>(buffer.size), SQLITE_TRANSIENT);
|
|
208
221
|
} else {
|
|
209
222
|
sqlite3_bind_null(statement, sqIndex);
|
|
210
223
|
}
|
|
@@ -214,7 +227,7 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
214
227
|
BridgeResult opsqlite_execute_prepared_statement(
|
|
215
228
|
std::string const &dbName, sqlite3_stmt *statement,
|
|
216
229
|
std::vector<DumbHostObject> *results,
|
|
217
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas) {
|
|
230
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
|
|
218
231
|
|
|
219
232
|
check_db_open(dbName);
|
|
220
233
|
|
|
@@ -227,8 +240,6 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
227
240
|
|
|
228
241
|
int result = SQLITE_OK;
|
|
229
242
|
|
|
230
|
-
isConsuming = true;
|
|
231
|
-
|
|
232
243
|
int i, count, column_type;
|
|
233
244
|
std::string column_name, column_declared_type;
|
|
234
245
|
|
|
@@ -237,7 +248,7 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
237
248
|
|
|
238
249
|
switch (result) {
|
|
239
250
|
case SQLITE_ROW: {
|
|
240
|
-
if (results ==
|
|
251
|
+
if (results == nullptr) {
|
|
241
252
|
break;
|
|
242
253
|
}
|
|
243
254
|
|
|
@@ -256,13 +267,13 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
256
267
|
* only represent Integers up to 53 bits
|
|
257
268
|
*/
|
|
258
269
|
double column_value = sqlite3_column_double(statement, i);
|
|
259
|
-
row.values.
|
|
270
|
+
row.values.emplace_back(column_value);
|
|
260
271
|
break;
|
|
261
272
|
}
|
|
262
273
|
|
|
263
274
|
case SQLITE_FLOAT: {
|
|
264
275
|
double column_value = sqlite3_column_double(statement, i);
|
|
265
|
-
row.values.
|
|
276
|
+
row.values.emplace_back(column_value);
|
|
266
277
|
break;
|
|
267
278
|
}
|
|
268
279
|
|
|
@@ -271,20 +282,20 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
271
282
|
reinterpret_cast<const char *>(sqlite3_column_text(statement, i));
|
|
272
283
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
273
284
|
// Specify length too; in case string contains NULL in the middle
|
|
274
|
-
row.values.
|
|
285
|
+
row.values.emplace_back(std::string(column_value, byteLen));
|
|
275
286
|
break;
|
|
276
287
|
}
|
|
277
288
|
|
|
278
289
|
case SQLITE_BLOB: {
|
|
279
290
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
280
291
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
281
|
-
|
|
292
|
+
auto *data = new uint8_t[blob_size];
|
|
282
293
|
// You cannot share raw memory between native and JS
|
|
283
294
|
// always copy the data
|
|
284
295
|
memcpy(data, blob, blob_size);
|
|
285
|
-
row.values.
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
row.values.emplace_back(
|
|
297
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
298
|
+
.size = static_cast<size_t>(blob_size)});
|
|
288
299
|
break;
|
|
289
300
|
}
|
|
290
301
|
|
|
@@ -292,14 +303,16 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
292
303
|
// Intentionally left blank
|
|
293
304
|
|
|
294
305
|
default:
|
|
295
|
-
row.values.
|
|
306
|
+
row.values.emplace_back(nullptr);
|
|
296
307
|
break;
|
|
297
308
|
}
|
|
298
309
|
i++;
|
|
299
310
|
}
|
|
311
|
+
|
|
300
312
|
if (results != nullptr) {
|
|
301
313
|
results->push_back(row);
|
|
302
314
|
}
|
|
315
|
+
|
|
303
316
|
break;
|
|
304
317
|
}
|
|
305
318
|
|
|
@@ -312,10 +325,10 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
312
325
|
column_name = sqlite3_column_name(statement, i);
|
|
313
326
|
const char *type = sqlite3_column_decltype(statement, i);
|
|
314
327
|
auto metadata = SmartHostObject();
|
|
315
|
-
metadata.fields.
|
|
316
|
-
metadata.fields.
|
|
317
|
-
metadata.fields.
|
|
318
|
-
|
|
328
|
+
metadata.fields.emplace_back("name", column_name);
|
|
329
|
+
metadata.fields.emplace_back("index", i);
|
|
330
|
+
metadata.fields.emplace_back("type",
|
|
331
|
+
type == nullptr ? "UNKNOWN" : type);
|
|
319
332
|
|
|
320
333
|
metadatas->push_back(metadata);
|
|
321
334
|
i++;
|
|
@@ -357,7 +370,8 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
|
|
|
357
370
|
|
|
358
371
|
const char *queryStr = query.c_str();
|
|
359
372
|
|
|
360
|
-
int statementStatus =
|
|
373
|
+
int statementStatus =
|
|
374
|
+
sqlite3_prepare_v2(db, queryStr, -1, &statement, nullptr);
|
|
361
375
|
|
|
362
376
|
if (statementStatus == SQLITE_ERROR) {
|
|
363
377
|
const char *message = sqlite3_errmsg(db);
|
|
@@ -368,12 +382,144 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
|
|
|
368
382
|
return statement;
|
|
369
383
|
}
|
|
370
384
|
|
|
385
|
+
BridgeResult opsqlite_execute(std::string const &name, std::string const &query,
|
|
386
|
+
const std::vector<JSVariant> *params) {
|
|
387
|
+
check_db_open(name);
|
|
388
|
+
|
|
389
|
+
sqlite3 *db = dbMap[name];
|
|
390
|
+
|
|
391
|
+
sqlite3_stmt *statement;
|
|
392
|
+
const char *errorMessage;
|
|
393
|
+
const char *remainingStatement = nullptr;
|
|
394
|
+
|
|
395
|
+
bool isFailed = false;
|
|
396
|
+
int step_result, current_column, column_count, column_type;
|
|
397
|
+
std::string column_name, column_declared_type;
|
|
398
|
+
std::vector<std::string> column_names;
|
|
399
|
+
std::vector<std::vector<JSVariant>> rows;
|
|
400
|
+
std::vector<JSVariant> row;
|
|
401
|
+
|
|
402
|
+
do {
|
|
403
|
+
const char *queryStr =
|
|
404
|
+
remainingStatement == nullptr ? query.c_str() : remainingStatement;
|
|
405
|
+
|
|
406
|
+
int statementStatus =
|
|
407
|
+
sqlite3_prepare_v2(db, queryStr, -1, &statement, &remainingStatement);
|
|
408
|
+
|
|
409
|
+
if (statementStatus != SQLITE_OK) {
|
|
410
|
+
errorMessage = sqlite3_errmsg(db);
|
|
411
|
+
return {.type = SQLiteError,
|
|
412
|
+
.message =
|
|
413
|
+
"[op-sqlite] SQL prepare error: " + std::string(errorMessage),
|
|
414
|
+
.affectedRows = 0};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (params != nullptr && !params->empty()) {
|
|
418
|
+
opsqlite_bind_statement(statement, params);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
column_count = sqlite3_column_count(statement);
|
|
422
|
+
bool is_consuming = true;
|
|
423
|
+
// Do a first pass to get the column names
|
|
424
|
+
for (int i = 0; i < column_count; i++) {
|
|
425
|
+
column_name = sqlite3_column_name(statement, i);
|
|
426
|
+
column_names.push_back(column_name);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
double double_value;
|
|
430
|
+
const char *string_value;
|
|
431
|
+
while (is_consuming) {
|
|
432
|
+
step_result = sqlite3_step(statement);
|
|
433
|
+
|
|
434
|
+
switch (step_result) {
|
|
435
|
+
case SQLITE_ROW:
|
|
436
|
+
current_column = 0;
|
|
437
|
+
row = std::vector<JSVariant>();
|
|
438
|
+
column_count = sqlite3_column_count(statement);
|
|
439
|
+
|
|
440
|
+
while (current_column < column_count) {
|
|
441
|
+
column_type = sqlite3_column_type(statement, current_column);
|
|
442
|
+
|
|
443
|
+
switch (column_type) {
|
|
444
|
+
|
|
445
|
+
case SQLITE_INTEGER:
|
|
446
|
+
// intentional fallthrough
|
|
447
|
+
case SQLITE_FLOAT: {
|
|
448
|
+
double_value = sqlite3_column_double(statement, current_column);
|
|
449
|
+
row.emplace_back(double_value);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
case SQLITE_TEXT: {
|
|
454
|
+
string_value = reinterpret_cast<const char *>(
|
|
455
|
+
sqlite3_column_text(statement, current_column));
|
|
456
|
+
int byteLen = sqlite3_column_bytes(statement, current_column);
|
|
457
|
+
// Specify length too; in case string contains NULL in the middle
|
|
458
|
+
row.emplace_back(std::string(string_value, byteLen));
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
case SQLITE_BLOB: {
|
|
463
|
+
int blob_size = sqlite3_column_bytes(statement, current_column);
|
|
464
|
+
const void *blob = sqlite3_column_blob(statement, current_column);
|
|
465
|
+
auto *data = new uint8_t[blob_size];
|
|
466
|
+
memcpy(data, blob, blob_size);
|
|
467
|
+
row.emplace_back(
|
|
468
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
469
|
+
.size = static_cast<size_t>(blob_size)});
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
case SQLITE_NULL:
|
|
474
|
+
// Intentionally left blank to switch to default case
|
|
475
|
+
default:
|
|
476
|
+
row.emplace_back(nullptr);
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
current_column++;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
rows.push_back(row);
|
|
484
|
+
break;
|
|
485
|
+
|
|
486
|
+
case SQLITE_DONE:
|
|
487
|
+
is_consuming = false;
|
|
488
|
+
break;
|
|
489
|
+
|
|
490
|
+
default:
|
|
491
|
+
isFailed = true;
|
|
492
|
+
is_consuming = false;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
sqlite3_finalize(statement);
|
|
497
|
+
} while (remainingStatement != nullptr &&
|
|
498
|
+
strcmp(remainingStatement, "") != 0 && !isFailed);
|
|
499
|
+
|
|
500
|
+
if (isFailed) {
|
|
501
|
+
const char *message = sqlite3_errmsg(db);
|
|
502
|
+
return {.type = SQLiteError,
|
|
503
|
+
.message =
|
|
504
|
+
"[op-sqlite] SQL execution error: " + std::string(message),
|
|
505
|
+
.affectedRows = 0,
|
|
506
|
+
.insertId = 0};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
int changedRowCount = sqlite3_changes(db);
|
|
510
|
+
long long latestInsertRowId = sqlite3_last_insert_rowid(db);
|
|
511
|
+
return {.type = SQLiteOk,
|
|
512
|
+
.affectedRows = changedRowCount,
|
|
513
|
+
.insertId = static_cast<double>(latestInsertRowId),
|
|
514
|
+
.rows = std::move(rows),
|
|
515
|
+
.column_names = std::move(column_names)};
|
|
516
|
+
}
|
|
517
|
+
|
|
371
518
|
/// Base execution function, returns HostObjects to the JS environment
|
|
372
|
-
BridgeResult
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas) {
|
|
519
|
+
BridgeResult opsqlite_execute_host_objects(
|
|
520
|
+
std::string const &dbName, std::string const &query,
|
|
521
|
+
const std::vector<JSVariant> *params, std::vector<DumbHostObject> *results,
|
|
522
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
|
|
377
523
|
|
|
378
524
|
check_db_open(dbName);
|
|
379
525
|
|
|
@@ -406,16 +552,14 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
406
552
|
|
|
407
553
|
// The statement did not fail to parse but there is nothing to do, just
|
|
408
554
|
// skip to the end
|
|
409
|
-
if (statement ==
|
|
555
|
+
if (statement == nullptr) {
|
|
410
556
|
continue;
|
|
411
557
|
}
|
|
412
558
|
|
|
413
|
-
if (params != nullptr && params->
|
|
559
|
+
if (params != nullptr && !params->empty()) {
|
|
414
560
|
opsqlite_bind_statement(statement, params);
|
|
415
561
|
}
|
|
416
562
|
|
|
417
|
-
isConsuming = true;
|
|
418
|
-
|
|
419
563
|
int i, count, column_type;
|
|
420
564
|
std::string column_name, column_declared_type;
|
|
421
565
|
|
|
@@ -424,7 +568,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
424
568
|
|
|
425
569
|
switch (result) {
|
|
426
570
|
case SQLITE_ROW: {
|
|
427
|
-
if (results ==
|
|
571
|
+
if (results == nullptr) {
|
|
428
572
|
break;
|
|
429
573
|
}
|
|
430
574
|
|
|
@@ -443,13 +587,13 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
443
587
|
* only represent Integers up to 53 bits
|
|
444
588
|
*/
|
|
445
589
|
double column_value = sqlite3_column_double(statement, i);
|
|
446
|
-
row.values.
|
|
590
|
+
row.values.emplace_back(column_value);
|
|
447
591
|
break;
|
|
448
592
|
}
|
|
449
593
|
|
|
450
594
|
case SQLITE_FLOAT: {
|
|
451
595
|
double column_value = sqlite3_column_double(statement, i);
|
|
452
|
-
row.values.
|
|
596
|
+
row.values.emplace_back(column_value);
|
|
453
597
|
break;
|
|
454
598
|
}
|
|
455
599
|
|
|
@@ -458,20 +602,20 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
458
602
|
sqlite3_column_text(statement, i));
|
|
459
603
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
460
604
|
// Specify length too; in case string contains NULL in the middle
|
|
461
|
-
row.values.
|
|
605
|
+
row.values.emplace_back(std::string(column_value, byteLen));
|
|
462
606
|
break;
|
|
463
607
|
}
|
|
464
608
|
|
|
465
609
|
case SQLITE_BLOB: {
|
|
466
610
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
467
611
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
468
|
-
|
|
612
|
+
auto *data = new uint8_t[blob_size];
|
|
469
613
|
// You cannot share raw memory between native and JS
|
|
470
614
|
// always copy the data
|
|
471
615
|
memcpy(data, blob, blob_size);
|
|
472
|
-
row.values.
|
|
473
|
-
|
|
474
|
-
|
|
616
|
+
row.values.emplace_back(
|
|
617
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
618
|
+
.size = static_cast<size_t>(blob_size)});
|
|
475
619
|
break;
|
|
476
620
|
}
|
|
477
621
|
|
|
@@ -479,7 +623,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
479
623
|
// Intentionally left blank
|
|
480
624
|
|
|
481
625
|
default:
|
|
482
|
-
row.values.
|
|
626
|
+
row.values.emplace_back(nullptr);
|
|
483
627
|
break;
|
|
484
628
|
}
|
|
485
629
|
i++;
|
|
@@ -499,10 +643,10 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
499
643
|
column_name = sqlite3_column_name(statement, i);
|
|
500
644
|
const char *type = sqlite3_column_decltype(statement, i);
|
|
501
645
|
auto metadata = SmartHostObject();
|
|
502
|
-
metadata.fields.
|
|
503
|
-
metadata.fields.
|
|
504
|
-
metadata.fields.
|
|
505
|
-
|
|
646
|
+
metadata.fields.emplace_back("name", column_name);
|
|
647
|
+
metadata.fields.emplace_back("index", i);
|
|
648
|
+
metadata.fields.emplace_back("type",
|
|
649
|
+
type == nullptr ? "UNKNOWN" : type);
|
|
506
650
|
|
|
507
651
|
metadatas->push_back(metadata);
|
|
508
652
|
i++;
|
|
@@ -519,8 +663,8 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
519
663
|
}
|
|
520
664
|
|
|
521
665
|
sqlite3_finalize(statement);
|
|
522
|
-
} while (remainingStatement !=
|
|
523
|
-
!isFailed);
|
|
666
|
+
} while (remainingStatement != nullptr &&
|
|
667
|
+
strcmp(remainingStatement, "") != 0 && !isFailed);
|
|
524
668
|
|
|
525
669
|
if (isFailed) {
|
|
526
670
|
|
|
@@ -577,16 +721,14 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
577
721
|
|
|
578
722
|
// The statement did not fail to parse but there is nothing to do, just
|
|
579
723
|
// skip to the end
|
|
580
|
-
if (statement ==
|
|
724
|
+
if (statement == nullptr) {
|
|
581
725
|
continue;
|
|
582
726
|
}
|
|
583
727
|
|
|
584
|
-
if (params != nullptr && params->
|
|
728
|
+
if (params != nullptr && !params->empty()) {
|
|
585
729
|
opsqlite_bind_statement(statement, params);
|
|
586
730
|
}
|
|
587
731
|
|
|
588
|
-
isConsuming = true;
|
|
589
|
-
|
|
590
732
|
int i, count, column_type;
|
|
591
733
|
std::string column_name, column_declared_type;
|
|
592
734
|
|
|
@@ -615,13 +757,13 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
615
757
|
* only represent Integers up to 53 bits
|
|
616
758
|
*/
|
|
617
759
|
double column_value = sqlite3_column_double(statement, i);
|
|
618
|
-
row.
|
|
760
|
+
row.emplace_back(column_value);
|
|
619
761
|
break;
|
|
620
762
|
}
|
|
621
763
|
|
|
622
764
|
case SQLITE_FLOAT: {
|
|
623
765
|
double column_value = sqlite3_column_double(statement, i);
|
|
624
|
-
row.
|
|
766
|
+
row.emplace_back(column_value);
|
|
625
767
|
break;
|
|
626
768
|
}
|
|
627
769
|
|
|
@@ -630,27 +772,25 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
630
772
|
sqlite3_column_text(statement, i));
|
|
631
773
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
632
774
|
// Specify length too; in case string contains NULL in the middle
|
|
633
|
-
row.
|
|
775
|
+
row.emplace_back(std::string(column_value, byteLen));
|
|
634
776
|
break;
|
|
635
777
|
}
|
|
636
778
|
|
|
637
779
|
case SQLITE_BLOB: {
|
|
638
780
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
639
781
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
640
|
-
|
|
782
|
+
auto *data = new uint8_t[blob_size];
|
|
641
783
|
memcpy(data, blob, blob_size);
|
|
642
|
-
row.
|
|
643
|
-
|
|
644
|
-
|
|
784
|
+
row.emplace_back(
|
|
785
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
786
|
+
.size = static_cast<size_t>(blob_size)});
|
|
645
787
|
break;
|
|
646
788
|
}
|
|
647
789
|
|
|
648
790
|
case SQLITE_NULL:
|
|
649
|
-
|
|
650
|
-
break;
|
|
651
|
-
|
|
791
|
+
// intentional fallthrough
|
|
652
792
|
default:
|
|
653
|
-
row.
|
|
793
|
+
row.emplace_back(nullptr);
|
|
654
794
|
break;
|
|
655
795
|
}
|
|
656
796
|
i++;
|
|
@@ -673,8 +813,8 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
673
813
|
}
|
|
674
814
|
|
|
675
815
|
sqlite3_finalize(statement);
|
|
676
|
-
} while (remainingStatement !=
|
|
677
|
-
!isFailed);
|
|
816
|
+
} while (remainingStatement != nullptr &&
|
|
817
|
+
strcmp(remainingStatement, "") != 0 && !isFailed);
|
|
678
818
|
|
|
679
819
|
if (isFailed) {
|
|
680
820
|
|
|
@@ -756,7 +896,7 @@ BridgeResult opsqlite_deregister_update_hook(std::string const &dbName) {
|
|
|
756
896
|
sqlite3 *db = dbMap[dbName];
|
|
757
897
|
updateCallbackMap.erase(dbName);
|
|
758
898
|
|
|
759
|
-
sqlite3_update_hook(db,
|
|
899
|
+
sqlite3_update_hook(db, nullptr, nullptr);
|
|
760
900
|
|
|
761
901
|
return {SQLiteOk};
|
|
762
902
|
}
|
|
@@ -794,7 +934,7 @@ BridgeResult opsqlite_deregister_commit_hook(std::string const &dbName) {
|
|
|
794
934
|
|
|
795
935
|
sqlite3 *db = dbMap[dbName];
|
|
796
936
|
commitCallbackMap.erase(dbName);
|
|
797
|
-
sqlite3_commit_hook(db,
|
|
937
|
+
sqlite3_commit_hook(db, nullptr, nullptr);
|
|
798
938
|
|
|
799
939
|
return {SQLiteOk};
|
|
800
940
|
}
|
|
@@ -831,7 +971,7 @@ BridgeResult opsqlite_deregister_rollback_hook(std::string const &dbName) {
|
|
|
831
971
|
sqlite3 *db = dbMap[dbName];
|
|
832
972
|
rollbackCallbackMap.erase(dbName);
|
|
833
973
|
|
|
834
|
-
sqlite3_rollback_hook(db,
|
|
974
|
+
sqlite3_rollback_hook(db, nullptr, nullptr);
|
|
835
975
|
|
|
836
976
|
return {SQLiteOk};
|
|
837
977
|
}
|
|
@@ -867,7 +1007,7 @@ BridgeResult opsqlite_load_extension(std::string const &db_name,
|
|
|
867
1007
|
#endif
|
|
868
1008
|
}
|
|
869
1009
|
|
|
870
|
-
BatchResult opsqlite_execute_batch(std::string
|
|
1010
|
+
BatchResult opsqlite_execute_batch(std::string &name,
|
|
871
1011
|
std::vector<BatchArguments> *commands) {
|
|
872
1012
|
size_t commandCount = commands->size();
|
|
873
1013
|
if (commandCount <= 0) {
|
|
@@ -879,16 +1019,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
|
|
|
879
1019
|
|
|
880
1020
|
try {
|
|
881
1021
|
int affectedRows = 0;
|
|
882
|
-
opsqlite_execute(
|
|
883
|
-
nullptr);
|
|
1022
|
+
opsqlite_execute(name, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
|
|
884
1023
|
for (int i = 0; i < commandCount; i++) {
|
|
885
1024
|
auto command = commands->at(i);
|
|
886
1025
|
// We do not provide a datastructure to receive query data because we
|
|
887
1026
|
// don't need/want to handle this results in a batch execution
|
|
888
|
-
auto result = opsqlite_execute(
|
|
889
|
-
nullptr, nullptr);
|
|
1027
|
+
auto result = opsqlite_execute(name, command.sql, command.params.get());
|
|
890
1028
|
if (result.type == SQLiteError) {
|
|
891
|
-
opsqlite_execute(
|
|
1029
|
+
opsqlite_execute(name, "ROLLBACK", nullptr);
|
|
892
1030
|
return BatchResult{
|
|
893
1031
|
.type = SQLiteError,
|
|
894
1032
|
.message = result.message,
|
|
@@ -897,14 +1035,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
|
|
|
897
1035
|
affectedRows += result.affectedRows;
|
|
898
1036
|
}
|
|
899
1037
|
}
|
|
900
|
-
opsqlite_execute(
|
|
1038
|
+
opsqlite_execute(name, "COMMIT", nullptr);
|
|
901
1039
|
return BatchResult{
|
|
902
1040
|
.type = SQLiteOk,
|
|
903
1041
|
.affectedRows = affectedRows,
|
|
904
1042
|
.commands = static_cast<int>(commandCount),
|
|
905
1043
|
};
|
|
906
1044
|
} catch (std::exception &exc) {
|
|
907
|
-
opsqlite_execute(
|
|
1045
|
+
opsqlite_execute(name, "ROLLBACK", nullptr);
|
|
908
1046
|
return BatchResult{
|
|
909
1047
|
.type = SQLiteError,
|
|
910
1048
|
.message = exc.what(),
|
package/cpp/bridge.h
CHANGED
|
@@ -24,11 +24,13 @@ std::string opsqlite_get_db_path(std::string const &db_name,
|
|
|
24
24
|
|
|
25
25
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
26
26
|
BridgeResult opsqlite_open(std::string const &dbName, std::string const &dbPath,
|
|
27
|
-
std::string const &
|
|
27
|
+
std::string const &crsqlite_path,
|
|
28
|
+
std::string const &sqlite_vec_path,
|
|
28
29
|
std::string const &encryptionKey);
|
|
29
30
|
#else
|
|
30
31
|
BridgeResult opsqlite_open(std::string const &dbName, std::string const &dbPath,
|
|
31
|
-
std::string const &
|
|
32
|
+
std::string const &crsqlite_path,
|
|
33
|
+
std::string const &sqlite_vec_path);
|
|
32
34
|
#endif
|
|
33
35
|
|
|
34
36
|
BridgeResult opsqlite_close(std::string const &dbName);
|
|
@@ -44,13 +46,15 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
44
46
|
BridgeResult opsqlite_detach(std::string const &mainDBName,
|
|
45
47
|
std::string const &alias);
|
|
46
48
|
|
|
47
|
-
BridgeResult
|
|
48
|
-
|
|
49
|
-
const std::vector<JSVariant> *params,
|
|
50
|
-
std::vector<DumbHostObject> *results,
|
|
51
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas);
|
|
49
|
+
BridgeResult opsqlite_execute(std::string const &name, std::string const &query,
|
|
50
|
+
const std::vector<JSVariant> *params);
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
BridgeResult opsqlite_execute_host_objects(
|
|
53
|
+
std::string const &dbName, std::string const &query,
|
|
54
|
+
const std::vector<JSVariant> *params, std::vector<DumbHostObject> *results,
|
|
55
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas);
|
|
56
|
+
|
|
57
|
+
BatchResult opsqlite_execute_batch(std::string &name,
|
|
54
58
|
std::vector<BatchArguments> *commands);
|
|
55
59
|
|
|
56
60
|
BridgeResult opsqlite_execute_raw(std::string const &dbName,
|
|
@@ -79,7 +83,7 @@ void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
79
83
|
BridgeResult opsqlite_execute_prepared_statement(
|
|
80
84
|
std::string const &dbName, sqlite3_stmt *statement,
|
|
81
85
|
std::vector<DumbHostObject> *results,
|
|
82
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas);
|
|
86
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas);
|
|
83
87
|
|
|
84
88
|
BridgeResult opsqlite_load_extension(std::string const &db_name,
|
|
85
89
|
std::string &path,
|