@op-engineering/op-sqlite 11.2.14 → 11.3.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/cpp/bridge.cpp CHANGED
@@ -25,38 +25,42 @@ namespace opsqlite {
25
25
 
26
26
  inline void opsqlite_bind_statement(sqlite3_stmt *statement,
27
27
  const std::vector<JSVariant> *values) {
28
- sqlite3_clear_bindings(statement);
29
-
30
- size_t size = values->size();
31
-
32
- for (int ii = 0; ii < size; ii++) {
33
- int stmt_index = ii + 1;
34
- JSVariant value = values->at(ii);
35
-
36
- std::visit(
37
- [&](auto &&v) {
38
- using T = std::decay_t<decltype(v)>;
39
-
40
- if constexpr (std::is_same_v<T, bool>) {
41
- sqlite3_bind_int(statement, stmt_index, static_cast<int>(v));
42
- } else if constexpr (std::is_same_v<T, int>) {
43
- sqlite3_bind_int(statement, stmt_index, v);
44
- } else if constexpr (std::is_same_v<T, long long>) {
45
- sqlite3_bind_double(statement, stmt_index, static_cast<double>(v));
46
- } else if constexpr (std::is_same_v<T, double>) {
47
- sqlite3_bind_double(statement, stmt_index, v);
48
- } else if constexpr (std::is_same_v<T, std::string>) {
49
- sqlite3_bind_text(statement, stmt_index, v.c_str(),
50
- static_cast<int>(v.length()), SQLITE_TRANSIENT);
51
- } else if constexpr (std::is_same_v<T, ArrayBuffer>) {
52
- sqlite3_bind_blob(statement, stmt_index, v.data.get(),
53
- static_cast<int>(v.size), SQLITE_TRANSIENT);
54
- } else {
55
- sqlite3_bind_null(statement, stmt_index);
56
- }
57
- },
58
- value);
59
- }
28
+ sqlite3_clear_bindings(statement);
29
+
30
+ size_t size = values->size();
31
+
32
+ for (int ii = 0; ii < size; ii++) {
33
+ int stmt_index = ii + 1;
34
+ JSVariant value = values->at(ii);
35
+
36
+ std::visit(
37
+ [&](auto &&v) {
38
+ using T = std::decay_t<decltype(v)>;
39
+
40
+ if constexpr (std::is_same_v<T, bool>) {
41
+ sqlite3_bind_int(statement, stmt_index,
42
+ static_cast<int>(v));
43
+ } else if constexpr (std::is_same_v<T, int>) {
44
+ sqlite3_bind_int(statement, stmt_index, v);
45
+ } else if constexpr (std::is_same_v<T, long long>) {
46
+ sqlite3_bind_double(statement, stmt_index,
47
+ static_cast<double>(v));
48
+ } else if constexpr (std::is_same_v<T, double>) {
49
+ sqlite3_bind_double(statement, stmt_index, v);
50
+ } else if constexpr (std::is_same_v<T, std::string>) {
51
+ sqlite3_bind_text(statement, stmt_index, v.c_str(),
52
+ static_cast<int>(v.length()),
53
+ SQLITE_TRANSIENT);
54
+ } else if constexpr (std::is_same_v<T, ArrayBuffer>) {
55
+ sqlite3_bind_blob(statement, stmt_index, v.data.get(),
56
+ static_cast<int>(v.size),
57
+ SQLITE_TRANSIENT);
58
+ } else {
59
+ sqlite3_bind_null(statement, stmt_index);
60
+ }
61
+ },
62
+ value);
63
+ }
60
64
  }
61
65
 
62
66
  /// Returns the completely formed db path, but it also creates any sub-folders
@@ -64,18 +68,18 @@ inline void opsqlite_bind_statement(sqlite3_stmt *statement,
64
68
  std::string opsqlite_get_db_path(std::string const &db_name,
65
69
  std::string const &location) {
66
70
 
67
- if (location == ":memory:") {
68
- return location;
69
- }
71
+ if (location == ":memory:") {
72
+ return location;
73
+ }
70
74
 
71
- // Will return false if the directory already exists, no need to check
72
- std::filesystem::create_directories(location);
75
+ // Will return false if the directory already exists, no need to check
76
+ std::filesystem::create_directories(location);
73
77
 
74
- if (!location.empty() && location.back() != '/') {
75
- return location + "/" + db_name;
76
- }
78
+ if (!location.empty() && location.back() != '/') {
79
+ return location + "/" + db_name;
80
+ }
77
81
 
78
- return location + db_name;
82
+ return location + db_name;
79
83
  }
80
84
 
81
85
  #ifdef OP_SQLITE_USE_SQLCIPHER
@@ -88,363 +92,371 @@ sqlite3 *opsqlite_open(std::string const &name, std::string const &path,
88
92
  [[maybe_unused]] std::string const &crsqlite_path,
89
93
  [[maybe_unused]] std::string const &sqlite_vec_path) {
90
94
  #endif
91
- std::string final_path = opsqlite_get_db_path(name, path);
92
- char *errMsg;
93
- sqlite3 *db;
95
+ std::string final_path = opsqlite_get_db_path(name, path);
96
+ char *errMsg;
97
+ sqlite3 *db;
94
98
 
95
- int flags =
96
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
99
+ int flags =
100
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
97
101
 
98
- int status = sqlite3_open_v2(final_path.c_str(), &db, flags, nullptr);
102
+ int status = sqlite3_open_v2(final_path.c_str(), &db, flags, nullptr);
99
103
 
100
- if (status != SQLITE_OK) {
101
- throw std::runtime_error(sqlite3_errmsg(db));
102
- }
104
+ if (status != SQLITE_OK) {
105
+ throw std::runtime_error(sqlite3_errmsg(db));
106
+ }
103
107
 
104
108
  #ifdef OP_SQLITE_USE_SQLCIPHER
105
- if (!encryption_key.empty()) {
106
- opsqlite_execute(db, "PRAGMA key = '" + encryption_key + "'", nullptr);
107
- }
109
+ if (!encryption_key.empty()) {
110
+ opsqlite_execute(db, "PRAGMA key = '" + encryption_key + "'", nullptr);
111
+ }
108
112
  #endif
109
113
 
110
114
  #ifndef OP_SQLITE_USE_PHONE_VERSION
111
- sqlite3_enable_load_extension(db, 1);
115
+ sqlite3_enable_load_extension(db, 1);
112
116
  #endif
113
117
 
114
118
  #ifdef OP_SQLITE_USE_CRSQLITE
115
- const char *crsqliteEntryPoint = "sqlite3_crsqlite_init";
119
+ const char *crsqliteEntryPoint = "sqlite3_crsqlite_init";
116
120
 
117
- sqlite3_load_extension(db, crsqlite_path.c_str(), crsqliteEntryPoint,
118
- &errMsg);
121
+ sqlite3_load_extension(db, crsqlite_path.c_str(), crsqliteEntryPoint,
122
+ &errMsg);
119
123
 
120
- if (errMsg != nullptr) {
121
- throw std::runtime_error(errMsg);
122
- }
124
+ if (errMsg != nullptr) {
125
+ throw std::runtime_error(errMsg);
126
+ }
123
127
  #endif
124
128
 
125
129
  #ifdef OP_SQLITE_USE_SQLITE_VEC
126
- const char *vec_entry_point = "sqlite3_vec_init";
130
+ const char *vec_entry_point = "sqlite3_vec_init";
127
131
 
128
- sqlite3_load_extension(db, sqlite_vec_path.c_str(), vec_entry_point, &errMsg);
132
+ sqlite3_load_extension(db, sqlite_vec_path.c_str(), vec_entry_point,
133
+ &errMsg);
129
134
 
130
- if (errMsg != nullptr) {
131
- throw std::runtime_error(errMsg);
132
- }
135
+ if (errMsg != nullptr) {
136
+ throw std::runtime_error(errMsg);
137
+ }
133
138
  #endif
134
139
 
135
- TOKENIZER_LIST
140
+ TOKENIZER_LIST
136
141
 
137
- return db;
142
+ return db;
138
143
  }
139
144
 
140
145
  void opsqlite_close(sqlite3 *db) {
141
146
  #ifdef OP_SQLITE_USE_CRSQLITE
142
- opsqlite_execute(db, "select crsql_finalize();", nullptr);
147
+ opsqlite_execute(db, "select crsql_finalize();", nullptr);
143
148
  #endif
144
149
 
145
- sqlite3_close_v2(db);
150
+ sqlite3_close_v2(db);
146
151
  }
147
152
 
148
153
  void opsqlite_attach(sqlite3 *db, std::string const &main_db_name,
149
154
  std::string const &doc_path,
150
155
  std::string const &secondary_db_name,
151
156
  std::string const &alias) {
152
- auto secondary_db_path = opsqlite_get_db_path(secondary_db_name, doc_path);
153
- auto statement = "ATTACH DATABASE '" + secondary_db_path + "' AS " + alias;
157
+ auto secondary_db_path = opsqlite_get_db_path(secondary_db_name, doc_path);
158
+ auto statement = "ATTACH DATABASE '" + secondary_db_path + "' AS " + alias;
154
159
 
155
- opsqlite_execute(db, statement, nullptr);
160
+ opsqlite_execute(db, statement, nullptr);
156
161
  }
157
162
 
158
163
  void opsqlite_detach(sqlite3 *db, std::string const &main_db_name,
159
164
  std::string const &alias) {
160
- std::string statement = "DETACH DATABASE " + alias;
161
- opsqlite_execute(db, statement, nullptr);
165
+ std::string statement = "DETACH DATABASE " + alias;
166
+ opsqlite_execute(db, statement, nullptr);
162
167
  }
163
168
 
164
169
  void opsqlite_remove(sqlite3 *db, std::string const &name,
165
170
  std::string const &doc_path) {
166
- opsqlite_close(db);
171
+ opsqlite_close(db);
167
172
 
168
- std::string db_path = opsqlite_get_db_path(name, doc_path);
173
+ std::string db_path = opsqlite_get_db_path(name, doc_path);
169
174
 
170
- if (!file_exists(db_path)) {
171
- throw std::runtime_error("op-sqlite: db file not found:" + db_path);
172
- }
175
+ if (!file_exists(db_path)) {
176
+ throw std::runtime_error("op-sqlite: db file not found:" + db_path);
177
+ }
173
178
 
174
- remove(db_path.c_str());
179
+ remove(db_path.c_str());
175
180
  }
176
181
 
177
182
  BridgeResult opsqlite_execute_prepared_statement(
178
183
  sqlite3 *db, sqlite3_stmt *statement, std::vector<DumbHostObject> *results,
179
184
  std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
180
185
 
181
- const char *errorMessage;
182
-
183
- bool isConsuming = true;
184
- bool isFailed = false;
185
-
186
- int result = SQLITE_OK;
187
-
188
- int i, count, column_type;
189
- std::string column_name, column_declared_type;
186
+ const char *errorMessage;
190
187
 
191
- while (isConsuming) {
192
- result = sqlite3_step(statement);
188
+ bool isConsuming = true;
189
+ bool isFailed = false;
193
190
 
194
- switch (result) {
195
- case SQLITE_ROW: {
196
- i = 0;
197
- DumbHostObject row = DumbHostObject(metadatas);
191
+ int result = SQLITE_OK;
198
192
 
199
- count = sqlite3_column_count(statement);
200
-
201
- while (i < count) {
202
- column_type = sqlite3_column_type(statement, i);
203
-
204
- switch (column_type) {
205
- case SQLITE_INTEGER: {
206
- /**
207
- * Warning this will loose precision because JS can
208
- * only represent Integers up to 53 bits
209
- */
210
- double column_value = sqlite3_column_double(statement, i);
211
- row.values.emplace_back(column_value);
212
- break;
213
- }
214
-
215
- case SQLITE_FLOAT: {
216
- double column_value = sqlite3_column_double(statement, i);
217
- row.values.emplace_back(column_value);
218
- break;
219
- }
193
+ int i, count, column_type;
194
+ std::string column_name, column_declared_type;
220
195
 
221
- case SQLITE_TEXT: {
222
- const char *column_value =
223
- reinterpret_cast<const char *>(sqlite3_column_text(statement, i));
224
- int byteLen = sqlite3_column_bytes(statement, i);
225
- // Specify length too; in case string contains NULL in the middle
226
- row.values.emplace_back(std::string(column_value, byteLen));
227
- break;
228
- }
196
+ while (isConsuming) {
197
+ result = sqlite3_step(statement);
198
+
199
+ switch (result) {
200
+ case SQLITE_ROW: {
201
+ i = 0;
202
+ DumbHostObject row = DumbHostObject(metadatas);
203
+
204
+ count = sqlite3_column_count(statement);
205
+
206
+ while (i < count) {
207
+ column_type = sqlite3_column_type(statement, i);
208
+
209
+ switch (column_type) {
210
+ case SQLITE_INTEGER: {
211
+ /**
212
+ * Warning this will loose precision because JS can
213
+ * only represent Integers up to 53 bits
214
+ */
215
+ double column_value = sqlite3_column_double(statement, i);
216
+ row.values.emplace_back(column_value);
217
+ break;
218
+ }
219
+
220
+ case SQLITE_FLOAT: {
221
+ double column_value = sqlite3_column_double(statement, i);
222
+ row.values.emplace_back(column_value);
223
+ break;
224
+ }
225
+
226
+ case SQLITE_TEXT: {
227
+ const char *column_value = reinterpret_cast<const char *>(
228
+ sqlite3_column_text(statement, i));
229
+ int byteLen = sqlite3_column_bytes(statement, i);
230
+ // Specify length too; in case string contains NULL in the
231
+ // middle
232
+ row.values.emplace_back(std::string(column_value, byteLen));
233
+ break;
234
+ }
235
+
236
+ case SQLITE_BLOB: {
237
+ int blob_size = sqlite3_column_bytes(statement, i);
238
+ const void *blob = sqlite3_column_blob(statement, i);
239
+ auto *data = new uint8_t[blob_size];
240
+ // You cannot share raw memory between native and JS
241
+ // always copy the data
242
+ memcpy(data, blob, blob_size);
243
+ row.values.emplace_back(
244
+ ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
245
+ .size = static_cast<size_t>(blob_size)});
246
+ break;
247
+ }
248
+
249
+ case SQLITE_NULL:
250
+ // Intentionally left blank
251
+
252
+ default:
253
+ row.values.emplace_back(nullptr);
254
+ break;
255
+ }
256
+ i++;
257
+ }
258
+
259
+ results->emplace_back(row);
229
260
 
230
- case SQLITE_BLOB: {
231
- int blob_size = sqlite3_column_bytes(statement, i);
232
- const void *blob = sqlite3_column_blob(statement, i);
233
- auto *data = new uint8_t[blob_size];
234
- // You cannot share raw memory between native and JS
235
- // always copy the data
236
- memcpy(data, blob, blob_size);
237
- row.values.emplace_back(
238
- ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
239
- .size = static_cast<size_t>(blob_size)});
240
- break;
261
+ break;
241
262
  }
242
263
 
243
- case SQLITE_NULL:
244
- // Intentionally left blank
264
+ case SQLITE_DONE:
265
+ if (metadatas != nullptr) {
266
+ i = 0;
267
+ count = sqlite3_column_count(statement);
268
+
269
+ while (i < count) {
270
+ column_name = sqlite3_column_name(statement, i);
271
+ const char *type = sqlite3_column_decltype(statement, i);
272
+ auto metadata = SmartHostObject();
273
+ metadata.fields.emplace_back("name", column_name);
274
+ metadata.fields.emplace_back("index", i);
275
+ metadata.fields.emplace_back(
276
+ "type", type == nullptr ? "UNKNOWN" : type);
277
+
278
+ metadatas->emplace_back(metadata);
279
+ i++;
280
+ }
281
+ }
282
+ isConsuming = false;
283
+ break;
245
284
 
246
285
  default:
247
- row.values.emplace_back(nullptr);
248
- break;
286
+ errorMessage = sqlite3_errmsg(db);
287
+ isFailed = true;
288
+ isConsuming = false;
249
289
  }
250
- i++;
251
- }
252
-
253
- results->emplace_back(row);
254
-
255
- break;
256
290
  }
257
291
 
258
- case SQLITE_DONE:
259
- if (metadatas != nullptr) {
260
- i = 0;
261
- count = sqlite3_column_count(statement);
262
-
263
- while (i < count) {
264
- column_name = sqlite3_column_name(statement, i);
265
- const char *type = sqlite3_column_decltype(statement, i);
266
- auto metadata = SmartHostObject();
267
- metadata.fields.emplace_back("name", column_name);
268
- metadata.fields.emplace_back("index", i);
269
- metadata.fields.emplace_back("type",
270
- type == nullptr ? "UNKNOWN" : type);
271
-
272
- metadatas->emplace_back(metadata);
273
- i++;
274
- }
275
- }
276
- isConsuming = false;
277
- break;
292
+ sqlite3_reset(statement);
278
293
 
279
- default:
280
- errorMessage = sqlite3_errmsg(db);
281
- isFailed = true;
282
- isConsuming = false;
294
+ if (isFailed) {
295
+ throw std::runtime_error(
296
+ "[op-sqlite] SQLite code: " + std::to_string(result) +
297
+ " execution error: " + std::string(errorMessage));
283
298
  }
284
- }
285
-
286
- sqlite3_reset(statement);
287
-
288
- if (isFailed) {
289
- throw std::runtime_error(
290
- "[op-sqlite] SQLite code: " + std::to_string(result) +
291
- " execution error: " + std::string(errorMessage));
292
- }
293
299
 
294
- int changedRowCount = sqlite3_changes(db);
295
- long long latestInsertRowId = sqlite3_last_insert_rowid(db);
300
+ int changedRowCount = sqlite3_changes(db);
301
+ long long latestInsertRowId = sqlite3_last_insert_rowid(db);
296
302
 
297
- return {.affectedRows = changedRowCount,
298
- .insertId = static_cast<double>(latestInsertRowId)};
303
+ return {.affectedRows = changedRowCount,
304
+ .insertId = static_cast<double>(latestInsertRowId)};
299
305
  }
300
306
 
301
307
  sqlite3_stmt *opsqlite_prepare_statement(sqlite3 *db,
302
308
  std::string const &query) {
303
- sqlite3_stmt *statement;
309
+ sqlite3_stmt *statement;
304
310
 
305
- const char *queryStr = query.c_str();
311
+ const char *queryStr = query.c_str();
306
312
 
307
- int statementStatus =
308
- sqlite3_prepare_v2(db, queryStr, -1, &statement, nullptr);
313
+ int statementStatus =
314
+ sqlite3_prepare_v2(db, queryStr, -1, &statement, nullptr);
309
315
 
310
- if (statementStatus == SQLITE_ERROR) {
311
- const char *message = sqlite3_errmsg(db);
312
- throw std::runtime_error("[op-sqlite] SQL prepare statement error: " +
313
- std::string(message));
314
- }
316
+ if (statementStatus == SQLITE_ERROR) {
317
+ const char *message = sqlite3_errmsg(db);
318
+ throw std::runtime_error("[op-sqlite] SQL prepare statement error: " +
319
+ std::string(message));
320
+ }
315
321
 
316
- return statement;
322
+ return statement;
317
323
  }
318
324
 
319
325
  BridgeResult opsqlite_execute(sqlite3 *db, std::string const &query,
320
326
  const std::vector<JSVariant> *params) {
321
- sqlite3_stmt *statement;
322
- const char *errorMessage = nullptr;
323
- const char *remainingStatement = nullptr;
324
- bool has_failed = false;
325
- int status, current_column, column_count, column_type;
326
- std::string column_name, column_declared_type;
327
- std::vector<std::string> column_names;
328
- std::vector<std::vector<JSVariant>> rows;
329
- rows.reserve(20);
330
- std::vector<JSVariant> row;
331
-
332
- do {
333
- const char *query_str =
334
- remainingStatement == nullptr ? query.c_str() : remainingStatement;
335
-
336
- status =
337
- sqlite3_prepare_v2(db, query_str, -1, &statement, &remainingStatement);
338
-
339
- if (status != SQLITE_OK) {
340
- errorMessage = sqlite3_errmsg(db);
341
- throw std::runtime_error("[op-sqlite] sqlite query error: " +
342
- std::string(errorMessage));
343
- }
344
-
345
- // The statement did not fail to parse but there is nothing to do, just
346
- // skip to the end
347
- if (statement == nullptr) {
348
- continue;
349
- }
350
-
351
- if (params != nullptr && !params->empty()) {
352
- opsqlite_bind_statement(statement, params);
353
- }
354
-
355
- column_count = sqlite3_column_count(statement);
356
- column_names.reserve(column_count);
357
- bool is_consuming_rows = true;
358
- double double_value;
359
- const char *string_value;
360
-
361
- // Do a first pass to get the column names
362
- for (int i = 0; i < column_count; i++) {
363
- column_name = sqlite3_column_name(statement, i);
364
- column_names.emplace_back(column_name);
365
- }
327
+ sqlite3_stmt *statement;
328
+ const char *errorMessage = nullptr;
329
+ const char *remainingStatement = nullptr;
330
+ bool has_failed = false;
331
+ int status, current_column, column_count, column_type;
332
+ std::string column_name, column_declared_type;
333
+ std::vector<std::string> column_names;
334
+ std::vector<std::vector<JSVariant>> rows;
335
+ rows.reserve(20);
336
+ std::vector<JSVariant> row;
337
+
338
+ do {
339
+ const char *query_str =
340
+ remainingStatement == nullptr ? query.c_str() : remainingStatement;
341
+
342
+ status = sqlite3_prepare_v2(db, query_str, -1, &statement,
343
+ &remainingStatement);
344
+
345
+ if (status != SQLITE_OK) {
346
+ errorMessage = sqlite3_errmsg(db);
347
+ throw std::runtime_error("[op-sqlite] sqlite query error: " +
348
+ std::string(errorMessage));
349
+ }
366
350
 
367
- while (is_consuming_rows) {
368
- status = sqlite3_step(statement);
351
+ // The statement did not fail to parse but there is nothing to do, just
352
+ // skip to the end
353
+ if (statement == nullptr) {
354
+ continue;
355
+ }
369
356
 
370
- switch (status) {
371
- case SQLITE_ROW:
372
- current_column = 0;
373
- row = std::vector<JSVariant>();
374
- row.reserve(column_count);
357
+ if (params != nullptr && !params->empty()) {
358
+ opsqlite_bind_statement(statement, params);
359
+ }
375
360
 
376
- while (current_column < column_count) {
377
- column_type = sqlite3_column_type(statement, current_column);
361
+ column_count = sqlite3_column_count(statement);
362
+ column_names.reserve(column_count);
363
+ bool is_consuming_rows = true;
364
+ double double_value;
365
+ const char *string_value;
378
366
 
379
- switch (column_type) {
367
+ // Do a first pass to get the column names
368
+ for (int i = 0; i < column_count; i++) {
369
+ column_name = sqlite3_column_name(statement, i);
370
+ column_names.emplace_back(column_name);
371
+ }
380
372
 
381
- case SQLITE_INTEGER:
382
- // intentional fallthrough
383
- case SQLITE_FLOAT: {
384
- double_value = sqlite3_column_double(statement, current_column);
385
- row.emplace_back(double_value);
386
- break;
387
- }
388
-
389
- case SQLITE_TEXT: {
390
- string_value = reinterpret_cast<const char *>(
391
- sqlite3_column_text(statement, current_column));
392
- int len = sqlite3_column_bytes(statement, current_column);
393
- // Specify length too; in case string contains NULL in the middle
394
- row.emplace_back(std::string(string_value, len));
395
- break;
396
- }
397
-
398
- case SQLITE_BLOB: {
399
- int blob_size = sqlite3_column_bytes(statement, current_column);
400
- const void *blob = sqlite3_column_blob(statement, current_column);
401
- auto *data = new uint8_t[blob_size];
402
- memcpy(data, blob, blob_size);
403
- row.emplace_back(
404
- ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
373
+ while (is_consuming_rows) {
374
+ status = sqlite3_step(statement);
375
+
376
+ switch (status) {
377
+ case SQLITE_ROW:
378
+ current_column = 0;
379
+ row = std::vector<JSVariant>();
380
+ row.reserve(column_count);
381
+
382
+ while (current_column < column_count) {
383
+ column_type =
384
+ sqlite3_column_type(statement, current_column);
385
+
386
+ switch (column_type) {
387
+
388
+ case SQLITE_INTEGER:
389
+ // intentional fallthrough
390
+ case SQLITE_FLOAT: {
391
+ double_value =
392
+ sqlite3_column_double(statement, current_column);
393
+ row.emplace_back(double_value);
394
+ break;
395
+ }
396
+
397
+ case SQLITE_TEXT: {
398
+ string_value = reinterpret_cast<const char *>(
399
+ sqlite3_column_text(statement, current_column));
400
+ int len =
401
+ sqlite3_column_bytes(statement, current_column);
402
+ // Specify length too; in case string contains NULL in
403
+ // the middle
404
+ row.emplace_back(std::string(string_value, len));
405
+ break;
406
+ }
407
+
408
+ case SQLITE_BLOB: {
409
+ int blob_size =
410
+ sqlite3_column_bytes(statement, current_column);
411
+ const void *blob =
412
+ sqlite3_column_blob(statement, current_column);
413
+ auto *data = new uint8_t[blob_size];
414
+ memcpy(data, blob, blob_size);
415
+ row.emplace_back(ArrayBuffer{
416
+ .data = std::shared_ptr<uint8_t>{data},
405
417
  .size = static_cast<size_t>(blob_size)});
406
- break;
407
- }
408
-
409
- case SQLITE_NULL:
410
- // Intentionally left blank to switch to default case
411
- default:
412
- row.emplace_back(nullptr);
413
- break;
414
- }
415
-
416
- current_column++;
418
+ break;
419
+ }
420
+
421
+ case SQLITE_NULL:
422
+ // Intentionally left blank to switch to default case
423
+ default:
424
+ row.emplace_back(nullptr);
425
+ break;
426
+ }
427
+
428
+ current_column++;
429
+ }
430
+
431
+ rows.emplace_back(std::move(row));
432
+ break;
433
+
434
+ case SQLITE_DONE:
435
+ is_consuming_rows = false;
436
+ break;
437
+
438
+ default:
439
+ has_failed = true;
440
+ is_consuming_rows = false;
441
+ }
417
442
  }
418
443
 
419
- rows.emplace_back(std::move(row));
420
- break;
444
+ sqlite3_finalize(statement);
445
+ } while (remainingStatement != nullptr &&
446
+ strcmp(remainingStatement, "") != 0 && !has_failed);
421
447
 
422
- case SQLITE_DONE:
423
- is_consuming_rows = false;
424
- break;
425
-
426
- default:
427
- has_failed = true;
428
- is_consuming_rows = false;
429
- }
448
+ if (has_failed) {
449
+ const char *message = sqlite3_errmsg(db);
450
+ throw std::runtime_error("[op-sqlite] statement execution error: " +
451
+ std::string(message));
430
452
  }
431
453
 
432
- sqlite3_finalize(statement);
433
- } while (remainingStatement != nullptr &&
434
- strcmp(remainingStatement, "") != 0 && !has_failed);
435
-
436
- if (has_failed) {
437
- const char *message = sqlite3_errmsg(db);
438
- throw std::runtime_error("[op-sqlite] statement execution error: " +
439
- std::string(message));
440
- }
441
-
442
- int changedRowCount = sqlite3_changes(db);
443
- long long latestInsertRowId = sqlite3_last_insert_rowid(db);
444
- return {.affectedRows = changedRowCount,
445
- .insertId = static_cast<double>(latestInsertRowId),
446
- .rows = std::move(rows),
447
- .column_names = std::move(column_names)};
454
+ int changedRowCount = sqlite3_changes(db);
455
+ long long latestInsertRowId = sqlite3_last_insert_rowid(db);
456
+ return {.affectedRows = changedRowCount,
457
+ .insertId = static_cast<double>(latestInsertRowId),
458
+ .rows = std::move(rows),
459
+ .column_names = std::move(column_names)};
448
460
  }
449
461
 
450
462
  BridgeResult opsqlite_execute_host_objects(
@@ -452,156 +464,162 @@ BridgeResult opsqlite_execute_host_objects(
452
464
  std::vector<DumbHostObject> *results,
453
465
  std::shared_ptr<std::vector<SmartHostObject>> &metadatas) {
454
466
 
455
- sqlite3_stmt *statement;
456
- const char *errorMessage;
457
- const char *remainingStatement = nullptr;
467
+ sqlite3_stmt *statement;
468
+ const char *errorMessage;
469
+ const char *remainingStatement = nullptr;
458
470
 
459
- bool isConsuming = true;
460
- bool isFailed = false;
471
+ bool isConsuming = true;
472
+ bool isFailed = false;
461
473
 
462
- int result = SQLITE_OK;
474
+ int result = SQLITE_OK;
463
475
 
464
- do {
465
- const char *queryStr =
466
- remainingStatement == nullptr ? query.c_str() : remainingStatement;
476
+ do {
477
+ const char *queryStr =
478
+ remainingStatement == nullptr ? query.c_str() : remainingStatement;
467
479
 
468
- int statementStatus =
469
- sqlite3_prepare_v2(db, queryStr, -1, &statement, &remainingStatement);
470
-
471
- if (statementStatus != SQLITE_OK) {
472
- const char *message = sqlite3_errmsg(db);
473
- throw std::runtime_error(
474
- "[op-sqlite] SQL statement error on opsqlite_execute:\n" +
475
- std::to_string(statementStatus) + " description:\n" +
476
- std::string(message));
477
- }
478
-
479
- // The statement did not fail to parse but there is nothing to do, just
480
- // skip to the end
481
- if (statement == nullptr) {
482
- continue;
483
- }
480
+ int statementStatus = sqlite3_prepare_v2(db, queryStr, -1, &statement,
481
+ &remainingStatement);
484
482
 
485
- if (params != nullptr && !params->empty()) {
486
- opsqlite_bind_statement(statement, params);
487
- }
488
-
489
- int i, count, column_type;
490
- std::string column_name, column_declared_type;
491
-
492
- while (isConsuming) {
493
- result = sqlite3_step(statement);
494
-
495
- switch (result) {
496
- case SQLITE_ROW: {
497
- if (results == nullptr) {
498
- break;
483
+ if (statementStatus != SQLITE_OK) {
484
+ const char *message = sqlite3_errmsg(db);
485
+ throw std::runtime_error(
486
+ "[op-sqlite] SQL statement error on opsqlite_execute:\n" +
487
+ std::to_string(statementStatus) + " description:\n" +
488
+ std::string(message));
499
489
  }
500
490
 
501
- i = 0;
502
- DumbHostObject row = DumbHostObject(metadatas);
503
-
504
- count = sqlite3_column_count(statement);
505
-
506
- while (i < count) {
507
- column_type = sqlite3_column_type(statement, i);
491
+ // The statement did not fail to parse but there is nothing to do, just
492
+ // skip to the end
493
+ if (statement == nullptr) {
494
+ continue;
495
+ }
508
496
 
509
- switch (column_type) {
510
- case SQLITE_INTEGER: {
511
- /**
512
- * Warning this will loose precision because JS can
513
- * only represent Integers up to 53 bits
514
- */
515
- double column_value = sqlite3_column_double(statement, i);
516
- row.values.emplace_back(column_value);
517
- break;
518
- }
497
+ if (params != nullptr && !params->empty()) {
498
+ opsqlite_bind_statement(statement, params);
499
+ }
519
500
 
520
- case SQLITE_FLOAT: {
521
- double column_value = sqlite3_column_double(statement, i);
522
- row.values.emplace_back(column_value);
523
- break;
524
- }
525
-
526
- case SQLITE_TEXT: {
527
- const char *column_value = reinterpret_cast<const char *>(
528
- sqlite3_column_text(statement, i));
529
- int byteLen = sqlite3_column_bytes(statement, i);
530
- // Specify length too; in case string contains NULL in the middle
531
- row.values.emplace_back(std::string(column_value, byteLen));
532
- break;
533
- }
534
-
535
- case SQLITE_BLOB: {
536
- int blob_size = sqlite3_column_bytes(statement, i);
537
- const void *blob = sqlite3_column_blob(statement, i);
538
- auto *data = new uint8_t[blob_size];
539
- // You cannot share raw memory between native and JS
540
- // always copy the data
541
- memcpy(data, blob, blob_size);
542
- row.values.emplace_back(
543
- ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
501
+ int i, count, column_type;
502
+ std::string column_name, column_declared_type;
503
+
504
+ while (isConsuming) {
505
+ result = sqlite3_step(statement);
506
+
507
+ switch (result) {
508
+ case SQLITE_ROW: {
509
+ if (results == nullptr) {
510
+ break;
511
+ }
512
+
513
+ i = 0;
514
+ DumbHostObject row = DumbHostObject(metadatas);
515
+
516
+ count = sqlite3_column_count(statement);
517
+
518
+ while (i < count) {
519
+ column_type = sqlite3_column_type(statement, i);
520
+
521
+ switch (column_type) {
522
+ case SQLITE_INTEGER: {
523
+ /**
524
+ * Warning this will loose precision because JS can
525
+ * only represent Integers up to 53 bits
526
+ */
527
+ double column_value =
528
+ sqlite3_column_double(statement, i);
529
+ row.values.emplace_back(column_value);
530
+ break;
531
+ }
532
+
533
+ case SQLITE_FLOAT: {
534
+ double column_value =
535
+ sqlite3_column_double(statement, i);
536
+ row.values.emplace_back(column_value);
537
+ break;
538
+ }
539
+
540
+ case SQLITE_TEXT: {
541
+ const char *column_value =
542
+ reinterpret_cast<const char *>(
543
+ sqlite3_column_text(statement, i));
544
+ int byteLen = sqlite3_column_bytes(statement, i);
545
+ // Specify length too; in case string contains NULL in
546
+ // the middle
547
+ row.values.emplace_back(
548
+ std::string(column_value, byteLen));
549
+ break;
550
+ }
551
+
552
+ case SQLITE_BLOB: {
553
+ int blob_size = sqlite3_column_bytes(statement, i);
554
+ const void *blob = sqlite3_column_blob(statement, i);
555
+ auto *data = new uint8_t[blob_size];
556
+ // You cannot share raw memory between native and JS
557
+ // always copy the data
558
+ memcpy(data, blob, blob_size);
559
+ row.values.emplace_back(ArrayBuffer{
560
+ .data = std::shared_ptr<uint8_t>{data},
544
561
  .size = static_cast<size_t>(blob_size)});
545
- break;
546
- }
547
-
548
- case SQLITE_NULL:
549
- // Intentionally left blank
550
-
551
- default:
552
- row.values.emplace_back(nullptr);
553
- break;
554
- }
555
- i++;
562
+ break;
563
+ }
564
+
565
+ case SQLITE_NULL:
566
+ // Intentionally left blank
567
+
568
+ default:
569
+ row.values.emplace_back(nullptr);
570
+ break;
571
+ }
572
+ i++;
573
+ }
574
+
575
+ results->emplace_back(row);
576
+ break;
577
+ }
578
+
579
+ case SQLITE_DONE:
580
+ if (metadatas != nullptr) {
581
+ i = 0;
582
+ count = sqlite3_column_count(statement);
583
+
584
+ while (i < count) {
585
+ column_name = sqlite3_column_name(statement, i);
586
+ const char *type =
587
+ sqlite3_column_decltype(statement, i);
588
+ auto metadata = SmartHostObject();
589
+ metadata.fields.emplace_back("name", column_name);
590
+ metadata.fields.emplace_back("index", i);
591
+ metadata.fields.emplace_back(
592
+ "type", type == nullptr ? "UNKNOWN" : type);
593
+
594
+ metadatas->push_back(metadata);
595
+ i++;
596
+ }
597
+ }
598
+ isConsuming = false;
599
+ break;
600
+
601
+ default:
602
+ errorMessage = sqlite3_errmsg(db);
603
+ isFailed = true;
604
+ isConsuming = false;
605
+ }
556
606
  }
557
607
 
558
- results->emplace_back(row);
559
- break;
560
- }
561
-
562
- case SQLITE_DONE:
563
- if (metadatas != nullptr) {
564
- i = 0;
565
- count = sqlite3_column_count(statement);
608
+ sqlite3_finalize(statement);
609
+ } while (remainingStatement != nullptr &&
610
+ strcmp(remainingStatement, "") != 0 && !isFailed);
566
611
 
567
- while (i < count) {
568
- column_name = sqlite3_column_name(statement, i);
569
- const char *type = sqlite3_column_decltype(statement, i);
570
- auto metadata = SmartHostObject();
571
- metadata.fields.emplace_back("name", column_name);
572
- metadata.fields.emplace_back("index", i);
573
- metadata.fields.emplace_back("type",
574
- type == nullptr ? "UNKNOWN" : type);
575
-
576
- metadatas->push_back(metadata);
577
- i++;
578
- }
579
- }
580
- isConsuming = false;
581
- break;
582
-
583
- default:
584
- errorMessage = sqlite3_errmsg(db);
585
- isFailed = true;
586
- isConsuming = false;
587
- }
612
+ if (isFailed) {
613
+ throw std::runtime_error(
614
+ "[op-sqlite] SQLite error code: " + std::to_string(result) +
615
+ ", description: " + std::string(errorMessage));
588
616
  }
589
617
 
590
- sqlite3_finalize(statement);
591
- } while (remainingStatement != nullptr &&
592
- strcmp(remainingStatement, "") != 0 && !isFailed);
593
-
594
- if (isFailed) {
595
- throw std::runtime_error(
596
- "[op-sqlite] SQLite error code: " + std::to_string(result) +
597
- ", description: " + std::string(errorMessage));
598
- }
618
+ int changedRowCount = sqlite3_changes(db);
619
+ long long latestInsertRowId = sqlite3_last_insert_rowid(db);
599
620
 
600
- int changedRowCount = sqlite3_changes(db);
601
- long long latestInsertRowId = sqlite3_last_insert_rowid(db);
602
-
603
- return {.affectedRows = changedRowCount,
604
- .insertId = static_cast<double>(latestInsertRowId)};
621
+ return {.affectedRows = changedRowCount,
622
+ .insertId = static_cast<double>(latestInsertRowId)};
605
623
  }
606
624
 
607
625
  /// Executes returning data in raw arrays, a small performance optimization
@@ -610,244 +628,248 @@ BridgeResult
610
628
  opsqlite_execute_raw(sqlite3 *db, std::string const &query,
611
629
  const std::vector<JSVariant> *params,
612
630
  std::vector<std::vector<JSVariant>> *results) {
613
- sqlite3_stmt *statement;
614
- const char *errorMessage;
615
- const char *remainingStatement = nullptr;
616
-
617
- bool isConsuming = true;
618
- bool isFailed = false;
631
+ sqlite3_stmt *statement;
632
+ const char *errorMessage;
633
+ const char *remainingStatement = nullptr;
619
634
 
620
- int step = SQLITE_OK;
635
+ bool isConsuming = true;
636
+ bool isFailed = false;
621
637
 
622
- do {
623
- const char *queryStr =
624
- remainingStatement == nullptr ? query.c_str() : remainingStatement;
638
+ int step = SQLITE_OK;
625
639
 
626
- int statementStatus =
627
- sqlite3_prepare_v2(db, queryStr, -1, &statement, &remainingStatement);
640
+ do {
641
+ const char *queryStr =
642
+ remainingStatement == nullptr ? query.c_str() : remainingStatement;
628
643
 
629
- if (statementStatus != SQLITE_OK) {
630
- const char *message = sqlite3_errmsg(db);
631
- throw std::runtime_error(
632
- "[op-sqlite] SQL statement error:" + std::to_string(statementStatus) +
633
- " description:" + std::string(message));
634
- }
644
+ int statementStatus = sqlite3_prepare_v2(db, queryStr, -1, &statement,
645
+ &remainingStatement);
635
646
 
636
- // The statement did not fail to parse but there is nothing to do, just
637
- // skip to the end
638
- if (statement == nullptr) {
639
- continue;
640
- }
641
-
642
- if (params != nullptr && !params->empty()) {
643
- opsqlite_bind_statement(statement, params);
644
- }
645
-
646
- int i, column_type;
647
- std::string column_name, column_declared_type;
648
-
649
- int column_count = sqlite3_column_count(statement);
650
-
651
- while (isConsuming) {
652
- step = sqlite3_step(statement);
653
-
654
- switch (step) {
655
- case SQLITE_ROW: {
656
- if (results == nullptr) {
657
- break;
647
+ if (statementStatus != SQLITE_OK) {
648
+ const char *message = sqlite3_errmsg(db);
649
+ throw std::runtime_error("[op-sqlite] SQL statement error:" +
650
+ std::to_string(statementStatus) +
651
+ " description:" + std::string(message));
658
652
  }
659
653
 
660
- std::vector<JSVariant> row;
661
- row.reserve(column_count);
662
-
663
- i = 0;
654
+ // The statement did not fail to parse but there is nothing to do, just
655
+ // skip to the end
656
+ if (statement == nullptr) {
657
+ continue;
658
+ }
664
659
 
665
- while (i < column_count) {
666
- column_type = sqlite3_column_type(statement, i);
660
+ if (params != nullptr && !params->empty()) {
661
+ opsqlite_bind_statement(statement, params);
662
+ }
667
663
 
668
- switch (column_type) {
669
- case SQLITE_INTEGER:
670
- case SQLITE_FLOAT: {
671
- double column_value = sqlite3_column_double(statement, i);
672
- row.emplace_back(column_value);
673
- break;
674
- }
675
-
676
- case SQLITE_TEXT: {
677
- const char *column_value = reinterpret_cast<const char *>(
678
- sqlite3_column_text(statement, i));
679
- int byteLen = sqlite3_column_bytes(statement, i);
680
- // Specify length too; in case string contains NULL in the middle
681
- row.emplace_back(std::string(column_value, byteLen));
682
- break;
683
- }
684
-
685
- case SQLITE_BLOB: {
686
- int blob_size = sqlite3_column_bytes(statement, i);
687
- const void *blob = sqlite3_column_blob(statement, i);
688
- auto *data = new uint8_t[blob_size];
689
- memcpy(data, blob, blob_size);
690
- row.emplace_back(
691
- ArrayBuffer{.data = std::shared_ptr<uint8_t>{data},
664
+ int i, column_type;
665
+ std::string column_name, column_declared_type;
666
+
667
+ int column_count = sqlite3_column_count(statement);
668
+
669
+ while (isConsuming) {
670
+ step = sqlite3_step(statement);
671
+
672
+ switch (step) {
673
+ case SQLITE_ROW: {
674
+ if (results == nullptr) {
675
+ break;
676
+ }
677
+
678
+ std::vector<JSVariant> row;
679
+ row.reserve(column_count);
680
+
681
+ i = 0;
682
+
683
+ while (i < column_count) {
684
+ column_type = sqlite3_column_type(statement, i);
685
+
686
+ switch (column_type) {
687
+ case SQLITE_INTEGER:
688
+ case SQLITE_FLOAT: {
689
+ double column_value =
690
+ sqlite3_column_double(statement, i);
691
+ row.emplace_back(column_value);
692
+ break;
693
+ }
694
+
695
+ case SQLITE_TEXT: {
696
+ const char *column_value =
697
+ reinterpret_cast<const char *>(
698
+ sqlite3_column_text(statement, i));
699
+ int byteLen = sqlite3_column_bytes(statement, i);
700
+ // Specify length too; in case string contains NULL in
701
+ // the middle
702
+ row.emplace_back(std::string(column_value, byteLen));
703
+ break;
704
+ }
705
+
706
+ case SQLITE_BLOB: {
707
+ int blob_size = sqlite3_column_bytes(statement, i);
708
+ const void *blob = sqlite3_column_blob(statement, i);
709
+ auto *data = new uint8_t[blob_size];
710
+ memcpy(data, blob, blob_size);
711
+ row.emplace_back(ArrayBuffer{
712
+ .data = std::shared_ptr<uint8_t>{data},
692
713
  .size = static_cast<size_t>(blob_size)});
693
- break;
694
- }
695
-
696
- case SQLITE_NULL:
697
- // intentional fallthrough
698
- default:
699
- row.emplace_back(nullptr);
700
- break;
701
- }
702
- i++;
714
+ break;
715
+ }
716
+
717
+ case SQLITE_NULL:
718
+ // intentional fallthrough
719
+ default:
720
+ row.emplace_back(nullptr);
721
+ break;
722
+ }
723
+ i++;
724
+ }
725
+
726
+ results->emplace_back(row);
727
+
728
+ break;
729
+ }
730
+
731
+ case SQLITE_DONE:
732
+ isConsuming = false;
733
+ break;
734
+
735
+ default:
736
+ errorMessage = sqlite3_errmsg(db);
737
+ isFailed = true;
738
+ isConsuming = false;
739
+ }
703
740
  }
704
741
 
705
- results->emplace_back(row);
742
+ sqlite3_finalize(statement);
743
+ } while (remainingStatement != nullptr &&
744
+ strcmp(remainingStatement, "") != 0 && !isFailed);
706
745
 
707
- break;
708
- }
709
-
710
- case SQLITE_DONE:
711
- isConsuming = false;
712
- break;
713
-
714
- default:
715
- errorMessage = sqlite3_errmsg(db);
716
- isFailed = true;
717
- isConsuming = false;
718
- }
746
+ if (isFailed) {
747
+ throw std::runtime_error(
748
+ "[op-sqlite] SQLite error code: " + std::to_string(step) +
749
+ ", description: " + std::string(errorMessage));
719
750
  }
720
751
 
721
- sqlite3_finalize(statement);
722
- } while (remainingStatement != nullptr &&
723
- strcmp(remainingStatement, "") != 0 && !isFailed);
724
-
725
- if (isFailed) {
726
- throw std::runtime_error(
727
- "[op-sqlite] SQLite error code: " + std::to_string(step) +
728
- ", description: " + std::string(errorMessage));
729
- }
730
-
731
- int changedRowCount = sqlite3_changes(db);
732
- long long latestInsertRowId = sqlite3_last_insert_rowid(db);
752
+ int changedRowCount = sqlite3_changes(db);
753
+ long long latestInsertRowId = sqlite3_last_insert_rowid(db);
733
754
 
734
- return {.affectedRows = changedRowCount,
735
- .insertId = static_cast<double>(latestInsertRowId)};
755
+ return {.affectedRows = changedRowCount,
756
+ .insertId = static_cast<double>(latestInsertRowId)};
736
757
  }
737
758
 
738
759
  std::string operation_to_string(int operation_type) {
739
- switch (operation_type) {
740
- case SQLITE_INSERT:
741
- return "INSERT";
760
+ switch (operation_type) {
761
+ case SQLITE_INSERT:
762
+ return "INSERT";
742
763
 
743
- case SQLITE_DELETE:
744
- return "DELETE";
764
+ case SQLITE_DELETE:
765
+ return "DELETE";
745
766
 
746
- case SQLITE_UPDATE:
747
- return "UPDATE";
767
+ case SQLITE_UPDATE:
768
+ return "UPDATE";
748
769
 
749
- default:
750
- throw std::runtime_error("Unknown SQLite operation on hook");
751
- }
770
+ default:
771
+ throw std::runtime_error("Unknown SQLite operation on hook");
772
+ }
752
773
  }
753
774
 
754
775
  void update_callback(void *db_host_object_ptr, int operation_type,
755
776
  [[maybe_unused]] char const *database, char const *table,
756
777
  sqlite3_int64 row_id) {
757
- auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
758
- db_host_object->on_update(std::string(table),
759
- operation_to_string(operation_type), row_id);
778
+ auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
779
+ db_host_object->on_update(std::string(table),
780
+ operation_to_string(operation_type), row_id);
760
781
  }
761
782
 
762
783
  void opsqlite_register_update_hook(sqlite3 *db, void *db_host_object) {
763
- sqlite3_update_hook(db, &update_callback, (void *)db_host_object);
784
+ sqlite3_update_hook(db, &update_callback, (void *)db_host_object);
764
785
  }
765
786
 
766
787
  void opsqlite_deregister_update_hook(sqlite3 *db) {
767
- sqlite3_update_hook(db, nullptr, nullptr);
788
+ sqlite3_update_hook(db, nullptr, nullptr);
768
789
  }
769
790
 
770
791
  int commit_callback(void *db_host_object_ptr) {
771
- auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
772
- db_host_object->on_commit();
773
- return 0;
792
+ auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
793
+ db_host_object->on_commit();
794
+ return 0;
774
795
  }
775
796
 
776
797
  void opsqlite_register_commit_hook(sqlite3 *db, void *db_host_object_ptr) {
777
- sqlite3_commit_hook(db, &commit_callback, db_host_object_ptr);
798
+ sqlite3_commit_hook(db, &commit_callback, db_host_object_ptr);
778
799
  }
779
800
 
780
801
  void opsqlite_deregister_commit_hook(sqlite3 *db) {
781
- sqlite3_commit_hook(db, nullptr, nullptr);
802
+ sqlite3_commit_hook(db, nullptr, nullptr);
782
803
  }
783
804
 
784
805
  void rollback_callback(void *db_host_object_ptr) {
785
- auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
786
- db_host_object->on_rollback();
806
+ auto db_host_object = reinterpret_cast<DBHostObject *>(db_host_object_ptr);
807
+ db_host_object->on_rollback();
787
808
  }
788
809
 
789
810
  void opsqlite_register_rollback_hook(sqlite3 *db, void *db_host_object_ptr) {
790
- sqlite3_rollback_hook(db, &rollback_callback, db_host_object_ptr);
811
+ sqlite3_rollback_hook(db, &rollback_callback, db_host_object_ptr);
791
812
  }
792
813
 
793
814
  void opsqlite_deregister_rollback_hook(sqlite3 *db) {
794
- sqlite3_rollback_hook(db, nullptr, nullptr);
815
+ sqlite3_rollback_hook(db, nullptr, nullptr);
795
816
  }
796
817
 
797
818
  void opsqlite_load_extension(sqlite3 *db, std::string &path,
798
819
  std::string &entry_point) {
799
820
  #ifdef OP_SQLITE_USE_PHONE_VERSION
800
- throw std::runtime_error("[op-sqlite] Embedded version of SQLite does not "
801
- "support loading extensions");
821
+ throw std::runtime_error("[op-sqlite] Embedded version of SQLite does not "
822
+ "support loading extensions");
802
823
  #else
803
- int status = 0;
804
- status = sqlite3_enable_load_extension(db, 1);
824
+ int status = 0;
825
+ status = sqlite3_enable_load_extension(db, 1);
805
826
 
806
- if (status != SQLITE_OK) {
807
- throw std::runtime_error("Could not enable extension loading");
808
- }
827
+ if (status != SQLITE_OK) {
828
+ throw std::runtime_error("Could not enable extension loading");
829
+ }
809
830
 
810
- const char *entry_point_cstr = nullptr;
811
- if (!entry_point.empty()) {
812
- entry_point_cstr = entry_point.c_str();
813
- }
831
+ const char *entry_point_cstr = nullptr;
832
+ if (!entry_point.empty()) {
833
+ entry_point_cstr = entry_point.c_str();
834
+ }
814
835
 
815
- char *error_message;
836
+ char *error_message;
816
837
 
817
- status = sqlite3_load_extension(db, path.c_str(), entry_point_cstr,
818
- &error_message);
819
- if (status != SQLITE_OK) {
820
- throw std::runtime_error(error_message);
821
- }
838
+ status = sqlite3_load_extension(db, path.c_str(), entry_point_cstr,
839
+ &error_message);
840
+ if (status != SQLITE_OK) {
841
+ throw std::runtime_error(error_message);
842
+ }
822
843
  #endif
823
844
  }
824
845
 
825
- BatchResult opsqlite_execute_batch(sqlite3 *db,
826
- std::vector<BatchArguments> *commands) {
827
- size_t commandCount = commands->size();
828
- if (commandCount <= 0) {
829
- throw std::runtime_error("No SQL commands provided");
830
- }
831
-
832
- int affectedRows = 0;
833
- opsqlite_execute(db, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
834
- for (int i = 0; i < commandCount; i++) {
835
- const auto &command = commands->at(i);
836
- // We do not provide a datastructure to receive query data because we
837
- // don't need/want to handle this results in a batch execution
838
- try {
839
- auto result = opsqlite_execute(db, command.sql, command.params.get());
840
- affectedRows += result.affectedRows;
841
- } catch (std::exception &exc) {
842
- opsqlite_execute(db, "ROLLBACK", nullptr);
843
- throw exc;
846
+ BatchResult
847
+ opsqlite_execute_batch(sqlite3 *db,
848
+ const std::vector<BatchArguments> *commands) {
849
+ size_t commandCount = commands->size();
850
+ if (commandCount <= 0) {
851
+ throw std::runtime_error("No SQL commands provided");
852
+ }
853
+
854
+ int affectedRows = 0;
855
+ opsqlite_execute(db, "BEGIN EXCLUSIVE TRANSACTION", nullptr);
856
+ for (int i = 0; i < commandCount; i++) {
857
+ const auto &command = commands->at(i);
858
+ // We do not provide a datastructure to receive query data because we
859
+ // don't need/want to handle this results in a batch execution
860
+ try {
861
+ auto result = opsqlite_execute(db, command.sql, &command.params);
862
+ affectedRows += result.affectedRows;
863
+ } catch (std::exception &exc) {
864
+ opsqlite_execute(db, "ROLLBACK", nullptr);
865
+ throw exc;
866
+ }
844
867
  }
845
- }
846
- opsqlite_execute(db, "COMMIT", nullptr);
847
- return BatchResult{
848
- .affectedRows = affectedRows,
849
- .commands = static_cast<int>(commandCount),
850
- };
868
+ opsqlite_execute(db, "COMMIT", nullptr);
869
+ return BatchResult{
870
+ .affectedRows = affectedRows,
871
+ .commands = static_cast<int>(commandCount),
872
+ };
851
873
  }
852
874
 
853
875
  } // namespace opsqlite