@op-engineering/op-sqlite 7.4.3 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cpp/bridge.cpp CHANGED
@@ -24,7 +24,8 @@ std::unordered_map<std::string, RollbackCallback> rollbackCallbackMap =
24
24
 
25
25
  inline void check_db_open(std::string const &db_name) {
26
26
  if (dbMap.count(db_name) == 0) {
27
- throw std::runtime_error("[OP-SQLite] DB is not open");
27
+ throw std::runtime_error("[OP-SQLite] Database: " + db_name +
28
+ " is not open");
28
29
  }
29
30
  }
30
31
 
@@ -49,18 +50,23 @@ std::string opsqlite_get_db_path(std::string const &db_name,
49
50
  }
50
51
 
51
52
  #ifdef OP_SQLITE_USE_SQLCIPHER
52
- BridgeResult opsqlite_open(std::string const &dbName,
53
+ BridgeResult opsqlite_open(std::string const &name,
53
54
  std::string const &last_path,
54
55
  std::string const &crsqlite_path,
55
56
  std::string const &sqlite_vec_path,
56
57
  std::string const &encryptionKey) {
57
58
  #else
58
- BridgeResult opsqlite_open(std::string const &dbName,
59
+ BridgeResult opsqlite_open(std::string const &name,
59
60
  std::string const &last_path,
60
61
  std::string const &crsqlite_path,
61
62
  std::string const &sqlite_vec_path) {
63
+
64
+ if (dbMap.count(name) != 0) {
65
+ throw std::runtime_error(
66
+ "You can only have one JS connection per database");
67
+ }
62
68
  #endif
63
- std::string dbPath = opsqlite_get_db_path(dbName, last_path);
69
+ std::string dbPath = opsqlite_get_db_path(name, last_path);
64
70
 
65
71
  int sqlOpenFlags =
66
72
  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
@@ -73,11 +79,10 @@ BridgeResult opsqlite_open(std::string const &dbName,
73
79
  return {.type = SQLiteError, .message = sqlite3_errmsg(db)};
74
80
  }
75
81
 
76
- dbMap[dbName] = db;
82
+ dbMap[name] = db;
77
83
 
78
84
  #ifdef OP_SQLITE_USE_SQLCIPHER
79
- opsqlite_execute(dbName, "PRAGMA key = '" + encryptionKey + "'", nullptr,
80
- nullptr, nullptr);
85
+ opsqlite_execute(name, "PRAGMA key = '" + encryptionKey + "'", nullptr);
81
86
  #endif
82
87
 
83
88
  sqlite3_enable_load_extension(db, 1);
@@ -92,8 +97,6 @@ BridgeResult opsqlite_open(std::string const &dbName,
92
97
 
93
98
  if (errMsg != nullptr) {
94
99
  return {.type = SQLiteError, .message = errMsg};
95
- } else {
96
- LOGI("Loaded CRSQlite successfully");
97
100
  }
98
101
  #endif
99
102
 
@@ -104,8 +107,6 @@ BridgeResult opsqlite_open(std::string const &dbName,
104
107
 
105
108
  if (errMsg != nullptr) {
106
109
  return {.type = SQLiteError, .message = errMsg};
107
- } else {
108
- LOGI("Loaded sqlite-vec successfully");
109
110
  }
110
111
 
111
112
  #endif
@@ -113,20 +114,19 @@ BridgeResult opsqlite_open(std::string const &dbName,
113
114
  return {.type = SQLiteOk, .affectedRows = 0};
114
115
  }
115
116
 
116
- BridgeResult opsqlite_close(std::string const &dbName) {
117
+ BridgeResult opsqlite_close(std::string const &name) {
117
118
 
118
- check_db_open(dbName);
119
+ check_db_open(name);
119
120
 
120
- sqlite3 *db = dbMap[dbName];
121
+ sqlite3 *db = dbMap[name];
121
122
 
122
123
  #ifdef OP_SQLITE_USE_CRSQLITE
123
- opsqlite_execute(dbName, "select crsql_finalize();", nullptr, nullptr,
124
- nullptr);
124
+ opsqlite_execute(name, "select crsql_finalize();", nullptr);
125
125
  #endif
126
126
 
127
127
  sqlite3_close_v2(db);
128
128
 
129
- dbMap.erase(dbName);
129
+ dbMap.erase(name);
130
130
 
131
131
  return BridgeResult{
132
132
  .type = SQLiteOk,
@@ -140,8 +140,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
140
140
  std::string dbPath = opsqlite_get_db_path(databaseToAttach, docPath);
141
141
  std::string statement = "ATTACH DATABASE '" + dbPath + "' AS " + alias;
142
142
 
143
- BridgeResult result =
144
- opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
143
+ BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
145
144
 
146
145
  if (result.type == SQLiteError) {
147
146
  return {
@@ -158,8 +157,7 @@ BridgeResult opsqlite_attach(std::string const &mainDBName,
158
157
  BridgeResult opsqlite_detach(std::string const &mainDBName,
159
158
  std::string const &alias) {
160
159
  std::string statement = "DETACH DATABASE " + alias;
161
- BridgeResult result =
162
- opsqlite_execute(mainDBName, statement, nullptr, nullptr, nullptr);
160
+ BridgeResult result = opsqlite_execute(mainDBName, statement, nullptr);
163
161
  if (result.type == SQLiteError) {
164
162
  return BridgeResult{
165
163
  .type = SQLiteError,
@@ -206,22 +204,22 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
206
204
  int sqIndex = ii + 1;
207
205
  JSVariant value = values->at(ii);
208
206
 
209
- if (std::holds_alternative<bool>(value)) {
210
- sqlite3_bind_int(statement, sqIndex, std::get<bool>(value));
211
- } else if (std::holds_alternative<int>(value)) {
207
+ if (std::holds_alternative<bool>(value) ||
208
+ std::holds_alternative<int>(value)) {
212
209
  sqlite3_bind_int(statement, sqIndex, std::get<int>(value));
213
210
  } else if (std::holds_alternative<long long>(value)) {
214
- sqlite3_bind_double(statement, sqIndex, std::get<long long>(value));
211
+ sqlite3_bind_double(statement, sqIndex,
212
+ static_cast<double>(std::get<long long>(value)));
215
213
  } else if (std::holds_alternative<double>(value)) {
216
214
  sqlite3_bind_double(statement, sqIndex, std::get<double>(value));
217
215
  } else if (std::holds_alternative<std::string>(value)) {
218
216
  std::string str = std::get<std::string>(value);
219
- sqlite3_bind_text(statement, sqIndex, str.c_str(), str.length(),
220
- SQLITE_TRANSIENT);
217
+ sqlite3_bind_text(statement, sqIndex, str.c_str(),
218
+ static_cast<int>(str.length()), SQLITE_TRANSIENT);
221
219
  } else if (std::holds_alternative<ArrayBuffer>(value)) {
222
220
  ArrayBuffer buffer = std::get<ArrayBuffer>(value);
223
- sqlite3_bind_blob(statement, sqIndex, buffer.data.get(), buffer.size,
224
- SQLITE_TRANSIENT);
221
+ sqlite3_bind_blob(statement, sqIndex, buffer.data.get(),
222
+ static_cast<int>(buffer.size), SQLITE_TRANSIENT);
225
223
  } else {
226
224
  sqlite3_bind_null(statement, sqIndex);
227
225
  }
@@ -231,7 +229,7 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
231
229
  BridgeResult opsqlite_execute_prepared_statement(
232
230
  std::string const &dbName, sqlite3_stmt *statement,
233
231
  std::vector<DumbHostObject> *results,
234
- std::shared_ptr<std::vector<SmartHostObject>> metadatas) {
232
+ std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
235
233
 
236
234
  check_db_open(dbName);
237
235
 
@@ -244,8 +242,6 @@ BridgeResult opsqlite_execute_prepared_statement(
244
242
 
245
243
  int result = SQLITE_OK;
246
244
 
247
- isConsuming = true;
248
-
249
245
  int i, count, column_type;
250
246
  std::string column_name, column_declared_type;
251
247
 
@@ -254,7 +250,7 @@ BridgeResult opsqlite_execute_prepared_statement(
254
250
 
255
251
  switch (result) {
256
252
  case SQLITE_ROW: {
257
- if (results == NULL) {
253
+ if (results == nullptr) {
258
254
  break;
259
255
  }
260
256
 
@@ -273,13 +269,13 @@ BridgeResult opsqlite_execute_prepared_statement(
273
269
  * only represent Integers up to 53 bits
274
270
  */
275
271
  double column_value = sqlite3_column_double(statement, i);
276
- row.values.push_back(JSVariant(column_value));
272
+ row.values.emplace_back(column_value);
277
273
  break;
278
274
  }
279
275
 
280
276
  case SQLITE_FLOAT: {
281
277
  double column_value = sqlite3_column_double(statement, i);
282
- row.values.push_back(JSVariant(column_value));
278
+ row.values.emplace_back(column_value);
283
279
  break;
284
280
  }
285
281
 
@@ -288,20 +284,20 @@ BridgeResult opsqlite_execute_prepared_statement(
288
284
  reinterpret_cast<const char *>(sqlite3_column_text(statement, i));
289
285
  int byteLen = sqlite3_column_bytes(statement, i);
290
286
  // Specify length too; in case string contains NULL in the middle
291
- row.values.push_back(JSVariant(std::string(column_value, byteLen)));
287
+ row.values.emplace_back(std::string(column_value, byteLen));
292
288
  break;
293
289
  }
294
290
 
295
291
  case SQLITE_BLOB: {
296
292
  int blob_size = sqlite3_column_bytes(statement, i);
297
293
  const void *blob = sqlite3_column_blob(statement, i);
298
- uint8_t *data = new uint8_t[blob_size];
294
+ auto *data = new uint8_t[blob_size];
299
295
  // You cannot share raw memory between native and JS
300
296
  // always copy the data
301
297
  memcpy(data, blob, blob_size);
302
- row.values.push_back(
303
- JSVariant(ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
304
- .size = static_cast<size_t>(blob_size)}));
298
+ row.values.emplace_back(
299
+ ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
300
+ .size = static_cast<size_t>(blob_size)});
305
301
  break;
306
302
  }
307
303
 
@@ -309,14 +305,16 @@ BridgeResult opsqlite_execute_prepared_statement(
309
305
  // Intentionally left blank
310
306
 
311
307
  default:
312
- row.values.push_back(JSVariant(nullptr));
308
+ row.values.emplace_back(nullptr);
313
309
  break;
314
310
  }
315
311
  i++;
316
312
  }
313
+
317
314
  if (results != nullptr) {
318
315
  results->push_back(row);
319
316
  }
317
+
320
318
  break;
321
319
  }
322
320
 
@@ -329,10 +327,10 @@ BridgeResult opsqlite_execute_prepared_statement(
329
327
  column_name = sqlite3_column_name(statement, i);
330
328
  const char *type = sqlite3_column_decltype(statement, i);
331
329
  auto metadata = SmartHostObject();
332
- metadata.fields.push_back(std::make_pair("name", column_name));
333
- metadata.fields.push_back(std::make_pair("index", i));
334
- metadata.fields.push_back(
335
- std::make_pair("type", type == NULL ? "UNKNOWN" : type));
330
+ metadata.fields.emplace_back("name", column_name);
331
+ metadata.fields.emplace_back("index", i);
332
+ metadata.fields.emplace_back("type",
333
+ type == nullptr ? "UNKNOWN" : type);
336
334
 
337
335
  metadatas->push_back(metadata);
338
336
  i++;
@@ -374,7 +372,8 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
374
372
 
375
373
  const char *queryStr = query.c_str();
376
374
 
377
- int statementStatus = sqlite3_prepare_v2(db, queryStr, -1, &statement, NULL);
375
+ int statementStatus =
376
+ sqlite3_prepare_v2(db, queryStr, -1, &statement, nullptr);
378
377
 
379
378
  if (statementStatus == SQLITE_ERROR) {
380
379
  const char *message = sqlite3_errmsg(db);
@@ -385,12 +384,144 @@ sqlite3_stmt *opsqlite_prepare_statement(std::string const &dbName,
385
384
  return statement;
386
385
  }
387
386
 
387
+ BridgeResult opsqlite_execute(std::string const &name, std::string const &query,
388
+ const std::vector<JSVariant> *params) {
389
+ check_db_open(name);
390
+
391
+ sqlite3 *db = dbMap[name];
392
+
393
+ sqlite3_stmt *statement;
394
+ const char *errorMessage;
395
+ const char *remainingStatement = nullptr;
396
+
397
+ bool isFailed = false;
398
+ int step_result, current_column, column_count, column_type;
399
+ std::string column_name, column_declared_type;
400
+ std::vector<std::string> column_names;
401
+ std::vector<std::vector<JSVariant>> rows;
402
+ std::vector<JSVariant> row;
403
+
404
+ do {
405
+ const char *queryStr =
406
+ remainingStatement == nullptr ? query.c_str() : remainingStatement;
407
+
408
+ int statementStatus =
409
+ sqlite3_prepare_v2(db, queryStr, -1, &statement, &remainingStatement);
410
+
411
+ if (statementStatus != SQLITE_OK) {
412
+ errorMessage = sqlite3_errmsg(db);
413
+ return {.type = SQLiteError,
414
+ .message =
415
+ "[op-sqlite] SQL prepare error: " + std::string(errorMessage),
416
+ .affectedRows = 0};
417
+ }
418
+
419
+ if (params != nullptr && !params->empty()) {
420
+ opsqlite_bind_statement(statement, params);
421
+ }
422
+
423
+ column_count = sqlite3_column_count(statement);
424
+ bool is_consuming = true;
425
+ // Do a first pass to get the column names
426
+ for (int i = 0; i < column_count; i++) {
427
+ column_name = sqlite3_column_name(statement, i);
428
+ column_names.push_back(column_name);
429
+ }
430
+
431
+ double double_value;
432
+ const char *string_value;
433
+ while (is_consuming) {
434
+ step_result = sqlite3_step(statement);
435
+
436
+ switch (step_result) {
437
+ case SQLITE_ROW:
438
+ current_column = 0;
439
+ row = std::vector<JSVariant>();
440
+ column_count = sqlite3_column_count(statement);
441
+
442
+ while (current_column < column_count) {
443
+ column_type = sqlite3_column_type(statement, current_column);
444
+
445
+ switch (column_type) {
446
+
447
+ case SQLITE_INTEGER:
448
+ // intentional fallthrough
449
+ case SQLITE_FLOAT: {
450
+ double_value = sqlite3_column_double(statement, current_column);
451
+ row.emplace_back(double_value);
452
+ break;
453
+ }
454
+
455
+ case SQLITE_TEXT: {
456
+ string_value = reinterpret_cast<const char *>(
457
+ sqlite3_column_text(statement, current_column));
458
+ int byteLen = sqlite3_column_bytes(statement, current_column);
459
+ // Specify length too; in case string contains NULL in the middle
460
+ row.emplace_back(std::string(string_value, byteLen));
461
+ break;
462
+ }
463
+
464
+ case SQLITE_BLOB: {
465
+ int blob_size = sqlite3_column_bytes(statement, current_column);
466
+ const void *blob = sqlite3_column_blob(statement, current_column);
467
+ auto *data = new uint8_t[blob_size];
468
+ memcpy(data, blob, blob_size);
469
+ row.emplace_back(
470
+ ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
471
+ .size = static_cast<size_t>(blob_size)});
472
+ break;
473
+ }
474
+
475
+ case SQLITE_NULL:
476
+ // Intentionally left blank to switch to default case
477
+ default:
478
+ row.emplace_back(nullptr);
479
+ break;
480
+ }
481
+
482
+ current_column++;
483
+ }
484
+
485
+ rows.push_back(row);
486
+ break;
487
+
488
+ case SQLITE_DONE:
489
+ is_consuming = false;
490
+ break;
491
+
492
+ default:
493
+ isFailed = true;
494
+ is_consuming = false;
495
+ }
496
+ }
497
+
498
+ sqlite3_finalize(statement);
499
+ } while (remainingStatement != nullptr &&
500
+ strcmp(remainingStatement, "") != 0 && !isFailed);
501
+
502
+ if (isFailed) {
503
+ const char *message = sqlite3_errmsg(db);
504
+ return {.type = SQLiteError,
505
+ .message =
506
+ "[op-sqlite] SQL execution error: " + std::string(message),
507
+ .affectedRows = 0,
508
+ .insertId = 0};
509
+ }
510
+
511
+ int changedRowCount = sqlite3_changes(db);
512
+ long long latestInsertRowId = sqlite3_last_insert_rowid(db);
513
+ return {.type = SQLiteOk,
514
+ .affectedRows = changedRowCount,
515
+ .insertId = static_cast<double>(latestInsertRowId),
516
+ .rows = std::move(rows),
517
+ .column_names = std::move(column_names)};
518
+ }
519
+
388
520
  /// Base execution function, returns HostObjects to the JS environment
389
- BridgeResult
390
- opsqlite_execute(std::string const &dbName, std::string const &query,
391
- const std::vector<JSVariant> *params,
392
- std::vector<DumbHostObject> *results,
393
- std::shared_ptr<std::vector<SmartHostObject>> metadatas) {
521
+ BridgeResult opsqlite_execute_host_objects(
522
+ std::string const &dbName, std::string const &query,
523
+ const std::vector<JSVariant> *params, std::vector<DumbHostObject> *results,
524
+ std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
394
525
 
395
526
  check_db_open(dbName);
396
527
 
@@ -423,16 +554,14 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
423
554
 
424
555
  // The statement did not fail to parse but there is nothing to do, just
425
556
  // skip to the end
426
- if (statement == NULL) {
557
+ if (statement == nullptr) {
427
558
  continue;
428
559
  }
429
560
 
430
- if (params != nullptr && params->size() > 0) {
561
+ if (params != nullptr && !params->empty()) {
431
562
  opsqlite_bind_statement(statement, params);
432
563
  }
433
564
 
434
- isConsuming = true;
435
-
436
565
  int i, count, column_type;
437
566
  std::string column_name, column_declared_type;
438
567
 
@@ -441,7 +570,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
441
570
 
442
571
  switch (result) {
443
572
  case SQLITE_ROW: {
444
- if (results == NULL) {
573
+ if (results == nullptr) {
445
574
  break;
446
575
  }
447
576
 
@@ -460,13 +589,13 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
460
589
  * only represent Integers up to 53 bits
461
590
  */
462
591
  double column_value = sqlite3_column_double(statement, i);
463
- row.values.push_back(JSVariant(column_value));
592
+ row.values.emplace_back(column_value);
464
593
  break;
465
594
  }
466
595
 
467
596
  case SQLITE_FLOAT: {
468
597
  double column_value = sqlite3_column_double(statement, i);
469
- row.values.push_back(JSVariant(column_value));
598
+ row.values.emplace_back(column_value);
470
599
  break;
471
600
  }
472
601
 
@@ -475,20 +604,20 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
475
604
  sqlite3_column_text(statement, i));
476
605
  int byteLen = sqlite3_column_bytes(statement, i);
477
606
  // Specify length too; in case string contains NULL in the middle
478
- row.values.push_back(JSVariant(std::string(column_value, byteLen)));
607
+ row.values.emplace_back(std::string(column_value, byteLen));
479
608
  break;
480
609
  }
481
610
 
482
611
  case SQLITE_BLOB: {
483
612
  int blob_size = sqlite3_column_bytes(statement, i);
484
613
  const void *blob = sqlite3_column_blob(statement, i);
485
- uint8_t *data = new uint8_t[blob_size];
614
+ auto *data = new uint8_t[blob_size];
486
615
  // You cannot share raw memory between native and JS
487
616
  // always copy the data
488
617
  memcpy(data, blob, blob_size);
489
- row.values.push_back(
490
- JSVariant(ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
491
- .size = static_cast<size_t>(blob_size)}));
618
+ row.values.emplace_back(
619
+ ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
620
+ .size = static_cast<size_t>(blob_size)});
492
621
  break;
493
622
  }
494
623
 
@@ -496,7 +625,7 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
496
625
  // Intentionally left blank
497
626
 
498
627
  default:
499
- row.values.push_back(JSVariant(nullptr));
628
+ row.values.emplace_back(nullptr);
500
629
  break;
501
630
  }
502
631
  i++;
@@ -516,10 +645,10 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
516
645
  column_name = sqlite3_column_name(statement, i);
517
646
  const char *type = sqlite3_column_decltype(statement, i);
518
647
  auto metadata = SmartHostObject();
519
- metadata.fields.push_back(std::make_pair("name", column_name));
520
- metadata.fields.push_back(std::make_pair("index", i));
521
- metadata.fields.push_back(
522
- std::make_pair("type", type == NULL ? "UNKNOWN" : type));
648
+ metadata.fields.emplace_back("name", column_name);
649
+ metadata.fields.emplace_back("index", i);
650
+ metadata.fields.emplace_back("type",
651
+ type == nullptr ? "UNKNOWN" : type);
523
652
 
524
653
  metadatas->push_back(metadata);
525
654
  i++;
@@ -536,8 +665,8 @@ opsqlite_execute(std::string const &dbName, std::string const &query,
536
665
  }
537
666
 
538
667
  sqlite3_finalize(statement);
539
- } while (remainingStatement != NULL && strcmp(remainingStatement, "") != 0 &&
540
- !isFailed);
668
+ } while (remainingStatement != nullptr &&
669
+ strcmp(remainingStatement, "") != 0 && !isFailed);
541
670
 
542
671
  if (isFailed) {
543
672
 
@@ -594,16 +723,14 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
594
723
 
595
724
  // The statement did not fail to parse but there is nothing to do, just
596
725
  // skip to the end
597
- if (statement == NULL) {
726
+ if (statement == nullptr) {
598
727
  continue;
599
728
  }
600
729
 
601
- if (params != nullptr && params->size() > 0) {
730
+ if (params != nullptr && !params->empty()) {
602
731
  opsqlite_bind_statement(statement, params);
603
732
  }
604
733
 
605
- isConsuming = true;
606
-
607
734
  int i, count, column_type;
608
735
  std::string column_name, column_declared_type;
609
736
 
@@ -632,13 +759,13 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
632
759
  * only represent Integers up to 53 bits
633
760
  */
634
761
  double column_value = sqlite3_column_double(statement, i);
635
- row.push_back(JSVariant(column_value));
762
+ row.emplace_back(column_value);
636
763
  break;
637
764
  }
638
765
 
639
766
  case SQLITE_FLOAT: {
640
767
  double column_value = sqlite3_column_double(statement, i);
641
- row.push_back(JSVariant(column_value));
768
+ row.emplace_back(column_value);
642
769
  break;
643
770
  }
644
771
 
@@ -647,27 +774,25 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
647
774
  sqlite3_column_text(statement, i));
648
775
  int byteLen = sqlite3_column_bytes(statement, i);
649
776
  // Specify length too; in case string contains NULL in the middle
650
- row.push_back(JSVariant(std::string(column_value, byteLen)));
777
+ row.emplace_back(std::string(column_value, byteLen));
651
778
  break;
652
779
  }
653
780
 
654
781
  case SQLITE_BLOB: {
655
782
  int blob_size = sqlite3_column_bytes(statement, i);
656
783
  const void *blob = sqlite3_column_blob(statement, i);
657
- uint8_t *data = new uint8_t[blob_size];
784
+ auto *data = new uint8_t[blob_size];
658
785
  memcpy(data, blob, blob_size);
659
- row.push_back(
660
- JSVariant(ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
661
- .size = static_cast<size_t>(blob_size)}));
786
+ row.emplace_back(
787
+ ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
788
+ .size = static_cast<size_t>(blob_size)});
662
789
  break;
663
790
  }
664
791
 
665
792
  case SQLITE_NULL:
666
- row.push_back(JSVariant(nullptr));
667
- break;
668
-
793
+ // intentional fallthrough
669
794
  default:
670
- row.push_back(JSVariant(nullptr));
795
+ row.emplace_back(nullptr);
671
796
  break;
672
797
  }
673
798
  i++;
@@ -690,8 +815,8 @@ opsqlite_execute_raw(std::string const &dbName, std::string const &query,
690
815
  }
691
816
 
692
817
  sqlite3_finalize(statement);
693
- } while (remainingStatement != NULL && strcmp(remainingStatement, "") != 0 &&
694
- !isFailed);
818
+ } while (remainingStatement != nullptr &&
819
+ strcmp(remainingStatement, "") != 0 && !isFailed);
695
820
 
696
821
  if (isFailed) {
697
822
 
@@ -773,7 +898,7 @@ BridgeResult opsqlite_deregister_update_hook(std::string const &dbName) {
773
898
  sqlite3 *db = dbMap[dbName];
774
899
  updateCallbackMap.erase(dbName);
775
900
 
776
- sqlite3_update_hook(db, NULL, NULL);
901
+ sqlite3_update_hook(db, nullptr, nullptr);
777
902
 
778
903
  return {SQLiteOk};
779
904
  }
@@ -811,7 +936,7 @@ BridgeResult opsqlite_deregister_commit_hook(std::string const &dbName) {
811
936
 
812
937
  sqlite3 *db = dbMap[dbName];
813
938
  commitCallbackMap.erase(dbName);
814
- sqlite3_commit_hook(db, NULL, NULL);
939
+ sqlite3_commit_hook(db, nullptr, nullptr);
815
940
 
816
941
  return {SQLiteOk};
817
942
  }
@@ -848,7 +973,7 @@ BridgeResult opsqlite_deregister_rollback_hook(std::string const &dbName) {
848
973
  sqlite3 *db = dbMap[dbName];
849
974
  rollbackCallbackMap.erase(dbName);
850
975
 
851
- sqlite3_rollback_hook(db, NULL, NULL);
976
+ sqlite3_rollback_hook(db, nullptr, nullptr);
852
977
 
853
978
  return {SQLiteOk};
854
979
  }
@@ -884,7 +1009,7 @@ BridgeResult opsqlite_load_extension(std::string const &db_name,
884
1009
  #endif
885
1010
  }
886
1011
 
887
- BatchResult opsqlite_execute_batch(std::string dbName,
1012
+ BatchResult opsqlite_execute_batch(std::string &name,
888
1013
  std::vector<BatchArguments> *commands) {
889
1014
  size_t commandCount = commands->size();
890
1015
  if (commandCount <= 0) {
@@ -896,16 +1021,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
896
1021
 
897
1022
  try {
898
1023
  int affectedRows = 0;
899
- opsqlite_execute(dbName, "BEGIN EXCLUSIVE TRANSACTION", nullptr, nullptr,
900
- nullptr);
1024
+ opsqlite_execute(name, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
901
1025
  for (int i = 0; i < commandCount; i++) {
902
1026
  auto command = commands->at(i);
903
1027
  // We do not provide a datastructure to receive query data because we
904
1028
  // don't need/want to handle this results in a batch execution
905
- auto result = opsqlite_execute(dbName, command.sql, command.params.get(),
906
- nullptr, nullptr);
1029
+ auto result = opsqlite_execute(name, command.sql, command.params.get());
907
1030
  if (result.type == SQLiteError) {
908
- opsqlite_execute(dbName, "ROLLBACK", nullptr, nullptr, nullptr);
1031
+ opsqlite_execute(name, "ROLLBACK", nullptr);
909
1032
  return BatchResult{
910
1033
  .type = SQLiteError,
911
1034
  .message = result.message,
@@ -914,14 +1037,14 @@ BatchResult opsqlite_execute_batch(std::string dbName,
914
1037
  affectedRows += result.affectedRows;
915
1038
  }
916
1039
  }
917
- opsqlite_execute(dbName, "COMMIT", nullptr, nullptr, nullptr);
1040
+ opsqlite_execute(name, "COMMIT", nullptr);
918
1041
  return BatchResult{
919
1042
  .type = SQLiteOk,
920
1043
  .affectedRows = affectedRows,
921
1044
  .commands = static_cast<int>(commandCount),
922
1045
  };
923
1046
  } catch (std::exception &exc) {
924
- opsqlite_execute(dbName, "ROLLBACK", nullptr, nullptr, nullptr);
1047
+ opsqlite_execute(name, "ROLLBACK", nullptr);
925
1048
  return BatchResult{
926
1049
  .type = SQLiteError,
927
1050
  .message = exc.what(),