@rocicorp/zero-sqlite3 1.0.12 → 1.0.14
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 +1 -0
- package/package.json +2 -2
- package/src/objects/statement.cpp +85 -0
- package/src/objects/statement.hpp +1 -0
package/lib/index.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ declare namespace BetterSqlite3 {
|
|
|
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
46
|
scanStatusReset(): this;
|
|
47
|
+
explainQueryPlan(...params: BindParameters | []): Result[];
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
interface ColumnDefinition {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rocicorp/zero-sqlite3",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "better-sqlite3 on bedrock",
|
|
5
5
|
"homepage": "https://github.com/rocicorp/zero-sqlite3",
|
|
6
6
|
"author": "Rocicorp",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"sqlite3": "^5.1.6"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
|
-
"install": "prebuild-install || node-gyp rebuild --release",
|
|
47
|
+
"install": "prebuild-install || node -e \"require('fs').existsSync('build/Release/better_sqlite3.node')||process.exit(1)\" || node-gyp rebuild --release",
|
|
48
48
|
"build-release": "node-gyp rebuild --release",
|
|
49
49
|
"build-debug": "node-gyp rebuild --debug",
|
|
50
50
|
"test": "mocha --exit --slow=75 --timeout=5000",
|
|
@@ -66,6 +66,7 @@ INIT(Statement::Init) {
|
|
|
66
66
|
SetPrototypeMethod(isolate, data, t, "columns", JS_columns);
|
|
67
67
|
SetPrototypeMethod(isolate, data, t, "scanStatusV2", JS_scanStatusV2);
|
|
68
68
|
SetPrototypeMethod(isolate, data, t, "scanStatusReset", JS_scanStatusReset);
|
|
69
|
+
SetPrototypeMethod(isolate, data, t, "explainQueryPlan", JS_explainQueryPlan);
|
|
69
70
|
SetPrototypeGetter(isolate, data, t, "busy", JS_busy);
|
|
70
71
|
return t->GetFunction(OnlyContext).ToLocalChecked();
|
|
71
72
|
}
|
|
@@ -227,6 +228,90 @@ NODE_METHOD(Statement::JS_all) {
|
|
|
227
228
|
#endif
|
|
228
229
|
}
|
|
229
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
|
+
|
|
230
315
|
NODE_METHOD(Statement::JS_iterate) {
|
|
231
316
|
UseAddon;
|
|
232
317
|
UseIsolate;
|