@op-engineering/op-sqlite 7.4.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/build.gradle +8 -0
- package/cpp/DBHostObject.cpp +101 -106
- package/cpp/PreparedStatementHostObject.cpp +39 -14
- package/cpp/PreparedStatementHostObject.h +17 -4
- package/cpp/bindings.cpp +5 -5
- package/cpp/bridge.cpp +206 -85
- package/cpp/bridge.h +9 -7
- 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/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/package.json +44 -14
- 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/bindings.cpp
CHANGED
|
@@ -52,7 +52,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
|
52
52
|
_sqlite_vec_path = std::string(sqlite_vec_path);
|
|
53
53
|
_invoker = invoker;
|
|
54
54
|
|
|
55
|
-
auto open = HOSTFN("open"
|
|
55
|
+
auto open = HOSTFN("open") {
|
|
56
56
|
jsi::Object options = args[0].asObject(rt);
|
|
57
57
|
std::string name = options.getProperty(rt, "name").asString(rt).utf8(rt);
|
|
58
58
|
std::string path = std::string(_base_path);
|
|
@@ -91,7 +91,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
|
91
91
|
return jsi::Object::createFromHostObject(rt, db);
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
auto is_sqlcipher = HOSTFN("isSQLCipher"
|
|
94
|
+
auto is_sqlcipher = HOSTFN("isSQLCipher") {
|
|
95
95
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
96
96
|
return true;
|
|
97
97
|
#else
|
|
@@ -99,7 +99,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
|
99
99
|
#endif
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
auto is_libsql = HOSTFN("isLibsql"
|
|
102
|
+
auto is_libsql = HOSTFN("isLibsql") {
|
|
103
103
|
#ifdef OP_SQLITE_USE_LIBSQL
|
|
104
104
|
return true;
|
|
105
105
|
#else
|
|
@@ -108,7 +108,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
#ifdef OP_SQLITE_USE_LIBSQL
|
|
111
|
-
auto open_remote = HOSTFN("openRemote"
|
|
111
|
+
auto open_remote = HOSTFN("openRemote") {
|
|
112
112
|
jsi::Object options = args[0].asObject(rt);
|
|
113
113
|
std::string url = options.getProperty(rt, "url").asString(rt).utf8(rt);
|
|
114
114
|
std::string auth_token =
|
|
@@ -119,7 +119,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
|
|
|
119
119
|
return jsi::Object::createFromHostObject(rt, db);
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
-
auto open_sync = HOSTFN("openSync"
|
|
122
|
+
auto open_sync = HOSTFN("openSync") {
|
|
123
123
|
jsi::Object options = args[0].asObject(rt);
|
|
124
124
|
std::string name = options.getProperty(rt, "name").asString(rt).utf8(rt);
|
|
125
125
|
std::string path = std::string(_base_path);
|
package/cpp/bridge.cpp
CHANGED
|
@@ -76,8 +76,7 @@ BridgeResult opsqlite_open(std::string const &dbName,
|
|
|
76
76
|
dbMap[dbName] = db;
|
|
77
77
|
|
|
78
78
|
#ifdef OP_SQLITE_USE_SQLCIPHER
|
|
79
|
-
opsqlite_execute(dbName, "PRAGMA key = '" + encryptionKey + "'", nullptr
|
|
80
|
-
nullptr, nullptr);
|
|
79
|
+
opsqlite_execute(dbName, "PRAGMA key = '" + encryptionKey + "'", nullptr);
|
|
81
80
|
#endif
|
|
82
81
|
|
|
83
82
|
sqlite3_enable_load_extension(db, 1);
|
|
@@ -120,8 +119,7 @@ BridgeResult opsqlite_close(std::string const &dbName) {
|
|
|
120
119
|
sqlite3 *db = dbMap[dbName];
|
|
121
120
|
|
|
122
121
|
#ifdef OP_SQLITE_USE_CRSQLITE
|
|
123
|
-
opsqlite_execute(dbName, "select crsql_finalize();", nullptr
|
|
124
|
-
nullptr);
|
|
122
|
+
opsqlite_execute(dbName, "select crsql_finalize();", nullptr);
|
|
125
123
|
#endif
|
|
126
124
|
|
|
127
125
|
sqlite3_close_v2(db);
|
|
@@ -140,8 +138,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
140
138
|
std::string dbPath = opsqlite_get_db_path(databaseToAttach, docPath);
|
|
141
139
|
std::string statement = "ATTACH DATABASE '" + dbPath + "' AS " + alias;
|
|
142
140
|
|
|
143
|
-
BridgeResult result =
|
|
144
|
-
opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
|
|
141
|
+
BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
|
|
145
142
|
|
|
146
143
|
if (result.type == SQLiteError) {
|
|
147
144
|
return {
|
|
@@ -158,8 +155,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
158
155
|
BridgeResult opsqlite_detach(std::string const &mainDBName,
|
|
159
156
|
std::string const &alias) {
|
|
160
157
|
std::string statement = "DETACH DATABASE " + alias;
|
|
161
|
-
BridgeResult result =
|
|
162
|
-
opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
|
|
158
|
+
BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
|
|
163
159
|
if (result.type == SQLiteError) {
|
|
164
160
|
return BridgeResult{
|
|
165
161
|
.type = SQLiteError,
|
|
@@ -206,22 +202,22 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
206
202
|
int sqIndex = ii + 1;
|
|
207
203
|
JSVariant value = values->at(ii);
|
|
208
204
|
|
|
209
|
-
if (std::holds_alternative<bool>(value)
|
|
210
|
-
|
|
211
|
-
} else if (std::holds_alternative<int>(value)) {
|
|
205
|
+
if (std::holds_alternative<bool>(value) ||
|
|
206
|
+
std::holds_alternative<int>(value)) {
|
|
212
207
|
sqlite3_bind_int(statement, sqIndex, std::get<int>(value));
|
|
213
208
|
} else if (std::holds_alternative<long long>(value)) {
|
|
214
|
-
sqlite3_bind_double(statement, sqIndex,
|
|
209
|
+
sqlite3_bind_double(statement, sqIndex,
|
|
210
|
+
static_cast<double>(std::get<long long>(value)));
|
|
215
211
|
} else if (std::holds_alternative<double>(value)) {
|
|
216
212
|
sqlite3_bind_double(statement, sqIndex, std::get<double>(value));
|
|
217
213
|
} else if (std::holds_alternative<std::string>(value)) {
|
|
218
214
|
std::string str = std::get<std::string>(value);
|
|
219
|
-
sqlite3_bind_text(statement, sqIndex, str.c_str(),
|
|
220
|
-
SQLITE_TRANSIENT);
|
|
215
|
+
sqlite3_bind_text(statement, sqIndex, str.c_str(),
|
|
216
|
+
static_cast<int>(str.length()), SQLITE_TRANSIENT);
|
|
221
217
|
} else if (std::holds_alternative<ArrayBuffer>(value)) {
|
|
222
218
|
ArrayBuffer buffer = std::get<ArrayBuffer>(value);
|
|
223
|
-
sqlite3_bind_blob(statement, sqIndex, buffer.data.get(),
|
|
224
|
-
SQLITE_TRANSIENT);
|
|
219
|
+
sqlite3_bind_blob(statement, sqIndex, buffer.data.get(),
|
|
220
|
+
static_cast<int>(buffer.size), SQLITE_TRANSIENT);
|
|
225
221
|
} else {
|
|
226
222
|
sqlite3_bind_null(statement, sqIndex);
|
|
227
223
|
}
|
|
@@ -231,7 +227,7 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
231
227
|
BridgeResult opsqlite_execute_prepared_statement(
|
|
232
228
|
std::string const &dbName, sqlite3_stmt *statement,
|
|
233
229
|
std::vector<DumbHostObject> *results,
|
|
234
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas) {
|
|
230
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
|
|
235
231
|
|
|
236
232
|
check_db_open(dbName);
|
|
237
233
|
|
|
@@ -244,8 +240,6 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
244
240
|
|
|
245
241
|
int result = SQLITE_OK;
|
|
246
242
|
|
|
247
|
-
isConsuming = true;
|
|
248
|
-
|
|
249
243
|
int i, count, column_type;
|
|
250
244
|
std::string column_name, column_declared_type;
|
|
251
245
|
|
|
@@ -254,7 +248,7 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
254
248
|
|
|
255
249
|
switch (result) {
|
|
256
250
|
case SQLITE_ROW: {
|
|
257
|
-
if (results ==
|
|
251
|
+
if (results == nullptr) {
|
|
258
252
|
break;
|
|
259
253
|
}
|
|
260
254
|
|
|
@@ -273,13 +267,13 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
273
267
|
* only represent Integers up to 53 bits
|
|
274
268
|
*/
|
|
275
269
|
double column_value = sqlite3_column_double(statement, i);
|
|
276
|
-
row.values.
|
|
270
|
+
row.values.emplace_back(column_value);
|
|
277
271
|
break;
|
|
278
272
|
}
|
|
279
273
|
|
|
280
274
|
case SQLITE_FLOAT: {
|
|
281
275
|
double column_value = sqlite3_column_double(statement, i);
|
|
282
|
-
row.values.
|
|
276
|
+
row.values.emplace_back(column_value);
|
|
283
277
|
break;
|
|
284
278
|
}
|
|
285
279
|
|
|
@@ -288,20 +282,20 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
288
282
|
reinterpret_cast<const char *>(sqlite3_column_text(statement, i));
|
|
289
283
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
290
284
|
// Specify length too; in case string contains NULL in the middle
|
|
291
|
-
row.values.
|
|
285
|
+
row.values.emplace_back(std::string(column_value, byteLen));
|
|
292
286
|
break;
|
|
293
287
|
}
|
|
294
288
|
|
|
295
289
|
case SQLITE_BLOB: {
|
|
296
290
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
297
291
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
298
|
-
|
|
292
|
+
auto *data = new uint8_t[blob_size];
|
|
299
293
|
// You cannot share raw memory between native and JS
|
|
300
294
|
// always copy the data
|
|
301
295
|
memcpy(data, blob, blob_size);
|
|
302
|
-
row.values.
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
row.values.emplace_back(
|
|
297
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
298
|
+
.size = static_cast<size_t>(blob_size)});
|
|
305
299
|
break;
|
|
306
300
|
}
|
|
307
301
|
|
|
@@ -309,14 +303,16 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
309
303
|
// Intentionally left blank
|
|
310
304
|
|
|
311
305
|
default:
|
|
312
|
-
row.values.
|
|
306
|
+
row.values.emplace_back(nullptr);
|
|
313
307
|
break;
|
|
314
308
|
}
|
|
315
309
|
i++;
|
|
316
310
|
}
|
|
311
|
+
|
|
317
312
|
if (results != nullptr) {
|
|
318
313
|
results->push_back(row);
|
|
319
314
|
}
|
|
315
|
+
|
|
320
316
|
break;
|
|
321
317
|
}
|
|
322
318
|
|
|
@@ -329,10 +325,10 @@ BridgeResult opsqlite_execute_prepared_statement(
|
|
|
329
325
|
column_name = sqlite3_column_name(statement, i);
|
|
330
326
|
const char *type = sqlite3_column_decltype(statement, i);
|
|
331
327
|
auto metadata = SmartHostObject();
|
|
332
|
-
metadata.fields.
|
|
333
|
-
metadata.fields.
|
|
334
|
-
metadata.fields.
|
|
335
|
-
|
|
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);
|
|
336
332
|
|
|
337
333
|
metadatas->push_back(metadata);
|
|
338
334
|
i++;
|
|
@@ -374,7 +370,8 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
|
|
|
374
370
|
|
|
375
371
|
const char *queryStr = query.c_str();
|
|
376
372
|
|
|
377
|
-
int statementStatus =
|
|
373
|
+
int statementStatus =
|
|
374
|
+
sqlite3_prepare_v2(db, queryStr, -1, &statement, nullptr);
|
|
378
375
|
|
|
379
376
|
if (statementStatus == SQLITE_ERROR) {
|
|
380
377
|
const char *message = sqlite3_errmsg(db);
|
|
@@ -385,12 +382,144 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
|
|
|
385
382
|
return statement;
|
|
386
383
|
}
|
|
387
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
|
+
|
|
388
518
|
/// Base execution function, returns HostObjects to the JS environment
|
|
389
|
-
BridgeResult
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
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) {
|
|
394
523
|
|
|
395
524
|
check_db_open(dbName);
|
|
396
525
|
|
|
@@ -423,16 +552,14 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
423
552
|
|
|
424
553
|
// The statement did not fail to parse but there is nothing to do, just
|
|
425
554
|
// skip to the end
|
|
426
|
-
if (statement ==
|
|
555
|
+
if (statement == nullptr) {
|
|
427
556
|
continue;
|
|
428
557
|
}
|
|
429
558
|
|
|
430
|
-
if (params != nullptr && params->
|
|
559
|
+
if (params != nullptr && !params->empty()) {
|
|
431
560
|
opsqlite_bind_statement(statement, params);
|
|
432
561
|
}
|
|
433
562
|
|
|
434
|
-
isConsuming = true;
|
|
435
|
-
|
|
436
563
|
int i, count, column_type;
|
|
437
564
|
std::string column_name, column_declared_type;
|
|
438
565
|
|
|
@@ -441,7 +568,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
441
568
|
|
|
442
569
|
switch (result) {
|
|
443
570
|
case SQLITE_ROW: {
|
|
444
|
-
if (results ==
|
|
571
|
+
if (results == nullptr) {
|
|
445
572
|
break;
|
|
446
573
|
}
|
|
447
574
|
|
|
@@ -460,13 +587,13 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
460
587
|
* only represent Integers up to 53 bits
|
|
461
588
|
*/
|
|
462
589
|
double column_value = sqlite3_column_double(statement, i);
|
|
463
|
-
row.values.
|
|
590
|
+
row.values.emplace_back(column_value);
|
|
464
591
|
break;
|
|
465
592
|
}
|
|
466
593
|
|
|
467
594
|
case SQLITE_FLOAT: {
|
|
468
595
|
double column_value = sqlite3_column_double(statement, i);
|
|
469
|
-
row.values.
|
|
596
|
+
row.values.emplace_back(column_value);
|
|
470
597
|
break;
|
|
471
598
|
}
|
|
472
599
|
|
|
@@ -475,20 +602,20 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
475
602
|
sqlite3_column_text(statement, i));
|
|
476
603
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
477
604
|
// Specify length too; in case string contains NULL in the middle
|
|
478
|
-
row.values.
|
|
605
|
+
row.values.emplace_back(std::string(column_value, byteLen));
|
|
479
606
|
break;
|
|
480
607
|
}
|
|
481
608
|
|
|
482
609
|
case SQLITE_BLOB: {
|
|
483
610
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
484
611
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
485
|
-
|
|
612
|
+
auto *data = new uint8_t[blob_size];
|
|
486
613
|
// You cannot share raw memory between native and JS
|
|
487
614
|
// always copy the data
|
|
488
615
|
memcpy(data, blob, blob_size);
|
|
489
|
-
row.values.
|
|
490
|
-
|
|
491
|
-
|
|
616
|
+
row.values.emplace_back(
|
|
617
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
618
|
+
.size = static_cast<size_t>(blob_size)});
|
|
492
619
|
break;
|
|
493
620
|
}
|
|
494
621
|
|
|
@@ -496,7 +623,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
496
623
|
// Intentionally left blank
|
|
497
624
|
|
|
498
625
|
default:
|
|
499
|
-
row.values.
|
|
626
|
+
row.values.emplace_back(nullptr);
|
|
500
627
|
break;
|
|
501
628
|
}
|
|
502
629
|
i++;
|
|
@@ -516,10 +643,10 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
516
643
|
column_name = sqlite3_column_name(statement, i);
|
|
517
644
|
const char *type = sqlite3_column_decltype(statement, i);
|
|
518
645
|
auto metadata = SmartHostObject();
|
|
519
|
-
metadata.fields.
|
|
520
|
-
metadata.fields.
|
|
521
|
-
metadata.fields.
|
|
522
|
-
|
|
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);
|
|
523
650
|
|
|
524
651
|
metadatas->push_back(metadata);
|
|
525
652
|
i++;
|
|
@@ -536,8 +663,8 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
|
|
|
536
663
|
}
|
|
537
664
|
|
|
538
665
|
sqlite3_finalize(statement);
|
|
539
|
-
} while (remainingStatement !=
|
|
540
|
-
!isFailed);
|
|
666
|
+
} while (remainingStatement != nullptr &&
|
|
667
|
+
strcmp(remainingStatement, "") != 0 && !isFailed);
|
|
541
668
|
|
|
542
669
|
if (isFailed) {
|
|
543
670
|
|
|
@@ -594,16 +721,14 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
594
721
|
|
|
595
722
|
// The statement did not fail to parse but there is nothing to do, just
|
|
596
723
|
// skip to the end
|
|
597
|
-
if (statement ==
|
|
724
|
+
if (statement == nullptr) {
|
|
598
725
|
continue;
|
|
599
726
|
}
|
|
600
727
|
|
|
601
|
-
if (params != nullptr && params->
|
|
728
|
+
if (params != nullptr && !params->empty()) {
|
|
602
729
|
opsqlite_bind_statement(statement, params);
|
|
603
730
|
}
|
|
604
731
|
|
|
605
|
-
isConsuming = true;
|
|
606
|
-
|
|
607
732
|
int i, count, column_type;
|
|
608
733
|
std::string column_name, column_declared_type;
|
|
609
734
|
|
|
@@ -632,13 +757,13 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
632
757
|
* only represent Integers up to 53 bits
|
|
633
758
|
*/
|
|
634
759
|
double column_value = sqlite3_column_double(statement, i);
|
|
635
|
-
row.
|
|
760
|
+
row.emplace_back(column_value);
|
|
636
761
|
break;
|
|
637
762
|
}
|
|
638
763
|
|
|
639
764
|
case SQLITE_FLOAT: {
|
|
640
765
|
double column_value = sqlite3_column_double(statement, i);
|
|
641
|
-
row.
|
|
766
|
+
row.emplace_back(column_value);
|
|
642
767
|
break;
|
|
643
768
|
}
|
|
644
769
|
|
|
@@ -647,27 +772,25 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
647
772
|
sqlite3_column_text(statement, i));
|
|
648
773
|
int byteLen = sqlite3_column_bytes(statement, i);
|
|
649
774
|
// Specify length too; in case string contains NULL in the middle
|
|
650
|
-
row.
|
|
775
|
+
row.emplace_back(std::string(column_value, byteLen));
|
|
651
776
|
break;
|
|
652
777
|
}
|
|
653
778
|
|
|
654
779
|
case SQLITE_BLOB: {
|
|
655
780
|
int blob_size = sqlite3_column_bytes(statement, i);
|
|
656
781
|
const void *blob = sqlite3_column_blob(statement, i);
|
|
657
|
-
|
|
782
|
+
auto *data = new uint8_t[blob_size];
|
|
658
783
|
memcpy(data, blob, blob_size);
|
|
659
|
-
row.
|
|
660
|
-
|
|
661
|
-
|
|
784
|
+
row.emplace_back(
|
|
785
|
+
ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
|
|
786
|
+
.size = static_cast<size_t>(blob_size)});
|
|
662
787
|
break;
|
|
663
788
|
}
|
|
664
789
|
|
|
665
790
|
case SQLITE_NULL:
|
|
666
|
-
|
|
667
|
-
break;
|
|
668
|
-
|
|
791
|
+
// intentional fallthrough
|
|
669
792
|
default:
|
|
670
|
-
row.
|
|
793
|
+
row.emplace_back(nullptr);
|
|
671
794
|
break;
|
|
672
795
|
}
|
|
673
796
|
i++;
|
|
@@ -690,8 +813,8 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
|
|
|
690
813
|
}
|
|
691
814
|
|
|
692
815
|
sqlite3_finalize(statement);
|
|
693
|
-
} while (remainingStatement !=
|
|
694
|
-
!isFailed);
|
|
816
|
+
} while (remainingStatement != nullptr &&
|
|
817
|
+
strcmp(remainingStatement, "") != 0 && !isFailed);
|
|
695
818
|
|
|
696
819
|
if (isFailed) {
|
|
697
820
|
|
|
@@ -773,7 +896,7 @@ BridgeResult opsqlite_deregister_update_hook(std::string const &dbName) {
|
|
|
773
896
|
sqlite3 *db = dbMap[dbName];
|
|
774
897
|
updateCallbackMap.erase(dbName);
|
|
775
898
|
|
|
776
|
-
sqlite3_update_hook(db,
|
|
899
|
+
sqlite3_update_hook(db, nullptr, nullptr);
|
|
777
900
|
|
|
778
901
|
return {SQLiteOk};
|
|
779
902
|
}
|
|
@@ -811,7 +934,7 @@ BridgeResult opsqlite_deregister_commit_hook(std::string const &dbName) {
|
|
|
811
934
|
|
|
812
935
|
sqlite3 *db = dbMap[dbName];
|
|
813
936
|
commitCallbackMap.erase(dbName);
|
|
814
|
-
sqlite3_commit_hook(db,
|
|
937
|
+
sqlite3_commit_hook(db, nullptr, nullptr);
|
|
815
938
|
|
|
816
939
|
return {SQLiteOk};
|
|
817
940
|
}
|
|
@@ -848,7 +971,7 @@ BridgeResult opsqlite_deregister_rollback_hook(std::string const &dbName) {
|
|
|
848
971
|
sqlite3 *db = dbMap[dbName];
|
|
849
972
|
rollbackCallbackMap.erase(dbName);
|
|
850
973
|
|
|
851
|
-
sqlite3_rollback_hook(db,
|
|
974
|
+
sqlite3_rollback_hook(db, nullptr, nullptr);
|
|
852
975
|
|
|
853
976
|
return {SQLiteOk};
|
|
854
977
|
}
|
|
@@ -884,7 +1007,7 @@ BridgeResult opsqlite_load_extension(std::string const &db_name,
|
|
|
884
1007
|
#endif
|
|
885
1008
|
}
|
|
886
1009
|
|
|
887
|
-
BatchResult opsqlite_execute_batch(std::string
|
|
1010
|
+
BatchResult opsqlite_execute_batch(std::string &name,
|
|
888
1011
|
std::vector<BatchArguments> *commands) {
|
|
889
1012
|
size_t commandCount = commands->size();
|
|
890
1013
|
if (commandCount <= 0) {
|
|
@@ -896,16 +1019,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
|
|
|
896
1019
|
|
|
897
1020
|
try {
|
|
898
1021
|
int affectedRows = 0;
|
|
899
|
-
opsqlite_execute(
|
|
900
|
-
nullptr);
|
|
1022
|
+
opsqlite_execute(name, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
|
|
901
1023
|
for (int i = 0; i < commandCount; i++) {
|
|
902
1024
|
auto command = commands->at(i);
|
|
903
1025
|
// We do not provide a datastructure to receive query data because we
|
|
904
1026
|
// don't need/want to handle this results in a batch execution
|
|
905
|
-
auto result = opsqlite_execute(
|
|
906
|
-
nullptr, nullptr);
|
|
1027
|
+
auto result = opsqlite_execute(name, command.sql, command.params.get());
|
|
907
1028
|
if (result.type == SQLiteError) {
|
|
908
|
-
opsqlite_execute(
|
|
1029
|
+
opsqlite_execute(name, "ROLLBACK", nullptr);
|
|
909
1030
|
return BatchResult{
|
|
910
1031
|
.type = SQLiteError,
|
|
911
1032
|
.message = result.message,
|
|
@@ -914,14 +1035,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
|
|
|
914
1035
|
affectedRows += result.affectedRows;
|
|
915
1036
|
}
|
|
916
1037
|
}
|
|
917
|
-
opsqlite_execute(
|
|
1038
|
+
opsqlite_execute(name, "COMMIT", nullptr);
|
|
918
1039
|
return BatchResult{
|
|
919
1040
|
.type = SQLiteOk,
|
|
920
1041
|
.affectedRows = affectedRows,
|
|
921
1042
|
.commands = static_cast<int>(commandCount),
|
|
922
1043
|
};
|
|
923
1044
|
} catch (std::exception &exc) {
|
|
924
|
-
opsqlite_execute(
|
|
1045
|
+
opsqlite_execute(name, "ROLLBACK", nullptr);
|
|
925
1046
|
return BatchResult{
|
|
926
1047
|
.type = SQLiteError,
|
|
927
1048
|
.message = exc.what(),
|
package/cpp/bridge.h
CHANGED
|
@@ -46,13 +46,15 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
|
|
|
46
46
|
BridgeResult opsqlite_detach(std::string const &mainDBName,
|
|
47
47
|
std::string const &alias);
|
|
48
48
|
|
|
49
|
-
BridgeResult
|
|
50
|
-
|
|
51
|
-
const std::vector<JSVariant> *params,
|
|
52
|
-
std::vector<DumbHostObject> *results,
|
|
53
|
-
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);
|
|
54
51
|
|
|
55
|
-
|
|
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,
|
|
56
58
|
std::vector<BatchArguments> *commands);
|
|
57
59
|
|
|
58
60
|
BridgeResult opsqlite_execute_raw(std::string const &dbName,
|
|
@@ -81,7 +83,7 @@ void opsqlite_bind_statement(sqlite3_stmt *statement,
|
|
|
81
83
|
BridgeResult opsqlite_execute_prepared_statement(
|
|
82
84
|
std::string const &dbName, sqlite3_stmt *statement,
|
|
83
85
|
std::vector<DumbHostObject> *results,
|
|
84
|
-
std::shared_ptr<std::vector<SmartHostObject>> metadatas);
|
|
86
|
+
std::shared_ptr<std::vector<SmartHostObject>> &metadatas);
|
|
85
87
|
|
|
86
88
|
BridgeResult opsqlite_load_extension(std::string const &db_name,
|
|
87
89
|
std::string &path,
|