@rocicorp/zero-sqlite3 1.0.11 → 1.0.13

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/lib/index.d.ts CHANGED
@@ -43,6 +43,8 @@ declare namespace BetterSqlite3 {
43
43
  scanStatusV2(idx: number, opcode: ScanStatOpcode.SQLITE_SCANSTAT_PARENTID, resetFlag: number): number | undefined;
44
44
  scanStatusV2(idx: number, opcode: ScanStatOpcode.SQLITE_SCANSTAT_NCYCLE, resetFlag: number): number | undefined;
45
45
  scanStatusV2(idx: number, opcode: ScanStatOpcode, resetFlag: number): number | string | undefined;
46
+ scanStatusReset(): this;
47
+ explainQueryPlan(...params: BindParameters | []): Result[];
46
48
  }
47
49
 
48
50
  interface ColumnDefinition {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocicorp/zero-sqlite3",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "better-sqlite3 on bedrock",
5
5
  "homepage": "https://github.com/rocicorp/zero-sqlite3",
6
6
  "author": "Rocicorp",
@@ -65,6 +65,8 @@ INIT(Statement::Init) {
65
65
  SetPrototypeMethod(isolate, data, t, "safeIntegers", JS_safeIntegers);
66
66
  SetPrototypeMethod(isolate, data, t, "columns", JS_columns);
67
67
  SetPrototypeMethod(isolate, data, t, "scanStatusV2", JS_scanStatusV2);
68
+ SetPrototypeMethod(isolate, data, t, "scanStatusReset", JS_scanStatusReset);
69
+ SetPrototypeMethod(isolate, data, t, "explainQueryPlan", JS_explainQueryPlan);
68
70
  SetPrototypeGetter(isolate, data, t, "busy", JS_busy);
69
71
  return t->GetFunction(OnlyContext).ToLocalChecked();
70
72
  }
@@ -226,6 +228,90 @@ NODE_METHOD(Statement::JS_all) {
226
228
  #endif
227
229
  }
228
230
 
231
+ NODE_METHOD(Statement::JS_explainQueryPlan) {
232
+ Statement* stmt = Unwrap<Statement>(info.This());
233
+ REQUIRE_STATEMENT_RETURNS_DATA();
234
+ sqlite3_stmt* handle = stmt->handle;
235
+ Database* db = stmt->db;
236
+ REQUIRE_DATABASE_OPEN(db->GetState());
237
+ REQUIRE_DATABASE_NOT_BUSY(db->GetState());
238
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
239
+
240
+ // Binding is OPTIONAL: bind if params provided, skip if not
241
+ const bool pre_bound = stmt->bound;
242
+ bool did_bind = false;
243
+ if (!pre_bound && info.Length() > 0) {
244
+ STATEMENT_BIND(handle);
245
+ did_bind = true;
246
+ } else if (pre_bound && info.Length() > 0) {
247
+ return ThrowTypeError("This statement already has bound parameters");
248
+ }
249
+
250
+ db->GetState()->busy = true;
251
+ UseIsolate;
252
+ if (db->Log(isolate, handle)) {
253
+ db->GetState()->busy = false;
254
+ if (did_bind) { sqlite3_clear_bindings(handle); }
255
+ db->ThrowDatabaseError();
256
+ return;
257
+ }
258
+
259
+ UseContext;
260
+ const bool safe_ints = stmt->safe_ints;
261
+ const char mode = stmt->mode;
262
+
263
+ #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127
264
+ bool js_error = false;
265
+ uint32_t row_count = 0;
266
+ v8::Local<v8::Array> result = v8::Array::New(isolate, 0);
267
+
268
+ while (sqlite3_step(handle) == SQLITE_ROW) {
269
+ if (row_count == 0xffffffff) { ThrowRangeError("Array overflow (too many rows returned)"); js_error = true; break; }
270
+ result->Set(ctx, row_count++, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode)).FromJust();
271
+ }
272
+
273
+ if (sqlite3_reset(handle) == SQLITE_OK && !js_error) {
274
+ db->GetState()->busy = false;
275
+ if (did_bind) { sqlite3_clear_bindings(handle); }
276
+ info.GetReturnValue().Set(result);
277
+ return;
278
+ }
279
+ if (js_error) db->GetState()->was_js_error = true;
280
+ db->GetState()->busy = false;
281
+ if (did_bind) { sqlite3_clear_bindings(handle); }
282
+ db->ThrowDatabaseError();
283
+ #else
284
+ v8::LocalVector<v8::Value> rows(isolate);
285
+ rows.reserve(8);
286
+
287
+ if (mode == Data::FLAT) {
288
+ RowBuilder rowBuilder(isolate, handle, safe_ints);
289
+ while (sqlite3_step(handle) == SQLITE_ROW) {
290
+ rows.emplace_back(rowBuilder.GetRowJS());
291
+ }
292
+ } else {
293
+ while (sqlite3_step(handle) == SQLITE_ROW) {
294
+ rows.emplace_back(Data::GetRowJS(isolate, ctx, handle, safe_ints, mode));
295
+ }
296
+ }
297
+
298
+ if (sqlite3_reset(handle) == SQLITE_OK) {
299
+ if (rows.size() > 0xffffffff) {
300
+ ThrowRangeError("Array overflow (too many rows returned)");
301
+ db->GetState()->was_js_error = true;
302
+ } else {
303
+ db->GetState()->busy = false;
304
+ if (did_bind) { sqlite3_clear_bindings(handle); }
305
+ info.GetReturnValue().Set(v8::Array::New(isolate, rows.data(), rows.size()));
306
+ return;
307
+ }
308
+ }
309
+ db->GetState()->busy = false;
310
+ if (did_bind) { sqlite3_clear_bindings(handle); }
311
+ db->ThrowDatabaseError();
312
+ #endif
313
+ }
314
+
229
315
  NODE_METHOD(Statement::JS_iterate) {
230
316
  UseAddon;
231
317
  UseIsolate;
@@ -450,6 +536,15 @@ NODE_METHOD(Statement::JS_scanStatusV2) {
450
536
  }
451
537
  }
452
538
 
539
+ NODE_METHOD(Statement::JS_scanStatusReset) {
540
+ Statement* stmt = Unwrap<Statement>(info.This());
541
+ REQUIRE_DATABASE_OPEN(stmt->db->GetState());
542
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
543
+
544
+ sqlite3_stmt_scanstatus_reset(stmt->handle);
545
+ info.GetReturnValue().Set(info.This());
546
+ }
547
+
453
548
  NODE_GETTER(Statement::JS_busy) {
454
549
  Statement* stmt = Unwrap<Statement>(info.This());
455
550
  info.GetReturnValue().Set(stmt->alive && stmt->locked);
@@ -44,6 +44,8 @@ private:
44
44
  static NODE_METHOD(JS_safeIntegers);
45
45
  static NODE_METHOD(JS_columns);
46
46
  static NODE_METHOD(JS_scanStatusV2);
47
+ static NODE_METHOD(JS_scanStatusReset);
48
+ static NODE_METHOD(JS_explainQueryPlan);
47
49
  static NODE_GETTER(JS_busy);
48
50
 
49
51
  Database* const db;