@op-engineering/op-sqlite 11.2.13 → 11.2.15

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