indexeddbshim 17.0.0 → 17.1.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/README.md +62 -0
- package/badges/licenses-badge-dev.svg +1 -1
- package/badges/licenses-badge.svg +1 -1
- package/dist/CFG.d.ts +1 -0
- package/dist/CFG.d.ts.map +1 -1
- package/dist/IDBCursor.d.ts +9 -2
- package/dist/IDBCursor.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBIndex.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts +21 -0
- package/dist/IDBTransaction.d.ts.map +1 -1
- package/dist/Key.d.ts.map +1 -1
- package/dist/indexeddbshim-Key.js +25 -6
- package/dist/indexeddbshim-Key.js.map +1 -1
- package/dist/indexeddbshim-Key.min.js +2 -2
- package/dist/indexeddbshim-Key.min.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +1402 -818
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +467 -298
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +4 -4
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +1402 -818
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +467 -298
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +4 -4
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +471 -295
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +4 -4
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/node-UnicodeIdentifiers.d.ts.map +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/nodeSQLiteDatabase.d.ts +65 -0
- package/dist/nodeSQLiteDatabase.d.ts.map +1 -0
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/dist/util.d.ts +5 -0
- package/dist/util.d.ts.map +1 -1
- package/package.json +17 -13
- package/src/CFG.js +3 -0
- package/src/IDBCursor.js +136 -86
- package/src/IDBFactory.js +10 -6
- package/src/IDBIndex.js +1 -2
- package/src/IDBTransaction.js +32 -2
- package/src/Key.js +10 -2
- package/src/node-UnicodeIdentifiers.js +5 -1
- package/src/node.js +5 -1
- package/src/nodeSQLiteDatabase.js +174 -0
- package/src/nodeWebSQL.js +1 -3
- package/src/util.js +62 -3
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
/*! indexeddbshim - v17.
|
|
1
|
+
/*! indexeddbshim - v17.1.0 - 8/6/2026 */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
var fs$1 = require('node:fs');
|
|
6
6
|
var path = require('path');
|
|
7
7
|
var require$$0 = require('fs');
|
|
8
|
-
var require$$2 = require('
|
|
9
|
-
var require$$0$1 = require('util');
|
|
8
|
+
var require$$2 = require('util');
|
|
10
9
|
|
|
11
10
|
function _typeof(obj) {
|
|
12
11
|
"@babel/helpers - typeof";
|
|
@@ -980,6 +979,7 @@ function setPrototypeOfCustomEvent() {
|
|
|
980
979
|
* sqlBusyTimeout: number,
|
|
981
980
|
* sqlTrace: () => void,
|
|
982
981
|
* sqlProfile: () => void,
|
|
982
|
+
* escapeNULForSQLiteStatements: boolean,
|
|
983
983
|
* createIndexes: boolean
|
|
984
984
|
* }} ConfigValues
|
|
985
985
|
*/
|
|
@@ -1134,8 +1134,8 @@ val => {
|
|
|
1134
1134
|
// Callback not used by default
|
|
1135
1135
|
'sqlProfile',
|
|
1136
1136
|
// Callback not used by default
|
|
1137
|
-
|
|
1138
|
-
'createIndexes'].forEach(prop => {
|
|
1137
|
+
// Defaults to true except in Node builds where we can preserve literal NUL with better-sqlite3
|
|
1138
|
+
'escapeNULForSQLiteStatements', 'createIndexes'].forEach(prop => {
|
|
1139
1139
|
/** @type {(val: any) => void} */
|
|
1140
1140
|
let validator;
|
|
1141
1141
|
if (Array.isArray(prop)) {
|
|
@@ -1215,7 +1215,8 @@ function escapeNameForSQLiteIdentifier(arg) {
|
|
|
1215
1215
|
* @returns {string}
|
|
1216
1216
|
*/
|
|
1217
1217
|
function escapeSQLiteStatement(arg) {
|
|
1218
|
-
|
|
1218
|
+
const escaped = arg.replaceAll('^', '^^');
|
|
1219
|
+
return escapeUnmatchedSurrogates(CFG.escapeNULForSQLiteStatements === false ? escaped : escaped.replaceAll('\0', '^0'));
|
|
1219
1220
|
}
|
|
1220
1221
|
|
|
1221
1222
|
/**
|
|
@@ -1223,7 +1224,11 @@ function escapeSQLiteStatement(arg) {
|
|
|
1223
1224
|
* @returns {string}
|
|
1224
1225
|
*/
|
|
1225
1226
|
function unescapeSQLiteResponse(arg) {
|
|
1226
|
-
|
|
1227
|
+
const unescaped = unescapeUnmatchedSurrogates(arg);
|
|
1228
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
1229
|
+
return unescaped.replaceAll('^^', '^');
|
|
1230
|
+
}
|
|
1231
|
+
return unescaped.replaceAll(/(\^+)0/gu, (_, esc) => {
|
|
1227
1232
|
return esc.length % 2 ? esc.slice(1) + '\0' : _;
|
|
1228
1233
|
}).replaceAll('^^', '^');
|
|
1229
1234
|
}
|
|
@@ -1638,6 +1643,56 @@ function isNullish(v) {
|
|
|
1638
1643
|
return v === null || v === undefined;
|
|
1639
1644
|
}
|
|
1640
1645
|
|
|
1646
|
+
/**
|
|
1647
|
+
* Cursor/request continuation chains can call each other synchronously
|
|
1648
|
+
* (e.g. walking a large prefetched buffer, or advancing many interleaved
|
|
1649
|
+
* cursors in one transaction) which, for large enough record counts, can
|
|
1650
|
+
* exceed the JS engine's call stack ("Maximum call stack size exceeded").
|
|
1651
|
+
*
|
|
1652
|
+
* This can't be fixed by deferring continuations to a microtask/macrotask:
|
|
1653
|
+
* the transaction machinery synchronously checks (once the current call
|
|
1654
|
+
* stack unwinds) whether there are any pending requests left in order to
|
|
1655
|
+
* decide it's safe to commit; deferring a continuation opens a real gap in
|
|
1656
|
+
* which that check runs first and the transaction completes prematurely,
|
|
1657
|
+
* with the deferred continuation then acting on an already-finished
|
|
1658
|
+
* transaction (a hang, since it can never resolve).
|
|
1659
|
+
*
|
|
1660
|
+
* Instead, this implements a true trampoline: the first call starts a
|
|
1661
|
+
* synchronous work queue and drains it in a flat loop; any call made while
|
|
1662
|
+
* already draining (i.e. a continuation triggering another continuation)
|
|
1663
|
+
* is simply appended to that same queue and returns immediately instead of
|
|
1664
|
+
* recursing. This keeps everything synchronous (so no completion-check
|
|
1665
|
+
* race is introduced) while preventing the call stack from growing with
|
|
1666
|
+
* each successive continuation.
|
|
1667
|
+
*/
|
|
1668
|
+
const continuationState = {
|
|
1669
|
+
/** @type {Array<() => void>|null} */
|
|
1670
|
+
queue: null
|
|
1671
|
+
};
|
|
1672
|
+
|
|
1673
|
+
/**
|
|
1674
|
+
* @param {() => void} fn
|
|
1675
|
+
* @returns {void}
|
|
1676
|
+
*/
|
|
1677
|
+
function runContinuationSafely(fn) {
|
|
1678
|
+
if (continuationState.queue) {
|
|
1679
|
+
continuationState.queue.push(fn);
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
const queue = [fn];
|
|
1683
|
+
continuationState.queue = queue;
|
|
1684
|
+
try {
|
|
1685
|
+
while (queue.length) {
|
|
1686
|
+
const next = /** @type {() => void} */queue.shift();
|
|
1687
|
+
next();
|
|
1688
|
+
}
|
|
1689
|
+
} finally {
|
|
1690
|
+
// Ensure a thrown exception can't leave the queue permanently
|
|
1691
|
+
// stuck (which would silently swallow all future continuations).
|
|
1692
|
+
continuationState.queue = null;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1641
1696
|
/**
|
|
1642
1697
|
* @typedef {Error} DebuggingError
|
|
1643
1698
|
*/
|
|
@@ -2313,16 +2368,15 @@ Object.defineProperty(IDBOpenDBRequest, 'prototype', {
|
|
|
2313
2368
|
/* eslint-disable promise/prefer-await-to-callbacks -- Needed for API */
|
|
2314
2369
|
/* eslint-disable promise/catch-or-return, n/callback-return,
|
|
2315
2370
|
promise/always-return -- Not needed */
|
|
2316
|
-
/* eslint-disable unicorn/no-this-assignment -- Clarity */
|
|
2317
2371
|
// Since [immediate](https://github.com/calvinmetcalf/immediate) is
|
|
2318
2372
|
// not doing the trick for our WebSQL transactions (at least in Node),
|
|
2319
2373
|
// we are forced to make the promises run fully synchronously.
|
|
2320
2374
|
|
|
2321
|
-
|
|
2322
|
-
|
|
2375
|
+
/* eslint-disable jsdoc/reject-any-type -- Truly arbitrary */
|
|
2323
2376
|
/**
|
|
2324
2377
|
* @typedef {any} ArbitraryValue
|
|
2325
2378
|
*/
|
|
2379
|
+
/* eslint-enable jsdoc/reject-any-type -- Truly arbitrary */
|
|
2326
2380
|
|
|
2327
2381
|
/**
|
|
2328
2382
|
* @callback Resolve
|
|
@@ -2382,209 +2436,219 @@ const PENDING = 2,
|
|
|
2382
2436
|
REJECTED = 1;
|
|
2383
2437
|
|
|
2384
2438
|
/**
|
|
2385
|
-
*
|
|
2386
|
-
* @param {(
|
|
2387
|
-
* resolve: (value: ArbitraryValue | PromiseLike<ArbitraryValue>) => void,
|
|
2388
|
-
* reject: (reason?: any) => void
|
|
2389
|
-
* ) => void} fn
|
|
2439
|
+
*
|
|
2390
2440
|
*/
|
|
2391
|
-
|
|
2392
|
-
const that = this;
|
|
2393
|
-
// Value, this will be set to either a resolved value or rejected reason
|
|
2394
|
-
that.v = 0;
|
|
2395
|
-
// State of the promise
|
|
2396
|
-
that.s = PENDING;
|
|
2397
|
-
// Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
|
|
2398
|
-
/** @type {Callbacks|null} */
|
|
2399
|
-
that.c = [[], []];
|
|
2441
|
+
class SyncPromise {
|
|
2400
2442
|
/**
|
|
2401
|
-
*
|
|
2402
|
-
* @
|
|
2403
|
-
* @param {0|1} state
|
|
2404
|
-
* @returns {void}
|
|
2443
|
+
* @param {unknown[]|[]} promises
|
|
2444
|
+
* @returns {SyncPromise}
|
|
2405
2445
|
*/
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2446
|
+
static all(promises) {
|
|
2447
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2448
|
+
(resolve, reject) => {
|
|
2449
|
+
let l = promises.length;
|
|
2450
|
+
/** @type {ArbitraryValue[]} */
|
|
2451
|
+
const newPromises = [];
|
|
2452
|
+
if (!l) {
|
|
2453
|
+
resolve(newPromises);
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
promises.forEach((p, i) => {
|
|
2457
|
+
if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
|
|
2458
|
+
addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
|
|
2459
|
+
res => {
|
|
2460
|
+
newPromises[i] = res;
|
|
2461
|
+
--l;
|
|
2462
|
+
if (!l) {
|
|
2463
|
+
resolve(newPromises);
|
|
2464
|
+
}
|
|
2465
|
+
}), reject);
|
|
2466
|
+
} else {
|
|
2467
|
+
newPromises[i] = p;
|
|
2468
|
+
--l;
|
|
2469
|
+
if (!l) {
|
|
2470
|
+
resolve(promises);
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
});
|
|
2414
2474
|
});
|
|
2415
|
-
// Release memory, but if no handlers have been added, as we
|
|
2416
|
-
// assume that we will resolve/reject (truly) synchronously
|
|
2417
|
-
// and thus we avoid flagging checks about whether we've
|
|
2418
|
-
// already resolved/rejected.
|
|
2419
|
-
if (/** @type {Callbacks} */that.c[state].length) {
|
|
2420
|
-
that.c = null;
|
|
2421
|
-
}
|
|
2422
2475
|
}
|
|
2423
2476
|
|
|
2424
|
-
/**
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
}
|
|
2477
|
+
/**
|
|
2478
|
+
* @param {unknown[]|[]} promises
|
|
2479
|
+
* @returns {SyncPromise}
|
|
2480
|
+
*/
|
|
2481
|
+
static race(promises) {
|
|
2482
|
+
let resolved = false;
|
|
2483
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2484
|
+
(resolve, reject) => {
|
|
2485
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
2486
|
+
// eslint-disable-next-line unicorn/no-unused-array-method-return -- Shortcuts
|
|
2487
|
+
promises.some(p => {
|
|
2488
|
+
if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
|
|
2489
|
+
addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
|
|
2490
|
+
res => {
|
|
2491
|
+
if (resolved) {
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
resolve(res);
|
|
2495
|
+
resolved = true;
|
|
2496
|
+
}), reject);
|
|
2497
|
+
return false;
|
|
2498
|
+
}
|
|
2499
|
+
resolve(p);
|
|
2500
|
+
resolved = true;
|
|
2501
|
+
return true;
|
|
2502
|
+
});
|
|
2503
|
+
});
|
|
2431
2504
|
}
|
|
2432
2505
|
|
|
2433
|
-
/**
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
fn(resolve, reject);
|
|
2443
|
-
} catch (err) {
|
|
2444
|
-
reject(err);
|
|
2506
|
+
/**
|
|
2507
|
+
* @param {ArbitraryValue} val
|
|
2508
|
+
* @returns {SyncPromise}
|
|
2509
|
+
*/
|
|
2510
|
+
static resolve(val) {
|
|
2511
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2512
|
+
resolve => {
|
|
2513
|
+
resolve(val);
|
|
2514
|
+
});
|
|
2445
2515
|
}
|
|
2446
|
-
}
|
|
2447
2516
|
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
*/
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
function (resolve, reject) {
|
|
2459
|
-
const rej = typeof errBack === 'function' ? errBack : reject;
|
|
2517
|
+
/**
|
|
2518
|
+
* @param {ArbitraryValue} val
|
|
2519
|
+
* @returns {SyncPromise}
|
|
2520
|
+
*/
|
|
2521
|
+
static reject(val) {
|
|
2522
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2523
|
+
(resolve, reject) => {
|
|
2524
|
+
reject(val);
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2460
2527
|
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
try {
|
|
2464
|
-
resolve(cb ? cb(that.v) : that.v);
|
|
2465
|
-
} catch (e) {
|
|
2466
|
-
rej(e);
|
|
2467
|
-
}
|
|
2468
|
-
}
|
|
2469
|
-
if (that.s === FULFILLED) {
|
|
2470
|
-
settle();
|
|
2471
|
-
} else if (that.s === REJECTED) {
|
|
2472
|
-
rej(that.v);
|
|
2473
|
-
} else {
|
|
2474
|
-
/** @type {Callbacks} */that.c[FULFILLED].push(settle);
|
|
2475
|
-
/** @type {Callbacks} */
|
|
2476
|
-
that.c[REJECTED].push(rej);
|
|
2477
|
-
}
|
|
2478
|
-
});
|
|
2479
|
-
};
|
|
2528
|
+
// Value, this will be set to either a resolved value or rejected reason
|
|
2529
|
+
v = 0;
|
|
2480
2530
|
|
|
2481
|
-
/**
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2531
|
+
/**
|
|
2532
|
+
* @param {(
|
|
2533
|
+
* resolve: (value: ArbitraryValue | PromiseLike<ArbitraryValue>) => void,
|
|
2534
|
+
* reject: (reason?: ArbitraryValue) => void
|
|
2535
|
+
* ) => void} fn
|
|
2536
|
+
*/
|
|
2537
|
+
constructor(fn) {
|
|
2538
|
+
// State of the promise
|
|
2539
|
+
this.s = PENDING;
|
|
2540
|
+
// Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
|
|
2541
|
+
/** @type {Callbacks|null} */
|
|
2542
|
+
this.c = [[], []];
|
|
2489
2543
|
/**
|
|
2544
|
+
*
|
|
2545
|
+
* @param {ArbitraryValue} val
|
|
2546
|
+
* @param {0|1} state
|
|
2490
2547
|
* @returns {void}
|
|
2491
2548
|
*/
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
if (that.s === REJECTED) {
|
|
2500
|
-
settle();
|
|
2501
|
-
} else if (that.s === FULFILLED) {
|
|
2502
|
-
resolve(that.v);
|
|
2503
|
-
} else {
|
|
2504
|
-
/** @type {Callbacks} */that.c[REJECTED].push(settle);
|
|
2549
|
+
const transist = (val, state) => {
|
|
2550
|
+
this.v = val;
|
|
2551
|
+
this.s = state;
|
|
2552
|
+
|
|
2553
|
+
// console.log('state', state);
|
|
2505
2554
|
/** @type {Callbacks} */
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2555
|
+
this.c[state].forEach(func => {
|
|
2556
|
+
func(val);
|
|
2557
|
+
});
|
|
2558
|
+
// Release memory, but if no handlers have been added, as we
|
|
2559
|
+
// assume that we will resolve/reject (truly) synchronously
|
|
2560
|
+
// and thus we avoid flagging checks about whether we've
|
|
2561
|
+
// already resolved/rejected.
|
|
2562
|
+
if (/** @type {Callbacks} */this.c[state].length) {
|
|
2563
|
+
this.c = null;
|
|
2564
|
+
}
|
|
2565
|
+
};
|
|
2510
2566
|
|
|
2511
|
-
/**
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2567
|
+
/** @type {Resolve} */
|
|
2568
|
+
const resolve = val => {
|
|
2569
|
+
if (!this.c) ; else if (isPromise(val)) {
|
|
2570
|
+
addReject(val.then(resolve), reject);
|
|
2571
|
+
} else {
|
|
2572
|
+
transist(val, FULFILLED);
|
|
2573
|
+
}
|
|
2574
|
+
};
|
|
2575
|
+
|
|
2576
|
+
/** @type {Reject} */
|
|
2577
|
+
const reject = reason => {
|
|
2578
|
+
if (!this.c) ; else if (isPromise(reason)) {
|
|
2579
|
+
addReject(reason.then(reject), reject);
|
|
2580
|
+
} else {
|
|
2581
|
+
transist(reason, REJECTED);
|
|
2582
|
+
}
|
|
2583
|
+
};
|
|
2584
|
+
try {
|
|
2585
|
+
fn(resolve, reject);
|
|
2586
|
+
} catch (err) {
|
|
2587
|
+
reject(err);
|
|
2524
2588
|
}
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
/* eslint-disable unicorn/no-thenable -- Promise API */
|
|
2592
|
+
/**
|
|
2593
|
+
* @param {((value: ArbitraryValue) => ArbitraryValue)|null|undefined} [cb]
|
|
2594
|
+
* @param {(reason: ArbitraryValue) => PromiseLike<never>} [errBack]
|
|
2595
|
+
* @returns {SyncPromise}
|
|
2596
|
+
*/
|
|
2597
|
+
then(cb, errBack) {
|
|
2598
|
+
/* eslint-enable unicorn/no-thenable -- Promise API */
|
|
2599
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2600
|
+
(resolve, reject) => {
|
|
2601
|
+
const rej = typeof errBack === 'function' ? errBack : reject;
|
|
2602
|
+
|
|
2603
|
+
/** @type {Settle} */
|
|
2604
|
+
const settle = () => {
|
|
2605
|
+
try {
|
|
2606
|
+
resolve(cb ? cb(this.v) : this.v);
|
|
2607
|
+
} catch (e) {
|
|
2608
|
+
rej(e);
|
|
2609
|
+
}
|
|
2610
|
+
};
|
|
2611
|
+
if (this.s === FULFILLED) {
|
|
2612
|
+
settle();
|
|
2613
|
+
} else if (this.s === REJECTED) {
|
|
2614
|
+
rej(this.v);
|
|
2532
2615
|
} else {
|
|
2533
|
-
|
|
2534
|
-
|
|
2616
|
+
/** @type {Callbacks} */this.c[FULFILLED].push(settle);
|
|
2617
|
+
/** @type {Callbacks} */
|
|
2618
|
+
this.c[REJECTED].push(rej);
|
|
2535
2619
|
}
|
|
2536
2620
|
});
|
|
2537
|
-
}
|
|
2538
|
-
};
|
|
2621
|
+
}
|
|
2539
2622
|
|
|
2540
|
-
/**
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2623
|
+
/**
|
|
2624
|
+
* @param {(reason: ArbitraryValue) => PromiseLike<never>|null|undefined} cb
|
|
2625
|
+
* @returns {SyncPromise}
|
|
2626
|
+
*/
|
|
2627
|
+
catch(cb) {
|
|
2628
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2629
|
+
(resolve, reject) => {
|
|
2630
|
+
/**
|
|
2631
|
+
* @returns {void}
|
|
2632
|
+
*/
|
|
2633
|
+
const settle = () => {
|
|
2634
|
+
try {
|
|
2635
|
+
resolve(cb(this.v));
|
|
2636
|
+
} catch (e) {
|
|
2637
|
+
reject(e);
|
|
2638
|
+
}
|
|
2639
|
+
};
|
|
2640
|
+
if (this.s === REJECTED) {
|
|
2641
|
+
settle();
|
|
2642
|
+
} else if (this.s === FULFILLED) {
|
|
2643
|
+
resolve(this.v);
|
|
2644
|
+
} else {
|
|
2645
|
+
/** @type {Callbacks} */this.c[REJECTED].push(settle);
|
|
2646
|
+
/** @type {Callbacks} */
|
|
2647
|
+
this.c[FULFILLED].push(resolve);
|
|
2559
2648
|
}
|
|
2560
|
-
resolve(p);
|
|
2561
|
-
resolved = true;
|
|
2562
|
-
return true;
|
|
2563
2649
|
});
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
/**
|
|
2568
|
-
* @param {ArbitraryValue} val
|
|
2569
|
-
* @returns {SyncPromise}
|
|
2570
|
-
*/
|
|
2571
|
-
SyncPromise.resolve = function (val) {
|
|
2572
|
-
return new SyncPromise(/** @type {ResolveReject} */
|
|
2573
|
-
(resolve, reject) => {
|
|
2574
|
-
resolve(val);
|
|
2575
|
-
});
|
|
2576
|
-
};
|
|
2577
|
-
|
|
2578
|
-
/**
|
|
2579
|
-
* @param {ArbitraryValue} val
|
|
2580
|
-
* @returns {SyncPromise}
|
|
2581
|
-
*/
|
|
2582
|
-
SyncPromise.reject = function (val) {
|
|
2583
|
-
return new SyncPromise(/** @type {ResolveReject} */
|
|
2584
|
-
(resolve, reject) => {
|
|
2585
|
-
reject(val);
|
|
2586
|
-
});
|
|
2587
|
-
};
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2588
2652
|
|
|
2589
2653
|
/**
|
|
2590
2654
|
* Compares two keys.
|
|
@@ -2885,14 +2949,22 @@ const types = {
|
|
|
2885
2949
|
encoded[i] = encodedItem;
|
|
2886
2950
|
}
|
|
2887
2951
|
encoded.push(keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
|
|
2888
|
-
|
|
2952
|
+
let encodedKey = JSON.stringify(encoded);
|
|
2953
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
2954
|
+
encodedKey = encodedKey.replaceAll(String.raw`\u0000`, '\0');
|
|
2955
|
+
}
|
|
2956
|
+
return keyTypeToEncodedChar.array + '-' + encodedKey;
|
|
2889
2957
|
},
|
|
2890
2958
|
/**
|
|
2891
2959
|
* @param {string} key
|
|
2892
2960
|
* @returns {ValueTypeArray}
|
|
2893
2961
|
*/
|
|
2894
2962
|
decode(key) {
|
|
2895
|
-
|
|
2963
|
+
let decodedKey = key.slice(2);
|
|
2964
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
2965
|
+
decodedKey = decodedKey.replaceAll('\0', String.raw`\u0000`);
|
|
2966
|
+
}
|
|
2967
|
+
const decoded = JSON.parse(decodedKey);
|
|
2896
2968
|
decoded.pop(); // remove the extra item
|
|
2897
2969
|
for (let i = 0; i < decoded.length; i++) {
|
|
2898
2970
|
const item = decoded[i];
|
|
@@ -4312,6 +4384,7 @@ const readonlyProperties$3 = ['objectStoreNames', 'mode', 'db', 'error'];
|
|
|
4312
4384
|
* },
|
|
4313
4385
|
* __requestsFinished: boolean,
|
|
4314
4386
|
* __transFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
4387
|
+
* __callTransFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
4315
4388
|
* __transactionEndCallback: () => void,
|
|
4316
4389
|
* __transactionFinished: boolean,
|
|
4317
4390
|
* __completed: boolean,
|
|
@@ -4420,6 +4493,35 @@ IDBTransaction.prototype = EventTargetFactory.createInstance({
|
|
|
4420
4493
|
IDBTransaction.prototype.__transFinishedCb = function (err, cb) {
|
|
4421
4494
|
cb(Boolean(err));
|
|
4422
4495
|
};
|
|
4496
|
+
|
|
4497
|
+
/**
|
|
4498
|
+
* In Node, the real (SQL-commit-capable) `__transFinishedCb` is only
|
|
4499
|
+
* installed once the underlying WebSQL driver's own SQL-queue-idle check
|
|
4500
|
+
* has fired at least once for this transaction (asynchronously, via the
|
|
4501
|
+
* `nonstandardTransCb` passed to `db.transaction`/`.readTransaction`).
|
|
4502
|
+
* Since our own request processing can now finish synchronously (e.g., a
|
|
4503
|
+
* trivial upgrade using a synchronous SQL driver), it is possible to reach
|
|
4504
|
+
* transaction completion here before that has happened, in which case
|
|
4505
|
+
* `__transFinishedCb` is still the non-committing default above. Calling
|
|
4506
|
+
* that default directly would silently skip the actual SQL commit and
|
|
4507
|
+
* leave the underlying WebSQL transaction "running" forever, hanging any
|
|
4508
|
+
* later transaction on that same database connection. So, if the real
|
|
4509
|
+
* callback isn't installed yet, defer and retry until it is.
|
|
4510
|
+
* @this {IDBTransactionFull}
|
|
4511
|
+
* @param {boolean} err
|
|
4512
|
+
* @param {(bool?: boolean) => void} cb
|
|
4513
|
+
* @returns {void}
|
|
4514
|
+
*/
|
|
4515
|
+
IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
|
|
4516
|
+
const me = this;
|
|
4517
|
+
if (me.__transFinishedCb === IDBTransaction.prototype.__transFinishedCb) {
|
|
4518
|
+
setTimeout(() => {
|
|
4519
|
+
me.__callTransFinishedCb(err, cb);
|
|
4520
|
+
}, 0);
|
|
4521
|
+
return;
|
|
4522
|
+
}
|
|
4523
|
+
me.__transFinishedCb(err, cb);
|
|
4524
|
+
};
|
|
4423
4525
|
/**
|
|
4424
4526
|
* @this {IDBTransactionFull}
|
|
4425
4527
|
* @returns {void}
|
|
@@ -4479,7 +4581,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
4479
4581
|
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after success).'));
|
|
4480
4582
|
return;
|
|
4481
4583
|
}
|
|
4482
|
-
executeNextRequest
|
|
4584
|
+
runContinuationSafely(executeNextRequest);
|
|
4483
4585
|
}
|
|
4484
4586
|
|
|
4485
4587
|
/**
|
|
@@ -4551,7 +4653,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
4551
4653
|
try {
|
|
4552
4654
|
q = me.__requests[i];
|
|
4553
4655
|
if (!q.req) {
|
|
4554
|
-
q.op(tx, q.args, executeNextRequest, error);
|
|
4656
|
+
q.op(tx, q.args, () => runContinuationSafely(executeNextRequest), error);
|
|
4555
4657
|
return;
|
|
4556
4658
|
}
|
|
4557
4659
|
if (q.req.__done) {
|
|
@@ -6925,7 +7027,7 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
6925
7027
|
reject(err);
|
|
6926
7028
|
});
|
|
6927
7029
|
}));
|
|
6928
|
-
SyncPromise.all(indexCreations).then(finish
|
|
7030
|
+
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: any) => PromiseLike<never>} */
|
|
6929
7031
|
error).catch(err => {
|
|
6930
7032
|
console.log('Index rename error');
|
|
6931
7033
|
throw err;
|
|
@@ -9070,7 +9172,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
9070
9172
|
/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
|
|
9071
9173
|
req.__result.__versionTransaction = null;
|
|
9072
9174
|
sysdbFinishedCb(systx, false, function () {
|
|
9073
|
-
req.transaction.
|
|
9175
|
+
req.transaction.__callTransFinishedCb(false, function () {
|
|
9074
9176
|
ev.complete();
|
|
9075
9177
|
req.__transaction = null;
|
|
9076
9178
|
});
|
|
@@ -9181,6 +9283,13 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
9181
9283
|
function openDB(oldVersion) {
|
|
9182
9284
|
/** @type {DatabaseFull} */
|
|
9183
9285
|
let db;
|
|
9286
|
+
if (version === undefined) {
|
|
9287
|
+
// Resolve before use as a cache key below, or a `open(name)` call
|
|
9288
|
+
// (no explicit version) would cache/look up under `undefined`
|
|
9289
|
+
// instead of the actual version, causing a second, separate
|
|
9290
|
+
// connection to be opened for the same database on reopen.
|
|
9291
|
+
version = oldVersion || 1;
|
|
9292
|
+
}
|
|
9184
9293
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
9185
9294
|
db = websqlDBCache[name][version];
|
|
9186
9295
|
} else {
|
|
@@ -9192,9 +9301,6 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
9192
9301
|
websqlDBCache[name][version] = db;
|
|
9193
9302
|
}
|
|
9194
9303
|
}
|
|
9195
|
-
if (version === undefined) {
|
|
9196
|
-
version = oldVersion || 1;
|
|
9197
|
-
}
|
|
9198
9304
|
if (oldVersion > version) {
|
|
9199
9305
|
const err = createDOMException('VersionError', 'An attempt was made to open a database using a lower version than the existing version.', version);
|
|
9200
9306
|
if (useDatabaseCache) {
|
|
@@ -9363,7 +9469,6 @@ IDBFactory.prototype.deleteDatabase = function (name) {
|
|
|
9363
9469
|
} = data.rows.item(0));
|
|
9364
9470
|
const openConnections = me.__connections[name] || [];
|
|
9365
9471
|
triggerAnyVersionChangeAndBlockedEvents(openConnections, req, version, null).then(function () {
|
|
9366
|
-
// eslint-disable-line promise/catch-or-return -- Sync promise
|
|
9367
9472
|
// Since we need two databases which can't be in a single transaction, we
|
|
9368
9473
|
// do this deleting from `dbVersions` first since the `__sys__` deleting
|
|
9369
9474
|
// only impacts file memory whereas this one is critical for avoiding it
|
|
@@ -9392,7 +9497,7 @@ IDBFactory.prototype.deleteDatabase = function (name) {
|
|
|
9392
9497
|
});
|
|
9393
9498
|
return undefined;
|
|
9394
9499
|
// @ts-expect-error It's ok
|
|
9395
|
-
}
|
|
9500
|
+
}).catch(dbError);
|
|
9396
9501
|
return undefined;
|
|
9397
9502
|
}, dbError);
|
|
9398
9503
|
});
|
|
@@ -9574,6 +9679,9 @@ const shimIndexedDB = IDBFactory.__createInstance();
|
|
|
9574
9679
|
* __unique: boolean,
|
|
9575
9680
|
* __sqlDirection: "DESC"|"ASC",
|
|
9576
9681
|
* __matchedKeys: {[key: string]: true},
|
|
9682
|
+
* __continuationKey: import('./Key.js').Key|undefined,
|
|
9683
|
+
* __continuationPrimaryKey: import('./Key.js').Key|undefined,
|
|
9684
|
+
* __multiEntryExhausted: boolean,
|
|
9577
9685
|
* __invalidateCache: () => void
|
|
9578
9686
|
* }} IDBCursorFull
|
|
9579
9687
|
*/
|
|
@@ -9647,6 +9755,9 @@ IDBCursor.__super = function IDBCursor(query, direction, store, source, keyColum
|
|
|
9647
9755
|
this.__valueDecoder = this.__keyOnly ? Key : Sca;
|
|
9648
9756
|
this.__count = count;
|
|
9649
9757
|
this.__prefetchedIndex = -1;
|
|
9758
|
+
this.__continuationKey = undefined;
|
|
9759
|
+
this.__continuationPrimaryKey = undefined;
|
|
9760
|
+
this.__multiEntryExhausted = false;
|
|
9650
9761
|
this.__multiEntryIndex = this.__indexSource ? 'multiEntry' in source && source.multiEntry : false;
|
|
9651
9762
|
this.__unique = this.direction.includes('unique');
|
|
9652
9763
|
this.__sqlDirection = ['prev', 'prevunique'].includes(this.direction) ? 'DESC' : 'ASC';
|
|
@@ -9799,73 +9910,96 @@ const leftBracketRegex = /\[/gu;
|
|
|
9799
9910
|
* @param {SQLTransaction} tx
|
|
9800
9911
|
* @param {KeySuccess} success
|
|
9801
9912
|
* @param {FindError} error
|
|
9802
|
-
* @param {Integer
|
|
9913
|
+
* @param {Integer} [recordsToLoad]
|
|
9803
9914
|
* @this {IDBCursorFull}
|
|
9804
9915
|
* @returns {void}
|
|
9805
9916
|
*/
|
|
9806
|
-
IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad) {
|
|
9917
|
+
IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad = 1) {
|
|
9807
9918
|
const me = this;
|
|
9808
|
-
if (me.
|
|
9919
|
+
if (me.__multiEntryExhausted) {
|
|
9809
9920
|
if (CFG.DEBUG) {
|
|
9810
|
-
console.log('Reached end of multiEntry cursor');
|
|
9921
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (already exhausted)');
|
|
9811
9922
|
}
|
|
9812
9923
|
success(undefined, undefined, undefined);
|
|
9813
9924
|
return;
|
|
9814
9925
|
}
|
|
9815
9926
|
const quotedKeyColumnName = sqlQuote(me.__keyColumnName);
|
|
9816
|
-
const
|
|
9817
|
-
/** @type {string[]} */
|
|
9818
|
-
const sqlValues = [];
|
|
9819
|
-
sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
|
|
9820
|
-
if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
|
|
9821
|
-
if (me.__range.upper.indexOf(me.__range.lower) === 0) {
|
|
9822
|
-
sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
|
|
9823
|
-
sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
|
|
9824
|
-
}
|
|
9825
|
-
}
|
|
9927
|
+
const quotedKey = sqlQuote('key');
|
|
9826
9928
|
|
|
9827
9929
|
// Determine the ORDER BY direction based on the cursor.
|
|
9828
9930
|
const direction = me.__sqlDirection;
|
|
9829
9931
|
const op = direction === 'ASC' ? '>' : '<';
|
|
9830
|
-
const quotedKey = sqlQuote('key');
|
|
9831
|
-
if (primaryKey !== undefined) {
|
|
9832
|
-
sql.push('AND', quotedKey, op + '= ?');
|
|
9833
|
-
// Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
|
|
9834
|
-
sqlValues.push(/** @type {string} */encode$1(primaryKey));
|
|
9835
|
-
}
|
|
9836
|
-
if (key !== undefined) {
|
|
9837
|
-
sql.push('AND', quotedKeyColumnName, op + '= ?');
|
|
9838
|
-
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
9839
|
-
sqlValues.push(/** @type {string} */encode$1(key));
|
|
9840
|
-
} else if (me.__key !== undefined) {
|
|
9841
|
-
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
9842
|
-
// Key.convertValueToKey(me.__key); // Already checked when entered
|
|
9843
|
-
sqlValues.push(/** @type {string} */encode$1(me.__key));
|
|
9844
|
-
}
|
|
9845
|
-
if (!me.__count) {
|
|
9846
|
-
// 1. Sort by key
|
|
9847
|
-
sql.push('ORDER BY', quotedKeyColumnName, direction);
|
|
9848
9932
|
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9933
|
+
/**
|
|
9934
|
+
* Runs (and, if a batch of underlying rows produces no matching
|
|
9935
|
+
* multi-entry values, repeatedly re-runs) the query for the next batch
|
|
9936
|
+
* of underlying rows, advancing `me.__continuationKey`/
|
|
9937
|
+
* `me.__continuationPrimaryKey` (tracking the last *physical* row
|
|
9938
|
+
* scanned) each time, until either some matches are found or the
|
|
9939
|
+
* underlying table is exhausted.
|
|
9940
|
+
* @returns {void}
|
|
9941
|
+
*/
|
|
9942
|
+
function runQuery() {
|
|
9943
|
+
const sql = ['SELECT * FROM', escapeStoreNameForSQL(me.__store.__currentName)];
|
|
9944
|
+
/** @type {string[]} */
|
|
9945
|
+
const sqlValues = [];
|
|
9946
|
+
sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
|
|
9947
|
+
if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
|
|
9948
|
+
if (me.__range.upper.indexOf(me.__range.lower) === 0) {
|
|
9949
|
+
sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
|
|
9950
|
+
sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
|
|
9951
|
+
}
|
|
9952
|
+
}
|
|
9953
|
+
if (primaryKey !== undefined) {
|
|
9954
|
+
sql.push('AND', quotedKey, op + '= ?');
|
|
9955
|
+
// Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
|
|
9956
|
+
sqlValues.push(/** @type {string} */encode$1(primaryKey));
|
|
9853
9957
|
}
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9958
|
+
if (key !== undefined) {
|
|
9959
|
+
sql.push('AND', quotedKeyColumnName, op + '= ?');
|
|
9960
|
+
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
9961
|
+
sqlValues.push(/** @type {string} */encode$1(key));
|
|
9962
|
+
} else if (me.__continuationKey !== undefined) {
|
|
9963
|
+
// Resume from the last underlying (physical) row we scanned, not
|
|
9964
|
+
// from the last *matching* multi-entry value (which lives in a
|
|
9965
|
+
// different key-space than the raw index column and cannot be
|
|
9966
|
+
// reliably compared against it, e.g. for array index keys).
|
|
9967
|
+
sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
|
|
9968
|
+
const encodedContinuationKey = /** @type {string} */
|
|
9969
|
+
encode$1(me.__continuationKey, true);
|
|
9970
|
+
sqlValues.push(encodedContinuationKey, encodedContinuationKey, /** @type {string} */encode$1(me.__continuationPrimaryKey));
|
|
9971
|
+
}
|
|
9972
|
+
if (!me.__count) {
|
|
9973
|
+
// 1. Sort by key
|
|
9974
|
+
sql.push('ORDER BY', quotedKeyColumnName, direction);
|
|
9975
|
+
|
|
9976
|
+
// 2. Sort by primaryKey (if defined and not unique)
|
|
9977
|
+
if (!me.__unique && me.__keyColumnName !== 'key') {
|
|
9978
|
+
// Avoid adding 'key' twice
|
|
9979
|
+
sql.push(',', sqlQuote('key'), direction);
|
|
9980
|
+
}
|
|
9981
|
+
|
|
9982
|
+
// 3. Sort by position (if defined)
|
|
9983
|
+
|
|
9984
|
+
if (!me.__unique && me.__indexSource) {
|
|
9985
|
+
// 4. Sort by object store position (if defined and not unique)
|
|
9986
|
+
sql.push(',', sqlQuote(me.__valueColumnName), direction);
|
|
9987
|
+
}
|
|
9988
|
+
sql.push('LIMIT', String(recordsToLoad));
|
|
9989
|
+
}
|
|
9990
|
+
const sqlStr = sql.join(' ');
|
|
9991
|
+
if (CFG.DEBUG) {
|
|
9992
|
+
console.log('[multiEntry] query', sqlStr, sqlValues);
|
|
9860
9993
|
}
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9994
|
+
tx.executeSql(sqlStr, sqlValues, function (tx, data) {
|
|
9995
|
+
if (data.rows.length === 0) {
|
|
9996
|
+
me.__multiEntryExhausted = true;
|
|
9997
|
+
if (CFG.DEBUG) {
|
|
9998
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (no more rows)');
|
|
9999
|
+
}
|
|
10000
|
+
success(undefined, undefined, undefined);
|
|
10001
|
+
return;
|
|
10002
|
+
}
|
|
9869
10003
|
if (me.__count) {
|
|
9870
10004
|
// Avoid caching and other processing below
|
|
9871
10005
|
let ct = 0;
|
|
@@ -9878,6 +10012,16 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
|
|
|
9878
10012
|
success(undefined, ct, undefined);
|
|
9879
10013
|
return;
|
|
9880
10014
|
}
|
|
10015
|
+
|
|
10016
|
+
// Track how far we've physically scanned, regardless of whether
|
|
10017
|
+
// this batch produced any matches, so the next batch (if any)
|
|
10018
|
+
// resumes after this one instead of re-scanning or stopping early.
|
|
10019
|
+
const lastRawRow = data.rows.item(data.rows.length - 1);
|
|
10020
|
+
me.__continuationKey = decode$1(lastRawRow[me.__keyColumnName], true);
|
|
10021
|
+
me.__continuationPrimaryKey = decode$1(lastRawRow.key);
|
|
10022
|
+
if (data.rows.length < recordsToLoad) {
|
|
10023
|
+
me.__multiEntryExhausted = true;
|
|
10024
|
+
}
|
|
9881
10025
|
const rows = [];
|
|
9882
10026
|
for (let i = 0; i < data.rows.length; i++) {
|
|
9883
10027
|
const rowItem = data.rows.item(i);
|
|
@@ -9897,6 +10041,20 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
|
|
|
9897
10041
|
rows.push(clone);
|
|
9898
10042
|
}
|
|
9899
10043
|
}
|
|
10044
|
+
if (rows.length === 0) {
|
|
10045
|
+
if (me.__multiEntryExhausted) {
|
|
10046
|
+
if (CFG.DEBUG) {
|
|
10047
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (last batch had no matches)');
|
|
10048
|
+
}
|
|
10049
|
+
success(undefined, undefined, undefined);
|
|
10050
|
+
return;
|
|
10051
|
+
}
|
|
10052
|
+
if (CFG.DEBUG) {
|
|
10053
|
+
console.log('[multiEntry] batch had no matches; fetching next batch');
|
|
10054
|
+
}
|
|
10055
|
+
runQuery();
|
|
10056
|
+
return;
|
|
10057
|
+
}
|
|
9900
10058
|
const reverse = me.direction.indexOf('prev') === 0;
|
|
9901
10059
|
rows.sort(function (a, b) {
|
|
9902
10060
|
if (a.matchingKey.replaceAll(leftBracketRegex, 'z') < b.matchingKey.replaceAll(leftBracketRegex, 'z')) {
|
|
@@ -9913,47 +10071,31 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
|
|
|
9913
10071
|
}
|
|
9914
10072
|
return 0;
|
|
9915
10073
|
});
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
return this.data[index];
|
|
9927
|
-
}
|
|
9928
|
-
};
|
|
9929
|
-
if (CFG.DEBUG) {
|
|
9930
|
-
console.log('Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
9931
|
-
}
|
|
9932
|
-
me.__decode(rows[0], success);
|
|
9933
|
-
} else if (rows.length === 1) {
|
|
9934
|
-
if (CFG.DEBUG) {
|
|
9935
|
-
console.log('Reached end of multiEntry cursor');
|
|
9936
|
-
}
|
|
9937
|
-
me.__decode(rows[0], success);
|
|
9938
|
-
} else {
|
|
9939
|
-
if (CFG.DEBUG) {
|
|
9940
|
-
console.log('Reached end of multiEntry cursor');
|
|
10074
|
+
me.__prefetchedIndex = 0;
|
|
10075
|
+
me.__prefetchedData = {
|
|
10076
|
+
data: rows,
|
|
10077
|
+
length: rows.length,
|
|
10078
|
+
/**
|
|
10079
|
+
* @param {Integer} index
|
|
10080
|
+
* @returns {RowItemNonNull}
|
|
10081
|
+
*/
|
|
10082
|
+
item(index) {
|
|
10083
|
+
return this.data[index];
|
|
9941
10084
|
}
|
|
9942
|
-
|
|
10085
|
+
};
|
|
10086
|
+
if (CFG.DEBUG) {
|
|
10087
|
+
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
9943
10088
|
}
|
|
9944
|
-
|
|
10089
|
+
me.__decode(rows[0], success);
|
|
10090
|
+
}, function (tx, err) {
|
|
9945
10091
|
if (CFG.DEBUG) {
|
|
9946
|
-
console.log('
|
|
10092
|
+
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
9947
10093
|
}
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
}
|
|
9954
|
-
error(err);
|
|
9955
|
-
return false;
|
|
9956
|
-
});
|
|
10094
|
+
error(err);
|
|
10095
|
+
return false;
|
|
10096
|
+
});
|
|
10097
|
+
}
|
|
10098
|
+
runQuery();
|
|
9957
10099
|
};
|
|
9958
10100
|
|
|
9959
10101
|
/**
|
|
@@ -10062,6 +10204,7 @@ IDBCursor.prototype.__sourceOrEffectiveObjStoreDeleted = function () {
|
|
|
10062
10204
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
10063
10205
|
// @ts-expect-error Why is this not being found?
|
|
10064
10206
|
this.__prefetchedData = null;
|
|
10207
|
+
this.__multiEntryExhausted = false;
|
|
10065
10208
|
};
|
|
10066
10209
|
|
|
10067
10210
|
/**
|
|
@@ -10117,8 +10260,8 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
|
|
|
10117
10260
|
me.__advanceCount--;
|
|
10118
10261
|
me.__key = k;
|
|
10119
10262
|
me.__continue(undefined, true);
|
|
10120
|
-
|
|
10121
|
-
|
|
10263
|
+
// We don't call success yet but do need to advance the transaction queue
|
|
10264
|
+
runContinuationSafely(/** @type {() => void} */executeNextRequest);
|
|
10122
10265
|
return;
|
|
10123
10266
|
}
|
|
10124
10267
|
me.__advanceCount = undefined;
|
|
@@ -10140,11 +10283,11 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
|
|
|
10140
10283
|
return;
|
|
10141
10284
|
}
|
|
10142
10285
|
// @ts-expect-error Todo: Our bug to fix
|
|
10143
|
-
cursorContinue(tx, args, success, error);
|
|
10286
|
+
runContinuationSafely(() => cursorContinue(tx, args, success, error));
|
|
10144
10287
|
}
|
|
10145
10288
|
if (me.__unique && !me.__multiEntryIndex && encKey === encode$1(me.key, me.__multiEntryIndex)) {
|
|
10146
10289
|
// @ts-expect-error Todo: Our bug to fix
|
|
10147
|
-
cursorContinue(tx, args, success, error);
|
|
10290
|
+
runContinuationSafely(() => cursorContinue(tx, args, success, error));
|
|
10148
10291
|
return;
|
|
10149
10292
|
}
|
|
10150
10293
|
checkKey();
|
|
@@ -10747,21 +10890,21 @@ function requireNextTick() {
|
|
|
10747
10890
|
return nextTick;
|
|
10748
10891
|
}
|
|
10749
10892
|
|
|
10750
|
-
var queueMicrotask = {};
|
|
10893
|
+
var queueMicrotask$1 = {};
|
|
10751
10894
|
|
|
10752
10895
|
var hasRequiredQueueMicrotask;
|
|
10753
10896
|
function requireQueueMicrotask() {
|
|
10754
|
-
if (hasRequiredQueueMicrotask) return queueMicrotask;
|
|
10897
|
+
if (hasRequiredQueueMicrotask) return queueMicrotask$1;
|
|
10755
10898
|
hasRequiredQueueMicrotask = 1;
|
|
10756
|
-
queueMicrotask.test = function () {
|
|
10899
|
+
queueMicrotask$1.test = function () {
|
|
10757
10900
|
return typeof commonjsGlobal.queueMicrotask === 'function';
|
|
10758
10901
|
};
|
|
10759
|
-
queueMicrotask.install = function (func) {
|
|
10902
|
+
queueMicrotask$1.install = function (func) {
|
|
10760
10903
|
return function () {
|
|
10761
10904
|
commonjsGlobal.queueMicrotask(func);
|
|
10762
10905
|
};
|
|
10763
10906
|
};
|
|
10764
|
-
return queueMicrotask;
|
|
10907
|
+
return queueMicrotask$1;
|
|
10765
10908
|
}
|
|
10766
10909
|
|
|
10767
10910
|
var mutation = {};
|
|
@@ -10860,11 +11003,11 @@ function requireTimeout() {
|
|
|
10860
11003
|
return timeout;
|
|
10861
11004
|
}
|
|
10862
11005
|
|
|
10863
|
-
var lib;
|
|
10864
|
-
var hasRequiredLib;
|
|
10865
|
-
function requireLib() {
|
|
10866
|
-
if (hasRequiredLib) return lib;
|
|
10867
|
-
hasRequiredLib = 1;
|
|
11006
|
+
var lib$1;
|
|
11007
|
+
var hasRequiredLib$1;
|
|
11008
|
+
function requireLib$1() {
|
|
11009
|
+
if (hasRequiredLib$1) return lib$1;
|
|
11010
|
+
hasRequiredLib$1 = 1;
|
|
10868
11011
|
var types = [requireNextTick(), requireQueueMicrotask(), requireMutation(), requireMessageChannel(), requireStateChange(), requireTimeout()];
|
|
10869
11012
|
var draining;
|
|
10870
11013
|
var currentQueue;
|
|
@@ -10939,7 +11082,7 @@ function requireLib() {
|
|
|
10939
11082
|
return fun.apply(null, array);
|
|
10940
11083
|
}
|
|
10941
11084
|
};
|
|
10942
|
-
lib = immediate;
|
|
11085
|
+
lib$1 = immediate;
|
|
10943
11086
|
function immediate(task) {
|
|
10944
11087
|
var args = new Array(arguments.length - 1);
|
|
10945
11088
|
if (arguments.length > 1) {
|
|
@@ -10953,11 +11096,11 @@ function requireLib() {
|
|
|
10953
11096
|
scheduleDrain();
|
|
10954
11097
|
}
|
|
10955
11098
|
}
|
|
10956
|
-
return lib;
|
|
11099
|
+
return lib$1;
|
|
10957
11100
|
}
|
|
10958
11101
|
|
|
10959
|
-
var libExports = requireLib();
|
|
10960
|
-
var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports);
|
|
11102
|
+
var libExports$1 = requireLib$1();
|
|
11103
|
+
var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports$1);
|
|
10961
11104
|
|
|
10962
11105
|
var tinyQueue;
|
|
10963
11106
|
var hasRequiredTinyQueue;
|
|
@@ -11314,584 +11457,1026 @@ function customOpenDatabase(SQLiteDatabase, opts) {
|
|
|
11314
11457
|
return (...args) => openDatabase(args);
|
|
11315
11458
|
}
|
|
11316
11459
|
|
|
11317
|
-
var
|
|
11460
|
+
var lib = {exports: {}};
|
|
11318
11461
|
|
|
11319
|
-
|
|
11320
|
-
|
|
11462
|
+
var util = {};
|
|
11463
|
+
|
|
11464
|
+
var hasRequiredUtil;
|
|
11465
|
+
function requireUtil() {
|
|
11466
|
+
if (hasRequiredUtil) return util;
|
|
11467
|
+
hasRequiredUtil = 1;
|
|
11468
|
+
util.getBooleanOption = (options, key) => {
|
|
11469
|
+
let value = false;
|
|
11470
|
+
if (key in options && typeof (value = options[key]) !== 'boolean') {
|
|
11471
|
+
throw new TypeError(`Expected the "${key}" option to be a boolean`);
|
|
11472
|
+
}
|
|
11473
|
+
return value;
|
|
11474
|
+
};
|
|
11475
|
+
util.cppdb = Symbol();
|
|
11476
|
+
util.inspect = Symbol.for('nodejs.util.inspect.custom');
|
|
11477
|
+
return util;
|
|
11321
11478
|
}
|
|
11322
11479
|
|
|
11323
|
-
var
|
|
11480
|
+
var sqliteError;
|
|
11481
|
+
var hasRequiredSqliteError;
|
|
11482
|
+
function requireSqliteError() {
|
|
11483
|
+
if (hasRequiredSqliteError) return sqliteError;
|
|
11484
|
+
hasRequiredSqliteError = 1;
|
|
11485
|
+
class SqliteError extends Error {
|
|
11486
|
+
constructor(message, code) {
|
|
11487
|
+
if (typeof code !== 'string') {
|
|
11488
|
+
throw new TypeError('Expected second argument to be a string');
|
|
11489
|
+
}
|
|
11490
|
+
super('' + message);
|
|
11491
|
+
this.code = code;
|
|
11492
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
11493
|
+
Error.captureStackTrace(this, SqliteError);
|
|
11494
|
+
}
|
|
11495
|
+
}
|
|
11496
|
+
}
|
|
11497
|
+
Object.defineProperty(SqliteError.prototype, 'name', {
|
|
11498
|
+
value: 'SqliteError',
|
|
11499
|
+
writable: true,
|
|
11500
|
+
enumerable: false,
|
|
11501
|
+
configurable: true
|
|
11502
|
+
});
|
|
11503
|
+
sqliteError = SqliteError;
|
|
11504
|
+
return sqliteError;
|
|
11505
|
+
}
|
|
11324
11506
|
|
|
11325
|
-
var
|
|
11326
|
-
var hasRequiredFileUriToPath;
|
|
11327
|
-
function requireFileUriToPath() {
|
|
11328
|
-
if (hasRequiredFileUriToPath) return fileUriToPath_1;
|
|
11329
|
-
hasRequiredFileUriToPath = 1;
|
|
11330
|
-
/**
|
|
11331
|
-
* Module dependencies.
|
|
11332
|
-
*/
|
|
11507
|
+
var wrappers = {};
|
|
11333
11508
|
|
|
11334
|
-
|
|
11509
|
+
var hasRequiredWrappers;
|
|
11510
|
+
function requireWrappers() {
|
|
11511
|
+
if (hasRequiredWrappers) return wrappers;
|
|
11512
|
+
hasRequiredWrappers = 1;
|
|
11513
|
+
const {
|
|
11514
|
+
cppdb
|
|
11515
|
+
} = requireUtil();
|
|
11516
|
+
wrappers.prepare = function prepare(sql) {
|
|
11517
|
+
return this[cppdb].prepare(sql, this, false, false);
|
|
11518
|
+
};
|
|
11519
|
+
wrappers.exec = function exec(sql) {
|
|
11520
|
+
this[cppdb].exec(sql);
|
|
11521
|
+
return this;
|
|
11522
|
+
};
|
|
11523
|
+
wrappers.close = function close() {
|
|
11524
|
+
this[cppdb].close();
|
|
11525
|
+
return this;
|
|
11526
|
+
};
|
|
11527
|
+
wrappers.loadExtension = function loadExtension(...args) {
|
|
11528
|
+
this[cppdb].loadExtension(...args);
|
|
11529
|
+
return this;
|
|
11530
|
+
};
|
|
11531
|
+
wrappers.defaultSafeIntegers = function defaultSafeIntegers(...args) {
|
|
11532
|
+
this[cppdb].defaultSafeIntegers(...args);
|
|
11533
|
+
return this;
|
|
11534
|
+
};
|
|
11535
|
+
wrappers.unsafeMode = function unsafeMode(...args) {
|
|
11536
|
+
this[cppdb].unsafeMode(...args);
|
|
11537
|
+
return this;
|
|
11538
|
+
};
|
|
11539
|
+
wrappers.getters = {
|
|
11540
|
+
name: {
|
|
11541
|
+
get: function name() {
|
|
11542
|
+
return this[cppdb].name;
|
|
11543
|
+
},
|
|
11544
|
+
enumerable: true
|
|
11545
|
+
},
|
|
11546
|
+
open: {
|
|
11547
|
+
get: function open() {
|
|
11548
|
+
return this[cppdb].open;
|
|
11549
|
+
},
|
|
11550
|
+
enumerable: true
|
|
11551
|
+
},
|
|
11552
|
+
inTransaction: {
|
|
11553
|
+
get: function inTransaction() {
|
|
11554
|
+
return this[cppdb].inTransaction;
|
|
11555
|
+
},
|
|
11556
|
+
enumerable: true
|
|
11557
|
+
},
|
|
11558
|
+
readonly: {
|
|
11559
|
+
get: function readonly() {
|
|
11560
|
+
return this[cppdb].readonly;
|
|
11561
|
+
},
|
|
11562
|
+
enumerable: true
|
|
11563
|
+
},
|
|
11564
|
+
memory: {
|
|
11565
|
+
get: function memory() {
|
|
11566
|
+
return this[cppdb].memory;
|
|
11567
|
+
},
|
|
11568
|
+
enumerable: true
|
|
11569
|
+
}
|
|
11570
|
+
};
|
|
11571
|
+
return wrappers;
|
|
11572
|
+
}
|
|
11335
11573
|
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11574
|
+
var transaction;
|
|
11575
|
+
var hasRequiredTransaction;
|
|
11576
|
+
function requireTransaction() {
|
|
11577
|
+
if (hasRequiredTransaction) return transaction;
|
|
11578
|
+
hasRequiredTransaction = 1;
|
|
11579
|
+
const {
|
|
11580
|
+
cppdb
|
|
11581
|
+
} = requireUtil();
|
|
11582
|
+
const controllers = new WeakMap();
|
|
11583
|
+
transaction = function transaction(fn) {
|
|
11584
|
+
if (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');
|
|
11585
|
+
const db = this[cppdb];
|
|
11586
|
+
const controller = getController(db, this);
|
|
11587
|
+
const {
|
|
11588
|
+
apply
|
|
11589
|
+
} = Function.prototype;
|
|
11339
11590
|
|
|
11340
|
-
|
|
11591
|
+
// Each version of the transaction function has these same properties
|
|
11592
|
+
const properties = {
|
|
11593
|
+
default: {
|
|
11594
|
+
value: wrapTransaction(apply, fn, db, controller.default)
|
|
11595
|
+
},
|
|
11596
|
+
deferred: {
|
|
11597
|
+
value: wrapTransaction(apply, fn, db, controller.deferred)
|
|
11598
|
+
},
|
|
11599
|
+
immediate: {
|
|
11600
|
+
value: wrapTransaction(apply, fn, db, controller.immediate)
|
|
11601
|
+
},
|
|
11602
|
+
exclusive: {
|
|
11603
|
+
value: wrapTransaction(apply, fn, db, controller.exclusive)
|
|
11604
|
+
},
|
|
11605
|
+
database: {
|
|
11606
|
+
value: this,
|
|
11607
|
+
enumerable: true
|
|
11608
|
+
}
|
|
11609
|
+
};
|
|
11610
|
+
Object.defineProperties(properties.default.value, properties);
|
|
11611
|
+
Object.defineProperties(properties.deferred.value, properties);
|
|
11612
|
+
Object.defineProperties(properties.immediate.value, properties);
|
|
11613
|
+
Object.defineProperties(properties.exclusive.value, properties);
|
|
11341
11614
|
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
* @param {String} uri
|
|
11346
|
-
* @return {String} path
|
|
11347
|
-
* @api public
|
|
11348
|
-
*/
|
|
11615
|
+
// Return the default version of the transaction function
|
|
11616
|
+
return properties.default.value;
|
|
11617
|
+
};
|
|
11349
11618
|
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11619
|
+
// Return the database's cached transaction controller, or create a new one
|
|
11620
|
+
const getController = (db, self) => {
|
|
11621
|
+
let controller = controllers.get(db);
|
|
11622
|
+
if (!controller) {
|
|
11623
|
+
const shared = {
|
|
11624
|
+
commit: db.prepare('COMMIT', self, false, false),
|
|
11625
|
+
rollback: db.prepare('ROLLBACK', self, false, false),
|
|
11626
|
+
savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`', self, false, false),
|
|
11627
|
+
release: db.prepare('RELEASE `\t_bs3.\t`', self, false, false),
|
|
11628
|
+
rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`', self, false, false)
|
|
11629
|
+
};
|
|
11630
|
+
controllers.set(db, controller = {
|
|
11631
|
+
default: Object.assign({
|
|
11632
|
+
begin: db.prepare('BEGIN', self, false, false)
|
|
11633
|
+
}, shared),
|
|
11634
|
+
deferred: Object.assign({
|
|
11635
|
+
begin: db.prepare('BEGIN DEFERRED', self, false, false)
|
|
11636
|
+
}, shared),
|
|
11637
|
+
immediate: Object.assign({
|
|
11638
|
+
begin: db.prepare('BEGIN IMMEDIATE', self, false, false)
|
|
11639
|
+
}, shared),
|
|
11640
|
+
exclusive: Object.assign({
|
|
11641
|
+
begin: db.prepare('BEGIN EXCLUSIVE', self, false, false)
|
|
11642
|
+
}, shared)
|
|
11643
|
+
});
|
|
11353
11644
|
}
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
var host = rest.substring(0, firstSlash);
|
|
11357
|
-
var path = rest.substring(firstSlash + 1);
|
|
11645
|
+
return controller;
|
|
11646
|
+
};
|
|
11358
11647
|
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11648
|
+
// Return a new transaction function by wrapping the given function
|
|
11649
|
+
const wrapTransaction = (apply, fn, db, {
|
|
11650
|
+
begin,
|
|
11651
|
+
commit,
|
|
11652
|
+
rollback,
|
|
11653
|
+
savepoint,
|
|
11654
|
+
release,
|
|
11655
|
+
rollbackTo
|
|
11656
|
+
}) => function sqliteTransaction() {
|
|
11657
|
+
let before, after, undo;
|
|
11658
|
+
if (db.inTransaction) {
|
|
11659
|
+
before = savepoint;
|
|
11660
|
+
after = release;
|
|
11661
|
+
undo = rollbackTo;
|
|
11662
|
+
} else {
|
|
11663
|
+
before = begin;
|
|
11664
|
+
after = commit;
|
|
11665
|
+
undo = rollback;
|
|
11366
11666
|
}
|
|
11667
|
+
before.run();
|
|
11668
|
+
try {
|
|
11669
|
+
const result = apply.call(fn, this, arguments);
|
|
11670
|
+
if (result && typeof result.then === 'function') {
|
|
11671
|
+
throw new TypeError('Transaction function cannot return a promise');
|
|
11672
|
+
}
|
|
11673
|
+
after.run();
|
|
11674
|
+
return result;
|
|
11675
|
+
} catch (ex) {
|
|
11676
|
+
if (db.inTransaction) {
|
|
11677
|
+
undo.run();
|
|
11678
|
+
if (undo !== rollback) after.run();
|
|
11679
|
+
}
|
|
11680
|
+
throw ex;
|
|
11681
|
+
}
|
|
11682
|
+
};
|
|
11683
|
+
return transaction;
|
|
11684
|
+
}
|
|
11367
11685
|
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11686
|
+
var pragma;
|
|
11687
|
+
var hasRequiredPragma;
|
|
11688
|
+
function requirePragma() {
|
|
11689
|
+
if (hasRequiredPragma) return pragma;
|
|
11690
|
+
hasRequiredPragma = 1;
|
|
11691
|
+
const {
|
|
11692
|
+
getBooleanOption,
|
|
11693
|
+
cppdb
|
|
11694
|
+
} = requireUtil();
|
|
11695
|
+
pragma = function pragma(source, options) {
|
|
11696
|
+
if (options == null) options = {};
|
|
11697
|
+
if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11698
|
+
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
|
|
11699
|
+
const simple = getBooleanOption(options, 'simple');
|
|
11700
|
+
const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true, false);
|
|
11701
|
+
return simple ? stmt.pluck().get() : stmt.all();
|
|
11702
|
+
};
|
|
11703
|
+
return pragma;
|
|
11704
|
+
}
|
|
11376
11705
|
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11706
|
+
var explain;
|
|
11707
|
+
var hasRequiredExplain;
|
|
11708
|
+
function requireExplain() {
|
|
11709
|
+
if (hasRequiredExplain) return explain;
|
|
11710
|
+
hasRequiredExplain = 1;
|
|
11711
|
+
const {
|
|
11712
|
+
cppdb
|
|
11713
|
+
} = requireUtil();
|
|
11714
|
+
explain = function explain(source) {
|
|
11715
|
+
if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11716
|
+
const stmt = this[cppdb].prepare(`EXPLAIN ${source}`, this, false, true);
|
|
11717
|
+
return stmt.all();
|
|
11718
|
+
};
|
|
11719
|
+
return explain;
|
|
11388
11720
|
}
|
|
11389
11721
|
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11403
|
-
|
|
11722
|
+
var backup;
|
|
11723
|
+
var hasRequiredBackup;
|
|
11724
|
+
function requireBackup() {
|
|
11725
|
+
if (hasRequiredBackup) return backup;
|
|
11726
|
+
hasRequiredBackup = 1;
|
|
11727
|
+
const fs = require$$0;
|
|
11728
|
+
const path$1 = path;
|
|
11729
|
+
const {
|
|
11730
|
+
promisify
|
|
11731
|
+
} = require$$2;
|
|
11732
|
+
const {
|
|
11733
|
+
cppdb
|
|
11734
|
+
} = requireUtil();
|
|
11735
|
+
const fsAccess = promisify(fs.access);
|
|
11736
|
+
backup = async function backup(filename, options) {
|
|
11737
|
+
if (options == null) options = {};
|
|
11738
|
+
|
|
11739
|
+
// Validate arguments
|
|
11740
|
+
if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11741
|
+
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
|
|
11742
|
+
|
|
11743
|
+
// Interpret options
|
|
11744
|
+
filename = filename.trim();
|
|
11745
|
+
const attachedName = 'attached' in options ? options.attached : 'main';
|
|
11746
|
+
const handler = 'progress' in options ? options.progress : null;
|
|
11747
|
+
|
|
11748
|
+
// Validate interpreted options
|
|
11749
|
+
if (!filename) throw new TypeError('Backup filename cannot be an empty string');
|
|
11750
|
+
if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
|
|
11751
|
+
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
|
|
11752
|
+
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
|
|
11753
|
+
if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
|
|
11754
|
+
|
|
11755
|
+
// Make sure the specified directory exists
|
|
11756
|
+
await fsAccess(path$1.dirname(filename)).catch(() => {
|
|
11757
|
+
throw new TypeError('Cannot save backup because the directory does not exist');
|
|
11758
|
+
});
|
|
11759
|
+
const isNewFile = await fsAccess(filename).then(() => false, () => true);
|
|
11760
|
+
return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
|
|
11761
|
+
};
|
|
11762
|
+
const runBackup = (backup, handler) => {
|
|
11763
|
+
let rate = 0;
|
|
11764
|
+
let useDefault = true;
|
|
11765
|
+
return new Promise((resolve, reject) => {
|
|
11766
|
+
setImmediate(function step() {
|
|
11404
11767
|
try {
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
|
|
11768
|
+
const progress = backup.transfer(rate);
|
|
11769
|
+
if (!progress.remainingPages) {
|
|
11770
|
+
backup.close();
|
|
11771
|
+
resolve(progress);
|
|
11772
|
+
return;
|
|
11773
|
+
}
|
|
11774
|
+
if (useDefault) {
|
|
11775
|
+
useDefault = false;
|
|
11776
|
+
rate = 100;
|
|
11777
|
+
}
|
|
11778
|
+
if (handler) {
|
|
11779
|
+
const ret = handler(progress);
|
|
11780
|
+
if (ret !== undefined) {
|
|
11781
|
+
if (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));else throw new TypeError('Expected progress callback to return a number or undefined');
|
|
11782
|
+
}
|
|
11783
|
+
}
|
|
11784
|
+
setImmediate(step);
|
|
11785
|
+
} catch (err) {
|
|
11786
|
+
backup.close();
|
|
11787
|
+
reject(err);
|
|
11408
11788
|
}
|
|
11409
|
-
|
|
11410
|
-
|
|
11411
|
-
|
|
11412
|
-
|
|
11413
|
-
|
|
11414
|
-
platform: process.platform,
|
|
11415
|
-
arch: process.arch,
|
|
11416
|
-
nodePreGyp: 'node-v' + process.versions.modules + '-' + process.platform + '-' + process.arch,
|
|
11417
|
-
version: process.versions.node,
|
|
11418
|
-
bindings: 'bindings.node',
|
|
11419
|
-
try: [
|
|
11420
|
-
// node-gyp's linked version in the "build" dir
|
|
11421
|
-
['module_root', 'build', 'bindings'],
|
|
11422
|
-
// node-waf and gyp_addon (a.k.a node-gyp)
|
|
11423
|
-
['module_root', 'build', 'Debug', 'bindings'], ['module_root', 'build', 'Release', 'bindings'],
|
|
11424
|
-
// Debug files, for development (legacy behavior, remove for node v0.9)
|
|
11425
|
-
['module_root', 'out', 'Debug', 'bindings'], ['module_root', 'Debug', 'bindings'],
|
|
11426
|
-
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
|
|
11427
|
-
['module_root', 'out', 'Release', 'bindings'], ['module_root', 'Release', 'bindings'],
|
|
11428
|
-
// Legacy from node-waf, node <= 0.4.x
|
|
11429
|
-
['module_root', 'build', 'default', 'bindings'],
|
|
11430
|
-
// Production "Release" buildtype binary (meh...)
|
|
11431
|
-
['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],
|
|
11432
|
-
// node-qbs builds
|
|
11433
|
-
['module_root', 'addon-build', 'release', 'install-root', 'bindings'], ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'], ['module_root', 'addon-build', 'default', 'install-root', 'bindings'],
|
|
11434
|
-
// node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
|
|
11435
|
-
['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']]
|
|
11436
|
-
};
|
|
11437
|
-
|
|
11438
|
-
/**
|
|
11439
|
-
* The main `bindings()` function loads the compiled bindings for a given module.
|
|
11440
|
-
* It uses V8's Error API to determine the parent filename that this function is
|
|
11441
|
-
* being invoked from, which is then used to find the root directory.
|
|
11442
|
-
*/
|
|
11789
|
+
});
|
|
11790
|
+
});
|
|
11791
|
+
};
|
|
11792
|
+
return backup;
|
|
11793
|
+
}
|
|
11443
11794
|
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11795
|
+
var serialize;
|
|
11796
|
+
var hasRequiredSerialize;
|
|
11797
|
+
function requireSerialize() {
|
|
11798
|
+
if (hasRequiredSerialize) return serialize;
|
|
11799
|
+
hasRequiredSerialize = 1;
|
|
11800
|
+
const {
|
|
11801
|
+
cppdb
|
|
11802
|
+
} = requireUtil();
|
|
11803
|
+
serialize = function serialize(options) {
|
|
11804
|
+
if (options == null) options = {};
|
|
11805
|
+
|
|
11806
|
+
// Validate arguments
|
|
11807
|
+
if (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');
|
|
11808
|
+
|
|
11809
|
+
// Interpret and validate options
|
|
11810
|
+
const attachedName = 'attached' in options ? options.attached : 'main';
|
|
11811
|
+
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
|
|
11812
|
+
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
|
|
11813
|
+
return this[cppdb].serialize(attachedName);
|
|
11814
|
+
};
|
|
11815
|
+
return serialize;
|
|
11816
|
+
}
|
|
11453
11817
|
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11818
|
+
var _function;
|
|
11819
|
+
var hasRequired_function;
|
|
11820
|
+
function require_function() {
|
|
11821
|
+
if (hasRequired_function) return _function;
|
|
11822
|
+
hasRequired_function = 1;
|
|
11823
|
+
const {
|
|
11824
|
+
getBooleanOption,
|
|
11825
|
+
cppdb
|
|
11826
|
+
} = requireUtil();
|
|
11827
|
+
_function = function defineFunction(name, options, fn) {
|
|
11828
|
+
// Apply defaults
|
|
11829
|
+
if (options == null) options = {};
|
|
11830
|
+
if (typeof options === 'function') {
|
|
11831
|
+
fn = options;
|
|
11832
|
+
options = {};
|
|
11833
|
+
}
|
|
11834
|
+
|
|
11835
|
+
// Validate arguments
|
|
11836
|
+
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11837
|
+
if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
|
|
11838
|
+
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
|
|
11839
|
+
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
|
|
11840
|
+
|
|
11841
|
+
// Interpret options
|
|
11842
|
+
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
|
|
11843
|
+
const deterministic = getBooleanOption(options, 'deterministic');
|
|
11844
|
+
const directOnly = getBooleanOption(options, 'directOnly');
|
|
11845
|
+
const varargs = getBooleanOption(options, 'varargs');
|
|
11846
|
+
let argCount = -1;
|
|
11847
|
+
|
|
11848
|
+
// Determine argument count
|
|
11849
|
+
if (!varargs) {
|
|
11850
|
+
argCount = fn.length;
|
|
11851
|
+
if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
|
|
11852
|
+
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
|
|
11853
|
+
}
|
|
11854
|
+
this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
|
|
11855
|
+
return this;
|
|
11856
|
+
};
|
|
11857
|
+
return _function;
|
|
11858
|
+
}
|
|
11458
11859
|
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11860
|
+
var aggregate;
|
|
11861
|
+
var hasRequiredAggregate;
|
|
11862
|
+
function requireAggregate() {
|
|
11863
|
+
if (hasRequiredAggregate) return aggregate;
|
|
11864
|
+
hasRequiredAggregate = 1;
|
|
11865
|
+
const {
|
|
11866
|
+
getBooleanOption,
|
|
11867
|
+
cppdb
|
|
11868
|
+
} = requireUtil();
|
|
11869
|
+
aggregate = function defineAggregate(name, options) {
|
|
11870
|
+
// Validate arguments
|
|
11871
|
+
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11872
|
+
if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
|
|
11873
|
+
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
|
|
11874
|
+
|
|
11875
|
+
// Interpret options
|
|
11876
|
+
const start = 'start' in options ? options.start : null;
|
|
11877
|
+
const step = getFunctionOption(options, 'step', true);
|
|
11878
|
+
const inverse = getFunctionOption(options, 'inverse', false);
|
|
11879
|
+
const result = getFunctionOption(options, 'result', false);
|
|
11880
|
+
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
|
|
11881
|
+
const deterministic = getBooleanOption(options, 'deterministic');
|
|
11882
|
+
const directOnly = getBooleanOption(options, 'directOnly');
|
|
11883
|
+
const varargs = getBooleanOption(options, 'varargs');
|
|
11884
|
+
let argCount = -1;
|
|
11885
|
+
|
|
11886
|
+
// Determine argument count
|
|
11887
|
+
if (!varargs) {
|
|
11888
|
+
argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
|
|
11889
|
+
if (argCount > 0) argCount -= 1;
|
|
11890
|
+
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
|
|
11891
|
+
}
|
|
11892
|
+
this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
|
|
11893
|
+
return this;
|
|
11894
|
+
};
|
|
11895
|
+
const getFunctionOption = (options, key, required) => {
|
|
11896
|
+
const value = key in options ? options[key] : null;
|
|
11897
|
+
if (typeof value === 'function') return value;
|
|
11898
|
+
if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
|
|
11899
|
+
if (required) throw new TypeError(`Missing required option "${key}"`);
|
|
11900
|
+
return null;
|
|
11901
|
+
};
|
|
11902
|
+
const getLength = ({
|
|
11903
|
+
length
|
|
11904
|
+
}) => {
|
|
11905
|
+
if (Number.isInteger(length) && length >= 0) return length;
|
|
11906
|
+
throw new TypeError('Expected function.length to be a positive integer');
|
|
11907
|
+
};
|
|
11908
|
+
return aggregate;
|
|
11909
|
+
}
|
|
11463
11910
|
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11911
|
+
var table;
|
|
11912
|
+
var hasRequiredTable;
|
|
11913
|
+
function requireTable() {
|
|
11914
|
+
if (hasRequiredTable) return table;
|
|
11915
|
+
hasRequiredTable = 1;
|
|
11916
|
+
const {
|
|
11917
|
+
cppdb
|
|
11918
|
+
} = requireUtil();
|
|
11919
|
+
table = function defineTable(name, factory) {
|
|
11920
|
+
// Validate arguments
|
|
11921
|
+
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
11922
|
+
if (!name) throw new TypeError('Virtual table module name cannot be an empty string');
|
|
11923
|
+
|
|
11924
|
+
// Determine whether the module is eponymous-only or not
|
|
11925
|
+
let eponymous = false;
|
|
11926
|
+
if (typeof factory === 'object' && factory !== null) {
|
|
11927
|
+
eponymous = true;
|
|
11928
|
+
factory = defer(parseTableDefinition(factory, 'used', name));
|
|
11929
|
+
} else {
|
|
11930
|
+
if (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');
|
|
11931
|
+
factory = wrapFactory(factory);
|
|
11932
|
+
}
|
|
11933
|
+
this[cppdb].table(factory, name, eponymous);
|
|
11934
|
+
return this;
|
|
11935
|
+
};
|
|
11936
|
+
function wrapFactory(factory) {
|
|
11937
|
+
return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
|
|
11938
|
+
const thisObject = {
|
|
11939
|
+
module: moduleName,
|
|
11940
|
+
database: databaseName,
|
|
11941
|
+
table: tableName
|
|
11942
|
+
};
|
|
11468
11943
|
|
|
11469
|
-
//
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
l = opts.try.length,
|
|
11474
|
-
n,
|
|
11475
|
-
b,
|
|
11476
|
-
err;
|
|
11477
|
-
for (; i < l; i++) {
|
|
11478
|
-
n = join.apply(null, opts.try[i].map(function (p) {
|
|
11479
|
-
return opts[p] || p;
|
|
11480
|
-
}));
|
|
11481
|
-
tries.push(n);
|
|
11482
|
-
try {
|
|
11483
|
-
b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
|
|
11484
|
-
if (!opts.path) {
|
|
11485
|
-
b.path = n;
|
|
11486
|
-
}
|
|
11487
|
-
return b;
|
|
11488
|
-
} catch (e) {
|
|
11489
|
-
if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' && !/not find/i.test(e.message)) {
|
|
11490
|
-
throw e;
|
|
11491
|
-
}
|
|
11492
|
-
}
|
|
11944
|
+
// Generate a new table definition by invoking the factory
|
|
11945
|
+
const def = apply.call(factory, thisObject, args);
|
|
11946
|
+
if (typeof def !== 'object' || def === null) {
|
|
11947
|
+
throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
|
|
11493
11948
|
}
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11949
|
+
return parseTableDefinition(def, 'returned', moduleName);
|
|
11950
|
+
};
|
|
11951
|
+
}
|
|
11952
|
+
function parseTableDefinition(def, verb, moduleName) {
|
|
11953
|
+
// Validate required properties
|
|
11954
|
+
if (!hasOwnProperty.call(def, 'rows')) {
|
|
11955
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
|
|
11956
|
+
}
|
|
11957
|
+
if (!hasOwnProperty.call(def, 'columns')) {
|
|
11958
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
|
|
11499
11959
|
}
|
|
11500
|
-
module.exports = exports = bindings;
|
|
11501
|
-
|
|
11502
|
-
/**
|
|
11503
|
-
* Gets the filename of the JavaScript file that invokes this function.
|
|
11504
|
-
* Used to help find the root directory of a module.
|
|
11505
|
-
* Optionally accepts an filename argument to skip when searching for the invoking filename
|
|
11506
|
-
*/
|
|
11507
11960
|
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
Error.stackTraceLimit = 10;
|
|
11514
|
-
Error.prepareStackTrace = function (e, st) {
|
|
11515
|
-
for (var i = 0, l = st.length; i < l; i++) {
|
|
11516
|
-
fileName = st[i].getFileName();
|
|
11517
|
-
if (fileName !== __filename) {
|
|
11518
|
-
if (calling_file) {
|
|
11519
|
-
if (fileName !== calling_file) {
|
|
11520
|
-
return;
|
|
11521
|
-
}
|
|
11522
|
-
} else {
|
|
11523
|
-
return;
|
|
11524
|
-
}
|
|
11525
|
-
}
|
|
11526
|
-
}
|
|
11527
|
-
};
|
|
11961
|
+
// Validate "rows" property
|
|
11962
|
+
const rows = def.rows;
|
|
11963
|
+
if (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
|
|
11964
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
|
|
11965
|
+
}
|
|
11528
11966
|
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11967
|
+
// Validate "columns" property
|
|
11968
|
+
let columns = def.columns;
|
|
11969
|
+
if (!Array.isArray(columns) || !isStringArray(columns = [...columns])) {
|
|
11970
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
|
|
11971
|
+
}
|
|
11972
|
+
if (columns.length !== new Set(columns).size) {
|
|
11973
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
|
|
11974
|
+
}
|
|
11975
|
+
if (!columns.length) {
|
|
11976
|
+
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
|
|
11977
|
+
}
|
|
11532
11978
|
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
|
|
11979
|
+
// Validate "parameters" property
|
|
11980
|
+
let parameters;
|
|
11981
|
+
if (hasOwnProperty.call(def, 'parameters')) {
|
|
11982
|
+
parameters = def.parameters;
|
|
11983
|
+
if (!Array.isArray(parameters) || !isStringArray(parameters = [...parameters])) {
|
|
11984
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
|
|
11985
|
+
}
|
|
11986
|
+
} else {
|
|
11987
|
+
parameters = inferParameters(rows);
|
|
11988
|
+
}
|
|
11989
|
+
if (parameters.length !== new Set(parameters).size) {
|
|
11990
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
|
|
11991
|
+
}
|
|
11992
|
+
if (parameters.length > 32) {
|
|
11993
|
+
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
|
|
11994
|
+
}
|
|
11995
|
+
for (const parameter of parameters) {
|
|
11996
|
+
if (columns.includes(parameter)) {
|
|
11997
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
|
|
11998
|
+
}
|
|
11999
|
+
}
|
|
11536
12000
|
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
|
|
12001
|
+
// Validate "safeIntegers" option
|
|
12002
|
+
let safeIntegers = 2;
|
|
12003
|
+
if (hasOwnProperty.call(def, 'safeIntegers')) {
|
|
12004
|
+
const bool = def.safeIntegers;
|
|
12005
|
+
if (typeof bool !== 'boolean') {
|
|
12006
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
|
|
11541
12007
|
}
|
|
11542
|
-
|
|
11543
|
-
}
|
|
12008
|
+
safeIntegers = +bool;
|
|
12009
|
+
}
|
|
11544
12010
|
|
|
11545
|
-
|
|
11546
|
-
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
12011
|
+
// Validate "directOnly" option
|
|
12012
|
+
let directOnly = false;
|
|
12013
|
+
if (hasOwnProperty.call(def, 'directOnly')) {
|
|
12014
|
+
directOnly = def.directOnly;
|
|
12015
|
+
if (typeof directOnly !== 'boolean') {
|
|
12016
|
+
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
11553
12019
|
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
|
|
12020
|
+
// Generate SQL for the virtual table definition
|
|
12021
|
+
const columnDefinitions = [...parameters.map(identifier).map(str => `${str} HIDDEN`), ...columns.map(identifier)];
|
|
12022
|
+
return [`CREATE TABLE x(${columnDefinitions.join(', ')});`, wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName), parameters, safeIntegers, directOnly];
|
|
12023
|
+
}
|
|
12024
|
+
function wrapGenerator(generator, columnMap, moduleName) {
|
|
12025
|
+
return function* virtualTable(...args) {
|
|
12026
|
+
/*
|
|
12027
|
+
We must defensively clone any buffers in the arguments, because
|
|
12028
|
+
otherwise the generator could mutate one of them, which would cause
|
|
12029
|
+
us to return incorrect values for hidden columns, potentially
|
|
12030
|
+
corrupting the database.
|
|
12031
|
+
*/
|
|
12032
|
+
const output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);
|
|
12033
|
+
for (let i = 0; i < columnMap.size; ++i) {
|
|
12034
|
+
output.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)
|
|
12035
|
+
}
|
|
12036
|
+
for (const row of generator(...args)) {
|
|
12037
|
+
if (Array.isArray(row)) {
|
|
12038
|
+
extractRowArray(row, output, columnMap.size, moduleName);
|
|
12039
|
+
yield output;
|
|
12040
|
+
} else if (typeof row === 'object' && row !== null) {
|
|
12041
|
+
extractRowObject(row, output, columnMap, moduleName);
|
|
12042
|
+
yield output;
|
|
12043
|
+
} else {
|
|
12044
|
+
throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
|
|
11569
12045
|
}
|
|
11570
|
-
// Try the parent dir next
|
|
11571
|
-
prev = dir;
|
|
11572
|
-
dir = join(dir, '..');
|
|
11573
12046
|
}
|
|
11574
12047
|
};
|
|
11575
|
-
}
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11591
|
-
function requireTrace() {
|
|
11592
|
-
if (hasRequiredTrace) return trace;
|
|
11593
|
-
hasRequiredTrace = 1;
|
|
11594
|
-
// Inspired by https://github.com/tlrobinson/long-stack-traces
|
|
11595
|
-
const util = require$$0$1;
|
|
11596
|
-
function extendTrace(object, property, pos) {
|
|
11597
|
-
const old = object[property];
|
|
11598
|
-
object[property] = function () {
|
|
11599
|
-
const error = new Error();
|
|
11600
|
-
const name = object.constructor.name + '#' + property + '(' + Array.prototype.slice.call(arguments).map(function (el) {
|
|
11601
|
-
return util.inspect(el, false, 0);
|
|
11602
|
-
}).join(', ') + ')';
|
|
11603
|
-
if (typeof pos === 'undefined') pos = -1;
|
|
11604
|
-
if (pos < 0) pos += arguments.length;
|
|
11605
|
-
const cb = arguments[pos];
|
|
11606
|
-
if (typeof arguments[pos] === 'function') {
|
|
11607
|
-
arguments[pos] = function replacement() {
|
|
11608
|
-
const err = arguments[0];
|
|
11609
|
-
if (err && err.stack && !err.__augmented) {
|
|
11610
|
-
err.stack = filter(err).join('\n');
|
|
11611
|
-
err.stack += '\n--> in ' + name;
|
|
11612
|
-
err.stack += '\n' + filter(error).slice(1).join('\n');
|
|
11613
|
-
err.__augmented = true;
|
|
11614
|
-
}
|
|
11615
|
-
return cb.apply(this, arguments);
|
|
11616
|
-
};
|
|
12048
|
+
}
|
|
12049
|
+
function extractRowArray(row, output, columnCount, moduleName) {
|
|
12050
|
+
if (row.length !== columnCount) {
|
|
12051
|
+
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
|
|
12052
|
+
}
|
|
12053
|
+
const offset = output.length - columnCount;
|
|
12054
|
+
for (let i = 0; i < columnCount; ++i) {
|
|
12055
|
+
output[i + offset] = row[i];
|
|
12056
|
+
}
|
|
12057
|
+
}
|
|
12058
|
+
function extractRowObject(row, output, columnMap, moduleName) {
|
|
12059
|
+
let count = 0;
|
|
12060
|
+
for (const key of Object.keys(row)) {
|
|
12061
|
+
const index = columnMap.get(key);
|
|
12062
|
+
if (index === undefined) {
|
|
12063
|
+
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
|
|
11617
12064
|
}
|
|
11618
|
-
|
|
11619
|
-
|
|
12065
|
+
output[index] = row[key];
|
|
12066
|
+
count += 1;
|
|
12067
|
+
}
|
|
12068
|
+
if (count !== columnMap.size) {
|
|
12069
|
+
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
|
|
12070
|
+
}
|
|
11620
12071
|
}
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
|
|
12072
|
+
function inferParameters({
|
|
12073
|
+
length
|
|
12074
|
+
}) {
|
|
12075
|
+
if (!Number.isInteger(length) || length < 0) {
|
|
12076
|
+
throw new TypeError('Expected function.length to be a positive integer');
|
|
12077
|
+
}
|
|
12078
|
+
const params = [];
|
|
12079
|
+
for (let i = 0; i < length; ++i) {
|
|
12080
|
+
params.push(`$${i + 1}`);
|
|
12081
|
+
}
|
|
12082
|
+
return params;
|
|
11626
12083
|
}
|
|
11627
|
-
|
|
12084
|
+
const {
|
|
12085
|
+
hasOwnProperty
|
|
12086
|
+
} = Object.prototype;
|
|
12087
|
+
const {
|
|
12088
|
+
apply
|
|
12089
|
+
} = Function.prototype;
|
|
12090
|
+
const GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {});
|
|
12091
|
+
const identifier = str => `"${str.replace(/"/g, '""')}"`;
|
|
12092
|
+
const defer = x => () => x;
|
|
12093
|
+
const isStringArray = arr => {
|
|
12094
|
+
for (let i = 0; i < arr.length; ++i) {
|
|
12095
|
+
if (typeof arr[i] !== 'string') return false;
|
|
12096
|
+
}
|
|
12097
|
+
return true;
|
|
12098
|
+
};
|
|
12099
|
+
return table;
|
|
11628
12100
|
}
|
|
11629
12101
|
|
|
11630
|
-
var
|
|
11631
|
-
|
|
11632
|
-
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
12102
|
+
var inspect;
|
|
12103
|
+
var hasRequiredInspect;
|
|
12104
|
+
function requireInspect() {
|
|
12105
|
+
if (hasRequiredInspect) return inspect;
|
|
12106
|
+
hasRequiredInspect = 1;
|
|
12107
|
+
const DatabaseInspection = function Database() {};
|
|
12108
|
+
inspect = function inspect(depth, opts) {
|
|
12109
|
+
return Object.assign(new DatabaseInspection(), this);
|
|
12110
|
+
};
|
|
12111
|
+
return inspect;
|
|
12112
|
+
}
|
|
12113
|
+
|
|
12114
|
+
var database;
|
|
12115
|
+
var hasRequiredDatabase;
|
|
12116
|
+
function requireDatabase() {
|
|
12117
|
+
if (hasRequiredDatabase) return database;
|
|
12118
|
+
hasRequiredDatabase = 1;
|
|
12119
|
+
const fs = require$$0;
|
|
12120
|
+
const path$1 = path;
|
|
12121
|
+
const util = requireUtil();
|
|
12122
|
+
const SqliteError = requireSqliteError();
|
|
12123
|
+
database = function createDatabase(getAddon, allowNativeBinding) {
|
|
12124
|
+
function Database(filenameGiven, options) {
|
|
12125
|
+
if (new.target == null) {
|
|
12126
|
+
return new Database(filenameGiven, options);
|
|
12127
|
+
}
|
|
12128
|
+
|
|
12129
|
+
// Apply defaults
|
|
12130
|
+
let buffer;
|
|
12131
|
+
if (Buffer.isBuffer(filenameGiven)) {
|
|
12132
|
+
buffer = filenameGiven;
|
|
12133
|
+
filenameGiven = ':memory:';
|
|
12134
|
+
}
|
|
12135
|
+
if (filenameGiven == null) filenameGiven = '';
|
|
12136
|
+
if (options == null) options = {};
|
|
12137
|
+
|
|
12138
|
+
// Validate arguments
|
|
12139
|
+
if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
|
|
12140
|
+
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
|
|
12141
|
+
if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
|
|
12142
|
+
if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
|
|
12143
|
+
|
|
12144
|
+
// Interpret options
|
|
12145
|
+
const filename = filenameGiven.trim();
|
|
12146
|
+
const anonymous = filename === '' || filename === ':memory:';
|
|
12147
|
+
const readonly = util.getBooleanOption(options, 'readonly');
|
|
12148
|
+
const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
|
|
12149
|
+
const timeout = 'timeout' in options ? options.timeout : 5000;
|
|
12150
|
+
const verbose = 'verbose' in options ? options.verbose : null;
|
|
12151
|
+
const nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;
|
|
12152
|
+
|
|
12153
|
+
// Validate interpreted options
|
|
12154
|
+
if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
|
|
12155
|
+
if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
|
|
12156
|
+
if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
|
|
12157
|
+
if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
|
|
12158
|
+
if (!allowNativeBinding && 'nativeBinding' in options) throw new TypeError('The "nativeBinding" option is only supported by the default better-sqlite3 entrypoint');
|
|
12159
|
+
if (allowNativeBinding && nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
|
|
12160
|
+
|
|
12161
|
+
// Load the native addon
|
|
12162
|
+
const addon = getAddon(nativeBinding);
|
|
12163
|
+
if (!addon.isInitialized) {
|
|
12164
|
+
addon.initialize(SqliteError, arrayFactory, arrayAppender, rowFactory, recordFactory);
|
|
12165
|
+
addon.isInitialized = true;
|
|
12166
|
+
}
|
|
12167
|
+
|
|
12168
|
+
// Make sure the specified directory exists
|
|
12169
|
+
if (!anonymous && !filename.startsWith('file:') && !fs.existsSync(path$1.dirname(filename))) {
|
|
12170
|
+
throw new TypeError('Cannot open database because the directory does not exist');
|
|
12171
|
+
}
|
|
12172
|
+
Object.defineProperties(this, {
|
|
12173
|
+
[util.cppdb]: {
|
|
12174
|
+
value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null)
|
|
12175
|
+
},
|
|
12176
|
+
...wrappers.getters
|
|
12177
|
+
});
|
|
11654
12178
|
}
|
|
11655
|
-
|
|
11656
|
-
|
|
12179
|
+
const wrappers = requireWrappers();
|
|
12180
|
+
Database.prototype.prepare = wrappers.prepare;
|
|
12181
|
+
Database.prototype.transaction = requireTransaction();
|
|
12182
|
+
Database.prototype.pragma = requirePragma();
|
|
12183
|
+
Database.prototype.explain = requireExplain();
|
|
12184
|
+
Database.prototype.backup = requireBackup();
|
|
12185
|
+
Database.prototype.serialize = requireSerialize();
|
|
12186
|
+
Database.prototype.function = require_function();
|
|
12187
|
+
Database.prototype.aggregate = requireAggregate();
|
|
12188
|
+
Database.prototype.table = requireTable();
|
|
12189
|
+
Database.prototype.loadExtension = wrappers.loadExtension;
|
|
12190
|
+
Database.prototype.exec = wrappers.exec;
|
|
12191
|
+
Database.prototype.close = wrappers.close;
|
|
12192
|
+
Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
|
|
12193
|
+
Database.prototype.unsafeMode = wrappers.unsafeMode;
|
|
12194
|
+
Database.prototype[util.inspect] = requireInspect();
|
|
12195
|
+
return Database;
|
|
12196
|
+
};
|
|
12197
|
+
function arrayFactory(...values) {
|
|
12198
|
+
return values;
|
|
12199
|
+
}
|
|
12200
|
+
function arrayAppender(array, ...values) {
|
|
12201
|
+
const offset = array.length;
|
|
12202
|
+
for (let i = 0; i < values.length; ++i) {
|
|
12203
|
+
array[offset + i] = values[i];
|
|
11657
12204
|
}
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
// Make sure the callback is called.
|
|
11670
|
-
db = sqlite3.cached.objects[file];
|
|
11671
|
-
const callback = typeof a === 'number' ? b : a;
|
|
11672
|
-
if (typeof callback === 'function') {
|
|
11673
|
-
function cb() {
|
|
11674
|
-
callback.call(db, null);
|
|
11675
|
-
}
|
|
11676
|
-
if (db.open) process.nextTick(cb);else db.once('open', cb);
|
|
11677
|
-
}
|
|
11678
|
-
}
|
|
11679
|
-
return db;
|
|
11680
|
-
},
|
|
11681
|
-
objects: {}
|
|
12205
|
+
}
|
|
12206
|
+
function rowFactory(...keys) {
|
|
12207
|
+
if (!keys.includes('__proto__')) {
|
|
12208
|
+
const parameters = keys.map((_, index) => `v${index}`).join(',');
|
|
12209
|
+
const properties = keys.map((key, index) => `${JSON.stringify(key)}:v${index}`).join(',');
|
|
12210
|
+
return Function(`return (${parameters}) => ({${properties}})`)();
|
|
12211
|
+
}
|
|
12212
|
+
return (...values) => {
|
|
12213
|
+
const row = {};
|
|
12214
|
+
for (let i = 0; i < keys.length; ++i) row[keys[i]] = values[i];
|
|
12215
|
+
return row;
|
|
11682
12216
|
};
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
return params.length ? statement.bind.apply(statement, params) : statement;
|
|
11693
|
-
});
|
|
12217
|
+
}
|
|
12218
|
+
function recordFactory(value) {
|
|
12219
|
+
return {
|
|
12220
|
+
value,
|
|
12221
|
+
done: false
|
|
12222
|
+
};
|
|
12223
|
+
}
|
|
12224
|
+
return database;
|
|
12225
|
+
}
|
|
11694
12226
|
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
return this;
|
|
11699
|
-
});
|
|
12227
|
+
function commonjsRequire(path) {
|
|
12228
|
+
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
12229
|
+
}
|
|
11700
12230
|
|
|
11701
|
-
|
|
11702
|
-
Database.prototype.get = normalizeMethod(function (statement, params) {
|
|
11703
|
-
statement.get.apply(statement, params).finalize();
|
|
11704
|
-
return this;
|
|
11705
|
-
});
|
|
12231
|
+
var binding = {exports: {}};
|
|
11706
12232
|
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
12233
|
+
var hasRequiredBinding;
|
|
12234
|
+
function requireBinding() {
|
|
12235
|
+
if (hasRequiredBinding) return binding.exports;
|
|
12236
|
+
hasRequiredBinding = 1;
|
|
12237
|
+
(function (module, exports) {
|
|
11712
12238
|
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
12239
|
+
const fs = require$$0;
|
|
12240
|
+
const path$1 = path;
|
|
12241
|
+
const PREBUILD_PLATFORMS = ['linux', 'darwin', 'win32'];
|
|
12242
|
+
const PREBUILD_ARCHS = ['x64', 'arm64'];
|
|
12243
|
+
let DEFAULT_ADDON;
|
|
12244
|
+
function getBinding(nativeBinding) {
|
|
12245
|
+
// If a path was provided, load the binding from the filesystem.
|
|
12246
|
+
if (typeof nativeBinding === 'string') {
|
|
12247
|
+
// See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>
|
|
12248
|
+
const requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire;
|
|
12249
|
+
return requireFunc(path$1.resolve(nativeBinding).replace(/(\.node)?$/, '.node'));
|
|
12250
|
+
}
|
|
11722
12251
|
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
let backup;
|
|
11727
|
-
if (arguments.length <= 2) {
|
|
11728
|
-
// By default, we write the main database out to the main database of the named file.
|
|
11729
|
-
// This is the most likely use of the backup api.
|
|
11730
|
-
backup = new Backup(this, arguments[0], 'main', 'main', true, arguments[1]);
|
|
11731
|
-
} else {
|
|
11732
|
-
// Otherwise, give the user full control over the sqlite3_backup_init arguments.
|
|
11733
|
-
backup = new Backup(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
|
|
12252
|
+
// If an object was provided, use it as the binding directly.
|
|
12253
|
+
if (typeof nativeBinding === 'object' && nativeBinding !== null) {
|
|
12254
|
+
return nativeBinding;
|
|
11734
12255
|
}
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
Statement.prototype.map = function () {
|
|
11740
|
-
const params = Array.prototype.slice.call(arguments);
|
|
11741
|
-
const callback = params.pop();
|
|
11742
|
-
params.push(function (err, rows) {
|
|
11743
|
-
if (err) return callback(err);
|
|
11744
|
-
const result = {};
|
|
11745
|
-
if (rows.length) {
|
|
11746
|
-
const keys = Object.keys(rows[0]);
|
|
11747
|
-
const key = keys[0];
|
|
11748
|
-
if (keys.length > 2) {
|
|
11749
|
-
// Value is an object
|
|
11750
|
-
for (let i = 0; i < rows.length; i++) {
|
|
11751
|
-
result[rows[i][key]] = rows[i];
|
|
11752
|
-
}
|
|
11753
|
-
} else {
|
|
11754
|
-
const value = keys[1];
|
|
11755
|
-
// Value is a plain value
|
|
11756
|
-
for (let i = 0; i < rows.length; i++) {
|
|
11757
|
-
result[rows[i][key]] = rows[i][value];
|
|
11758
|
-
}
|
|
11759
|
-
}
|
|
11760
|
-
}
|
|
11761
|
-
callback(err, result);
|
|
11762
|
-
});
|
|
11763
|
-
return this.all.apply(this, params);
|
|
11764
|
-
};
|
|
11765
|
-
let isVerbose = false;
|
|
11766
|
-
const supportedEvents = ['trace', 'profile', 'change'];
|
|
11767
|
-
Database.prototype.addListener = Database.prototype.on = function (type) {
|
|
11768
|
-
const val = EventEmitter.prototype.addListener.apply(this, arguments);
|
|
11769
|
-
if (supportedEvents.indexOf(type) >= 0) {
|
|
11770
|
-
this.configure(type, true);
|
|
11771
|
-
}
|
|
11772
|
-
return val;
|
|
11773
|
-
};
|
|
11774
|
-
Database.prototype.removeListener = function (type) {
|
|
11775
|
-
const val = EventEmitter.prototype.removeListener.apply(this, arguments);
|
|
11776
|
-
if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) {
|
|
11777
|
-
this.configure(type, false);
|
|
12256
|
+
|
|
12257
|
+
// If we're using the default binding and it already exists, just return it.
|
|
12258
|
+
if (DEFAULT_ADDON) {
|
|
12259
|
+
return DEFAULT_ADDON;
|
|
11778
12260
|
}
|
|
11779
|
-
|
|
11780
|
-
|
|
11781
|
-
|
|
11782
|
-
|
|
11783
|
-
|
|
11784
|
-
this.configure(type, false);
|
|
12261
|
+
|
|
12262
|
+
// Otherwise, try to find the binding as a prebuilt binary.
|
|
12263
|
+
let filename = getPrebuildPath();
|
|
12264
|
+
if (filename) {
|
|
12265
|
+
return DEFAULT_ADDON = commonjsRequire(filename);
|
|
11785
12266
|
}
|
|
11786
|
-
return val;
|
|
11787
|
-
};
|
|
11788
12267
|
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
if (!
|
|
11792
|
-
|
|
11793
|
-
['prepare', 'get', 'run', 'all', 'each', 'map', 'close', 'exec'].forEach(function (name) {
|
|
11794
|
-
trace.extendTrace(Database.prototype, name);
|
|
11795
|
-
});
|
|
11796
|
-
['bind', 'get', 'run', 'all', 'each', 'map', 'reset', 'finalize'].forEach(function (name) {
|
|
11797
|
-
trace.extendTrace(Statement.prototype, name);
|
|
11798
|
-
});
|
|
11799
|
-
isVerbose = true;
|
|
12268
|
+
// If no prebuilt binary was found, try the default node-gyp locations.
|
|
12269
|
+
filename = path$1.join(__dirname, '..', 'build', 'Debug', 'better_sqlite3.node');
|
|
12270
|
+
if (!fs.existsSync(filename)) {
|
|
12271
|
+
filename = path$1.join(__dirname, '..', 'build', 'Release', 'better_sqlite3.node');
|
|
11800
12272
|
}
|
|
11801
|
-
return
|
|
11802
|
-
}
|
|
11803
|
-
|
|
11804
|
-
|
|
12273
|
+
return DEFAULT_ADDON = commonjsRequire(filename);
|
|
12274
|
+
}
|
|
12275
|
+
function getPrebuildPath() {
|
|
12276
|
+
if (PREBUILD_PLATFORMS.includes(process.platform) && PREBUILD_ARCHS.includes(process.arch)) {
|
|
12277
|
+
const target = `${isLinuxMusl() ? 'linuxmusl' : process.platform}-${process.arch}`;
|
|
12278
|
+
const filename = path$1.join(__dirname, '..', 'prebuilds', `${target}.node`);
|
|
12279
|
+
if (fs.existsSync(filename)) {
|
|
12280
|
+
return filename;
|
|
12281
|
+
}
|
|
12282
|
+
}
|
|
12283
|
+
return null;
|
|
12284
|
+
}
|
|
12285
|
+
function isLinuxMusl() {
|
|
12286
|
+
return process.platform === 'linux' && !process.report.getReport().header.glibcVersionRuntime;
|
|
12287
|
+
}
|
|
12288
|
+
exports.getBinding = getBinding;
|
|
12289
|
+
exports.getPrebuildPath = getPrebuildPath;
|
|
12290
|
+
|
|
12291
|
+
// This script is executed directly by binding.gyp to detect prebuilt binaries.
|
|
12292
|
+
if (require.main === module) {
|
|
12293
|
+
process.stdout.write(getPrebuildPath() ? '1' : '0');
|
|
12294
|
+
}
|
|
12295
|
+
})(binding, binding.exports);
|
|
12296
|
+
return binding.exports;
|
|
11805
12297
|
}
|
|
11806
12298
|
|
|
11807
|
-
var
|
|
11808
|
-
|
|
12299
|
+
var hasRequiredLib;
|
|
12300
|
+
function requireLib() {
|
|
12301
|
+
if (hasRequiredLib) return lib.exports;
|
|
12302
|
+
hasRequiredLib = 1;
|
|
12303
|
+
lib.exports = requireDatabase()(requireBinding().getBinding, true);
|
|
12304
|
+
lib.exports.SqliteError = requireSqliteError();
|
|
12305
|
+
return lib.exports;
|
|
12306
|
+
}
|
|
11809
12307
|
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
12308
|
+
var libExports = requireLib();
|
|
12309
|
+
var Database = /*@__PURE__*/getDefaultExportFromCjs(libExports);
|
|
12310
|
+
|
|
12311
|
+
/**
|
|
12312
|
+
*
|
|
12313
|
+
*/
|
|
12314
|
+
class SQLiteResult {
|
|
12315
|
+
/**
|
|
12316
|
+
* @param {Error|null|undefined} error
|
|
12317
|
+
* @param {number|undefined} [insertId]
|
|
12318
|
+
* @param {number} [rowsAffected]
|
|
12319
|
+
* @param {object[]} [rows]
|
|
12320
|
+
*/
|
|
12321
|
+
constructor(error, insertId, rowsAffected, rows) {
|
|
12322
|
+
this.error = error;
|
|
12323
|
+
this.insertId = insertId;
|
|
12324
|
+
this.rowsAffected = rowsAffected;
|
|
12325
|
+
this.rows = rows;
|
|
12326
|
+
}
|
|
11815
12327
|
}
|
|
12328
|
+
const READ_ONLY_ERROR = new Error('could not prepare statement (23 not authorized)');
|
|
11816
12329
|
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
12330
|
+
/**
|
|
12331
|
+
* @typedef {(sql: string, duration: number) => void} SQLProfileCallback
|
|
12332
|
+
*/
|
|
12333
|
+
|
|
12334
|
+
/**
|
|
12335
|
+
* @typedef {((sql: string) => void)|undefined} SQLTraceCallback
|
|
12336
|
+
*/
|
|
12337
|
+
|
|
12338
|
+
/**
|
|
12339
|
+
* @param {string} name
|
|
12340
|
+
* @param {{busyTimeout?: number, trace?: (sql: string) => void, profile?: SQLProfileCallback}} [opts]
|
|
12341
|
+
* @returns {void}
|
|
12342
|
+
*/
|
|
12343
|
+
function SQLiteDatabase(name, opts = {}) {
|
|
12344
|
+
/** @type {import('better-sqlite3').Database} */
|
|
12345
|
+
const db = new Database(name);
|
|
12346
|
+
|
|
12347
|
+
/** @type {SQLTraceCallback} */
|
|
12348
|
+
// eslint-disable-next-line prefer-destructuring -- TS
|
|
12349
|
+
let trace = opts.trace;
|
|
12350
|
+
/** @type {SQLProfileCallback|undefined} */
|
|
12351
|
+
// eslint-disable-next-line prefer-destructuring -- TS
|
|
12352
|
+
let profile = opts.profile;
|
|
11821
12353
|
if (opts.busyTimeout) {
|
|
11822
|
-
|
|
11823
|
-
}
|
|
11824
|
-
if (opts.trace) {
|
|
11825
|
-
this._db.configure('trace', opts.trace);
|
|
12354
|
+
db.pragma('busy_timeout = ' + Number(opts.busyTimeout));
|
|
11826
12355
|
}
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
12356
|
+
|
|
12357
|
+
// Kept untyped (rather than the better-sqlite3 `Database` type) since that
|
|
12358
|
+
// type is internal to `@types/better-sqlite3` and can't be named in this
|
|
12359
|
+
// file's emitted declaration.
|
|
12360
|
+
this._db = /** @type {any} */{
|
|
12361
|
+
_db: db,
|
|
12362
|
+
/**
|
|
12363
|
+
* Compatibility with node-sqlite3's configure API.
|
|
12364
|
+
* @param {'busyTimeout'|'trace'|'profile'} option
|
|
12365
|
+
* @param {number|((sql: string, duration?: number) => void)} value
|
|
12366
|
+
* @returns {void}
|
|
12367
|
+
*/
|
|
12368
|
+
configure(option, value) {
|
|
12369
|
+
if (option === 'busyTimeout') {
|
|
12370
|
+
db.pragma('busy_timeout = ' + Number(/** @type {number} */value));
|
|
12371
|
+
return;
|
|
12372
|
+
}
|
|
12373
|
+
if (option === 'trace') {
|
|
12374
|
+
trace = /** @type {(sql: string) => void} */value;
|
|
12375
|
+
return;
|
|
12376
|
+
}
|
|
12377
|
+
if (option === 'profile') {
|
|
12378
|
+
profile = /** @type {SQLProfileCallback} */value;
|
|
12379
|
+
}
|
|
12380
|
+
},
|
|
12381
|
+
/**
|
|
12382
|
+
* Compatibility with callback-oriented close semantics.
|
|
12383
|
+
* @param {(err?: Error|null) => void} [cb]
|
|
12384
|
+
* @returns {void}
|
|
12385
|
+
*/
|
|
12386
|
+
close(cb) {
|
|
12387
|
+
try {
|
|
12388
|
+
db.close();
|
|
12389
|
+
if (cb) {
|
|
12390
|
+
return cb(null);
|
|
12391
|
+
}
|
|
12392
|
+
} catch (err) {
|
|
12393
|
+
if (cb) {
|
|
12394
|
+
return cb(/** @type {Error} */err);
|
|
12395
|
+
}
|
|
12396
|
+
}
|
|
12397
|
+
return undefined;
|
|
12398
|
+
},
|
|
12399
|
+
getTrace() {
|
|
12400
|
+
return trace;
|
|
12401
|
+
},
|
|
12402
|
+
getProfile() {
|
|
12403
|
+
return profile;
|
|
11835
12404
|
}
|
|
11836
|
-
|
|
11837
|
-
var rowsAffected = 0;
|
|
11838
|
-
var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows);
|
|
11839
|
-
cb(resultSet);
|
|
11840
|
-
});
|
|
12405
|
+
};
|
|
11841
12406
|
}
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
|
|
11854
|
-
|
|
12407
|
+
|
|
12408
|
+
/**
|
|
12409
|
+
* @param {import('better-sqlite3').Database} db
|
|
12410
|
+
* @param {string} sql
|
|
12411
|
+
* @param {unknown[]} args
|
|
12412
|
+
* @returns {object[]}
|
|
12413
|
+
*/
|
|
12414
|
+
function runSelect(db, sql, args) {
|
|
12415
|
+
const stmt = db.prepare(sql);
|
|
12416
|
+
return stmt.reader ? (/** @type {object[]} */stmt.all(...args)) : [];
|
|
12417
|
+
}
|
|
12418
|
+
|
|
12419
|
+
/**
|
|
12420
|
+
* @param {import('better-sqlite3').Database} db
|
|
12421
|
+
* @param {string} sql
|
|
12422
|
+
* @param {unknown[]} args
|
|
12423
|
+
* @returns {import('better-sqlite3').RunResult}
|
|
12424
|
+
*/
|
|
12425
|
+
function runNonSelect(db, sql, args) {
|
|
12426
|
+
const stmt = db.prepare(sql);
|
|
12427
|
+
return stmt.run(...args);
|
|
11855
12428
|
}
|
|
12429
|
+
|
|
12430
|
+
/**
|
|
12431
|
+
* @param {{sql: string, args: unknown[]}[]} queries
|
|
12432
|
+
* @param {boolean} readOnly
|
|
12433
|
+
* @param {(err: Error|null, results?: SQLiteResult[]) => void} callback
|
|
12434
|
+
* @returns {void}
|
|
12435
|
+
*/
|
|
11856
12436
|
SQLiteDatabase.prototype.exec = function exec(queries, readOnly, callback) {
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
return function (res) {
|
|
11870
|
-
results[i] = res;
|
|
11871
|
-
checkDone();
|
|
11872
|
-
};
|
|
11873
|
-
}
|
|
11874
|
-
function doNext() {
|
|
11875
|
-
var query = queries[i];
|
|
11876
|
-
var sql = query.sql;
|
|
11877
|
-
var args = query.args;
|
|
11878
|
-
|
|
11879
|
-
// TODO: It seems like the node-sqlite3 API either allows:
|
|
11880
|
-
// 1) all(), which returns results but not rowsAffected or lastID
|
|
11881
|
-
// 2) run(), which doesn't return results, but returns rowsAffected and lastID
|
|
11882
|
-
// So we try to sniff whether it's a SELECT query or not.
|
|
11883
|
-
// This is inherently error-prone, although it will probably work in the 99%
|
|
11884
|
-
// case.
|
|
11885
|
-
var isSelect = /^\s*SELECT\b/i.test(sql);
|
|
12437
|
+
const db = this._db._db;
|
|
12438
|
+
const len = queries.length;
|
|
12439
|
+
const results = Array.from({
|
|
12440
|
+
length: len
|
|
12441
|
+
});
|
|
12442
|
+
for (let i = 0; i < len; i++) {
|
|
12443
|
+
const query = queries[i];
|
|
12444
|
+
const {
|
|
12445
|
+
sql,
|
|
12446
|
+
args
|
|
12447
|
+
} = query;
|
|
12448
|
+
const isSelect = /^\s*SELECT\b/iu.test(sql);
|
|
11886
12449
|
if (readOnly && !isSelect) {
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
12450
|
+
results[i] = new SQLiteResult(READ_ONLY_ERROR);
|
|
12451
|
+
continue;
|
|
12452
|
+
}
|
|
12453
|
+
const trace = this._db.getTrace();
|
|
12454
|
+
const profile = this._db.getProfile();
|
|
12455
|
+
// eslint-disable-next-line unicorn/prefer-bigint-literals -- `0n` needs ES2020+ target for tsc
|
|
12456
|
+
const start = profile ? process.hrtime.bigint() : BigInt(0);
|
|
12457
|
+
try {
|
|
12458
|
+
if (trace) {
|
|
12459
|
+
trace(sql);
|
|
12460
|
+
}
|
|
12461
|
+
if (isSelect) {
|
|
12462
|
+
const rows = runSelect(db, sql, args);
|
|
12463
|
+
results[i] = new SQLiteResult(null, undefined, 0, rows);
|
|
12464
|
+
} else {
|
|
12465
|
+
const executionResult = runNonSelect(db, sql, args);
|
|
12466
|
+
const insertId = Number(executionResult.lastInsertRowid);
|
|
12467
|
+
results[i] = new SQLiteResult(null, insertId, executionResult.changes, []);
|
|
12468
|
+
}
|
|
12469
|
+
} catch (err) {
|
|
12470
|
+
results[i] = new SQLiteResult(/** @type {Error} */err);
|
|
12471
|
+
} finally {
|
|
12472
|
+
if (profile) {
|
|
12473
|
+
profile(sql, Number(process.hrtime.bigint() - start));
|
|
12474
|
+
}
|
|
11892
12475
|
}
|
|
11893
12476
|
}
|
|
11894
|
-
|
|
12477
|
+
queueMicrotask(() => {
|
|
12478
|
+
callback(null, results);
|
|
12479
|
+
});
|
|
11895
12480
|
};
|
|
11896
12481
|
|
|
11897
12482
|
/**
|
|
@@ -11904,11 +12489,9 @@ function wrappedSQLiteDatabase(name) {
|
|
|
11904
12489
|
db._db.configure('busyTimeout', /** @type {number} */CFG.sqlBusyTimeout); // Default is 1000
|
|
11905
12490
|
}
|
|
11906
12491
|
if (CFG.sqlTrace) {
|
|
11907
|
-
// @ts-expect-error native API?
|
|
11908
12492
|
db._db.configure('trace', CFG.sqlTrace);
|
|
11909
12493
|
}
|
|
11910
12494
|
if (CFG.sqlProfile) {
|
|
11911
|
-
// @ts-expect-error native API?
|
|
11912
12495
|
db._db.configure('profile', CFG.sqlProfile);
|
|
11913
12496
|
}
|
|
11914
12497
|
return db;
|
|
@@ -11939,6 +12522,7 @@ CFG.win = {
|
|
|
11939
12522
|
const __setGlobalVars = function (idb, initialConfig = {}) {
|
|
11940
12523
|
const obj = setGlobalVars(idb, {
|
|
11941
12524
|
fs: fs$1,
|
|
12525
|
+
escapeNULForSQLiteStatements: false,
|
|
11942
12526
|
...initialConfig
|
|
11943
12527
|
});
|
|
11944
12528
|
/* istanbul ignore next -- TS guard */
|