indexeddbshim 12.0.0 → 13.0.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 +1 -1
- package/badges/licenses-badge-dev.svg +1 -1
- package/dist/CFG.d.ts +80 -0
- package/dist/CFG.d.ts.map +1 -0
- package/dist/DOMException.d.ts +71 -0
- package/dist/DOMException.d.ts.map +1 -0
- package/dist/DOMStringList.d.ts +20 -0
- package/dist/DOMStringList.d.ts.map +1 -0
- package/dist/Event.d.ts +21 -0
- package/dist/Event.d.ts.map +1 -0
- package/dist/IDBCursor.d.ts +288 -0
- package/dist/IDBCursor.d.ts.map +1 -0
- package/dist/IDBDatabase.d.ts +143 -0
- package/dist/IDBDatabase.d.ts.map +1 -0
- package/dist/IDBFactory.d.ts +96 -0
- package/dist/IDBFactory.d.ts.map +1 -0
- package/dist/IDBIndex.d.ts +243 -0
- package/dist/IDBIndex.d.ts.map +1 -0
- package/dist/IDBKeyRange.d.ts +79 -0
- package/dist/IDBKeyRange.d.ts.map +1 -0
- package/dist/IDBObjectStore.d.ts +273 -0
- package/dist/IDBObjectStore.d.ts.map +1 -0
- package/dist/IDBRequest.d.ts +88 -0
- package/dist/IDBRequest.d.ts.map +1 -0
- package/dist/IDBTransaction.d.ts +270 -0
- package/dist/IDBTransaction.d.ts.map +1 -0
- package/dist/IDBVersionChangeEvent.d.ts +22 -0
- package/dist/IDBVersionChangeEvent.d.ts.map +1 -0
- package/dist/Key.d.ts +214 -0
- package/dist/Key.d.ts.map +1 -0
- package/dist/Sca.d.ts +31 -0
- package/dist/Sca.d.ts.map +1 -0
- package/dist/UnicodeIdentifiers.d.ts +3 -0
- package/dist/UnicodeIdentifiers.d.ts.map +1 -0
- package/dist/browser-UnicodeIdentifiers.d.ts +2 -0
- package/dist/browser-UnicodeIdentifiers.d.ts.map +1 -0
- package/dist/browser-noninvasive.d.ts +3 -0
- package/dist/browser-noninvasive.d.ts.map +1 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/cmp.d.ts +9 -0
- package/dist/cmp.d.ts.map +1 -0
- package/dist/indexeddbshim-Key.js +553 -252
- 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 +17560 -1302
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +4367 -1604
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +2 -2
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +17556 -1302
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +4362 -1604
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +2 -2
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +4362 -1604
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +2 -2
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/node-UnicodeIdentifiers.d.ts +8 -0
- package/dist/node-UnicodeIdentifiers.d.ts.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/nodeWebSQL.d.ts +3 -0
- package/dist/nodeWebSQL.d.ts.map +1 -0
- package/dist/setGlobalVars.d.ts +79 -0
- package/dist/setGlobalVars.d.ts.map +1 -0
- package/dist/unicode-regex.d.ts +3 -0
- package/dist/unicode-regex.d.ts.map +1 -0
- package/dist/util.d.ts +174 -0
- package/dist/util.d.ts.map +1 -0
- package/index.html +1 -1
- package/package.json +51 -37
- package/src/CFG.js +89 -11
- package/src/DOMException.js +117 -31
- package/src/DOMStringList.js +93 -3
- package/src/Event.js +19 -4
- package/src/IDBCursor.js +350 -76
- package/src/IDBDatabase.js +88 -10
- package/src/IDBFactory.js +331 -61
- package/src/IDBIndex.js +393 -110
- package/src/IDBKeyRange.js +90 -17
- package/src/IDBObjectStore.js +347 -86
- package/src/IDBRequest.js +59 -1
- package/src/IDBTransaction.js +254 -46
- package/src/IDBVersionChangeEvent.js +28 -3
- package/src/Key.d.ts +1 -0
- package/src/Key.js +272 -162
- package/src/Sca.js +29 -4
- package/src/browser-UnicodeIdentifiers.js +5 -1
- package/src/cmp.js +5 -5
- package/src/node-UnicodeIdentifiers.js +9 -0
- package/src/node.js +5 -0
- package/src/nodeWebSQL.js +11 -5
- package/src/setGlobalVars.js +159 -22
- package/src/unicode-regex.js +2 -0
- package/src/util.js +229 -40
- package/typings/shimIndexedDB.d.ts +9 -0
package/src/IDBIndex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import SyncPromise from 'sync-promise';
|
|
1
|
+
import SyncPromise from 'sync-promise-expanded';
|
|
2
2
|
import {createDOMException} from './DOMException.js';
|
|
3
3
|
import {IDBCursor, IDBCursorWithValue} from './IDBCursor.js';
|
|
4
4
|
import * as util from './util.js';
|
|
@@ -11,22 +11,70 @@ import IDBObjectStore from './IDBObjectStore.js';
|
|
|
11
11
|
|
|
12
12
|
const readonlyProperties = ['objectStore', 'keyPath', 'multiEntry', 'unique'];
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {number} Integer
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {{
|
|
20
|
+
* columnName: string,
|
|
21
|
+
* keyPath: import('./Key.js').KeyPath,
|
|
22
|
+
* optionalParams: {
|
|
23
|
+
* unique: boolean,
|
|
24
|
+
* multiEntry: boolean
|
|
25
|
+
* }
|
|
26
|
+
* deleted?: boolean,
|
|
27
|
+
* __deleted?: boolean,
|
|
28
|
+
* cursors?: import('./IDBCursor.js').IDBCursorWithValueFull[],
|
|
29
|
+
* }} IDBIndexProperties
|
|
30
|
+
*/
|
|
31
|
+
|
|
15
32
|
/**
|
|
16
33
|
* IDB Index.
|
|
17
34
|
* @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndex
|
|
18
|
-
* @param {IDBObjectStore} store
|
|
19
|
-
* @param {IDBIndexProperties} indexProperties
|
|
20
35
|
* @class
|
|
21
36
|
*/
|
|
22
37
|
function IDBIndex () {
|
|
23
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
24
38
|
throw new TypeError('Illegal constructor');
|
|
25
39
|
}
|
|
26
40
|
const IDBIndexAlias = IDBIndex;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {IDBIndex & {
|
|
44
|
+
* name: string,
|
|
45
|
+
* keyPath: import('./Key.js').KeyPath,
|
|
46
|
+
* multiEntry: boolean,
|
|
47
|
+
* unique: boolean,
|
|
48
|
+
* objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
49
|
+
* __pendingCreate?: boolean,
|
|
50
|
+
* __deleted?: boolean,
|
|
51
|
+
* __originalName: string,
|
|
52
|
+
* __currentName: string,
|
|
53
|
+
* __pendingName?: string,
|
|
54
|
+
* __pendingDelete?: boolean,
|
|
55
|
+
* __name: string,
|
|
56
|
+
* __multiEntry: boolean,
|
|
57
|
+
* __unique: boolean,
|
|
58
|
+
* __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
59
|
+
* __keyPath: import('./Key.js').KeyPath,
|
|
60
|
+
* __recreated?: boolean
|
|
61
|
+
* }} IDBIndexFull
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
67
|
+
* @param {IDBIndexProperties} indexProperties
|
|
68
|
+
* @returns {IDBIndexFull}
|
|
69
|
+
*/
|
|
27
70
|
IDBIndex.__createInstance = function (store, indexProperties) {
|
|
71
|
+
/**
|
|
72
|
+
* @class
|
|
73
|
+
* @this {IDBIndexFull}
|
|
74
|
+
*/
|
|
28
75
|
function IDBIndex () {
|
|
29
76
|
const me = this;
|
|
77
|
+
// @ts-expect-error It's ok
|
|
30
78
|
me[Symbol.toStringTag] = 'IDBIndex';
|
|
31
79
|
util.defineReadonlyProperties(me, readonlyProperties);
|
|
32
80
|
me.__objectStore = store;
|
|
@@ -38,16 +86,31 @@ IDBIndex.__createInstance = function (store, indexProperties) {
|
|
|
38
86
|
me.__deleted = Boolean(indexProperties.__deleted);
|
|
39
87
|
me.__objectStore.__cursors = indexProperties.cursors || [];
|
|
40
88
|
Object.defineProperty(me, '__currentName', {
|
|
89
|
+
/**
|
|
90
|
+
* @this {IDBIndexFull}
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
41
93
|
get () {
|
|
42
|
-
return '__pendingName' in me
|
|
94
|
+
return '__pendingName' in me
|
|
95
|
+
? /** @type {string} */ (me.__pendingName)
|
|
96
|
+
: me.name;
|
|
43
97
|
}
|
|
44
98
|
});
|
|
45
99
|
Object.defineProperty(me, 'name', {
|
|
46
100
|
enumerable: false,
|
|
47
101
|
configurable: false,
|
|
102
|
+
/**
|
|
103
|
+
* @this {IDBIndexFull}
|
|
104
|
+
* @returns {string}
|
|
105
|
+
*/
|
|
48
106
|
get () {
|
|
49
107
|
return this.__name;
|
|
50
108
|
},
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} newName
|
|
111
|
+
* @this {IDBIndexFull}
|
|
112
|
+
* @returns {void}
|
|
113
|
+
*/
|
|
51
114
|
set (newName) {
|
|
52
115
|
const me = this;
|
|
53
116
|
newName = util.convertToDOMString(newName);
|
|
@@ -72,7 +135,9 @@ IDBIndex.__createInstance = function (store, indexProperties) {
|
|
|
72
135
|
objectStore.__indexes[newName] = me;
|
|
73
136
|
objectStore.indexNames.splice(objectStore.indexNames.indexOf(oldName), 1, newName);
|
|
74
137
|
|
|
75
|
-
const storeHandle =
|
|
138
|
+
const storeHandle = /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
139
|
+
objectStore.transaction
|
|
140
|
+
).__storeHandles[objectStore.name];
|
|
76
141
|
const oldIndexHandle = storeHandle.__indexHandles[oldName];
|
|
77
142
|
oldIndexHandle.__name = newName; // Fix old references
|
|
78
143
|
storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
|
|
@@ -82,24 +147,37 @@ IDBIndex.__createInstance = function (store, indexProperties) {
|
|
|
82
147
|
['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')],
|
|
83
148
|
['value', 'BLOB']
|
|
84
149
|
].concat(
|
|
150
|
+
// @ts-expect-error Has numeric indexes instead of iterator
|
|
85
151
|
[...objectStore.indexNames]
|
|
86
152
|
.filter((indexName) => indexName !== newName)
|
|
87
153
|
.map((indexName) => [util.escapeIndexNameForSQL(indexName), 'BLOB'])
|
|
88
154
|
);
|
|
89
155
|
|
|
90
|
-
me.__renameIndex(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
156
|
+
me.__renameIndex(
|
|
157
|
+
objectStore, oldName, newName, colInfoToPreserveArr,
|
|
158
|
+
function (tx, success) {
|
|
159
|
+
IDBIndexAlias.__updateIndexList(store, tx, function (store) {
|
|
160
|
+
delete storeHandle.__pendingName;
|
|
161
|
+
success(store);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
);
|
|
96
165
|
}
|
|
97
166
|
});
|
|
98
167
|
}
|
|
99
168
|
IDBIndex.prototype = IDBIndexAlias.prototype;
|
|
169
|
+
|
|
170
|
+
// @ts-expect-error It's ok
|
|
100
171
|
return new IDBIndex();
|
|
101
172
|
};
|
|
102
173
|
|
|
174
|
+
/**
|
|
175
|
+
*
|
|
176
|
+
* @param {IDBIndexFull} index
|
|
177
|
+
* @param {string} [msg]
|
|
178
|
+
* @throws {DOMException}
|
|
179
|
+
* @returns {void}
|
|
180
|
+
*/
|
|
103
181
|
IDBIndex.__invalidStateIfDeleted = function (index, msg) {
|
|
104
182
|
if (index.__deleted || index.__pendingDelete || (
|
|
105
183
|
index.__pendingCreate && index.objectStore.transaction && index.objectStore.transaction.__errored
|
|
@@ -110,10 +188,9 @@ IDBIndex.__invalidStateIfDeleted = function (index, msg) {
|
|
|
110
188
|
|
|
111
189
|
/**
|
|
112
190
|
* Clones an IDBIndex instance for a different IDBObjectStore instance.
|
|
113
|
-
* @param {
|
|
114
|
-
* @param {IDBObjectStore} store
|
|
115
|
-
* @
|
|
116
|
-
* @returns {IDBIndex}
|
|
191
|
+
* @param {IDBIndexFull} index
|
|
192
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
193
|
+
* @returns {IDBIndexFull}
|
|
117
194
|
*/
|
|
118
195
|
IDBIndex.__clone = function (index, store) {
|
|
119
196
|
const idx = IDBIndex.__createInstance(store, {
|
|
@@ -124,7 +201,11 @@ IDBIndex.__clone = function (index, store) {
|
|
|
124
201
|
unique: index.unique
|
|
125
202
|
}
|
|
126
203
|
});
|
|
127
|
-
|
|
204
|
+
/** @type {const} */ ([
|
|
205
|
+
'__pendingCreate', '__pendingDelete', '__deleted',
|
|
206
|
+
'__originalName', '__recreated'
|
|
207
|
+
]).forEach((p) => {
|
|
208
|
+
// @ts-expect-error Why is this type "never"?
|
|
128
209
|
idx[p] = index[p];
|
|
129
210
|
});
|
|
130
211
|
return idx;
|
|
@@ -132,10 +213,9 @@ IDBIndex.__clone = function (index, store) {
|
|
|
132
213
|
|
|
133
214
|
/**
|
|
134
215
|
* Creates a new index on an object store.
|
|
135
|
-
* @param {IDBObjectStore} store
|
|
136
|
-
* @param {
|
|
216
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
217
|
+
* @param {IDBIndexFull} index
|
|
137
218
|
* @returns {void}
|
|
138
|
-
* @protected
|
|
139
219
|
*/
|
|
140
220
|
IDBIndex.__createIndex = function (store, index) {
|
|
141
221
|
const indexName = index.name;
|
|
@@ -160,33 +240,55 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
160
240
|
|
|
161
241
|
// Create the index in WebSQL
|
|
162
242
|
const {transaction} = store;
|
|
163
|
-
|
|
243
|
+
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
244
|
+
transaction
|
|
245
|
+
).__addNonRequestToTransactionQueue(function createIndex (tx, args, success, failure) {
|
|
164
246
|
const columnExists = idx && (idx.__deleted || idx.__recreated); // This check must occur here rather than earlier as properties may not have been set yet otherwise
|
|
247
|
+
|
|
248
|
+
/** @type {{[key: string]: boolean}} */
|
|
165
249
|
let indexValues = {};
|
|
166
250
|
|
|
251
|
+
/**
|
|
252
|
+
* @param {SQLTransaction} tx
|
|
253
|
+
* @param {SQLError} err
|
|
254
|
+
* @returns {void}
|
|
255
|
+
*/
|
|
167
256
|
function error (tx, err) {
|
|
168
257
|
failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
|
|
169
258
|
}
|
|
170
259
|
|
|
260
|
+
/**
|
|
261
|
+
* @param {SQLTransaction} tx
|
|
262
|
+
* @returns {void}
|
|
263
|
+
*/
|
|
171
264
|
function applyIndex (tx) {
|
|
172
265
|
// Update the object store's index list
|
|
173
266
|
IDBIndex.__updateIndexList(store, tx, function () {
|
|
174
267
|
// Add index entries for all existing records
|
|
175
268
|
tx.executeSql('SELECT "key", "value" FROM ' + util.escapeStoreNameForSQL(storeName), [], function (tx, data) {
|
|
176
|
-
CFG.DEBUG
|
|
269
|
+
if (CFG.DEBUG) { console.log('Adding existing ' + storeName + ' records to the ' + indexName + ' index'); }
|
|
177
270
|
addIndexEntry(0);
|
|
178
271
|
|
|
272
|
+
/**
|
|
273
|
+
* @param {Integer} i
|
|
274
|
+
* @returns {void}
|
|
275
|
+
*/
|
|
179
276
|
function addIndexEntry (i) {
|
|
180
277
|
if (i < data.rows.length) {
|
|
181
278
|
try {
|
|
182
279
|
const value = Sca.decode(util.unescapeSQLiteResponse(data.rows.item(i).value));
|
|
183
|
-
|
|
184
|
-
if (
|
|
280
|
+
const indexKey = Key.extractKeyValueDecodedFromValueUsingKeyPath(value, index.keyPath, index.multiEntry); // Todo: Do we need this stricter error checking?
|
|
281
|
+
if (
|
|
282
|
+
('invalid' in indexKey && indexKey.invalid) ||
|
|
283
|
+
('failure' in indexKey && indexKey.failure)
|
|
284
|
+
) { // Todo: Do we need invalid checks and should we instead treat these as being duplicates?
|
|
185
285
|
throw new Error('Go to catch; ignore bad indexKey');
|
|
186
286
|
}
|
|
187
|
-
|
|
287
|
+
const indexKeyStr = /** @type {string} */ (
|
|
288
|
+
Key.encode(indexKey.value, index.multiEntry)
|
|
289
|
+
);
|
|
188
290
|
if (index.unique) {
|
|
189
|
-
if (indexValues[
|
|
291
|
+
if (indexValues[indexKeyStr]) {
|
|
190
292
|
indexValues = {};
|
|
191
293
|
failure(createDOMException(
|
|
192
294
|
'ConstraintError',
|
|
@@ -194,16 +296,17 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
194
296
|
));
|
|
195
297
|
return;
|
|
196
298
|
}
|
|
197
|
-
indexValues[
|
|
299
|
+
indexValues[indexKeyStr] = true;
|
|
198
300
|
}
|
|
199
301
|
|
|
200
302
|
tx.executeSql(
|
|
201
303
|
'UPDATE ' + util.escapeStoreNameForSQL(storeName) + ' SET ' +
|
|
202
304
|
util.escapeIndexNameForSQL(indexName) + ' = ? WHERE "key" = ?',
|
|
203
|
-
[util.escapeSQLiteStatement(
|
|
204
|
-
function (
|
|
305
|
+
[util.escapeSQLiteStatement(indexKeyStr), data.rows.item(i).key],
|
|
306
|
+
function () {
|
|
205
307
|
addIndexEntry(i + 1);
|
|
206
|
-
},
|
|
308
|
+
},
|
|
309
|
+
/** @type {SQLStatementErrorCallback} */ (error)
|
|
207
310
|
);
|
|
208
311
|
} catch (e) {
|
|
209
312
|
// Not a valid value to insert into index, so just continue
|
|
@@ -222,13 +325,17 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
222
325
|
success(store);
|
|
223
326
|
}
|
|
224
327
|
}
|
|
225
|
-
}, error);
|
|
226
|
-
}, error);
|
|
328
|
+
}, /** @type {SQLStatementErrorCallback} */ (error));
|
|
329
|
+
}, /** @type {SQLStatementErrorCallback} */ (error));
|
|
227
330
|
}
|
|
228
331
|
|
|
229
332
|
const escapedStoreNameSQL = util.escapeStoreNameForSQL(storeName);
|
|
230
333
|
const escapedIndexNameSQL = util.escapeIndexNameForSQL(index.name);
|
|
231
334
|
|
|
335
|
+
/**
|
|
336
|
+
* @param {SQLTransaction} tx
|
|
337
|
+
* @returns {void}
|
|
338
|
+
*/
|
|
232
339
|
function addIndexSQL (tx) {
|
|
233
340
|
if (!CFG.useSQLiteIndexes) {
|
|
234
341
|
applyIndex(tx);
|
|
@@ -244,7 +351,7 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
244
351
|
'" ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')',
|
|
245
352
|
[],
|
|
246
353
|
applyIndex,
|
|
247
|
-
error
|
|
354
|
+
/** @type {SQLStatementErrorCallback} */ (error)
|
|
248
355
|
);
|
|
249
356
|
}
|
|
250
357
|
|
|
@@ -255,17 +362,18 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
255
362
|
} else {
|
|
256
363
|
// For a new index, add a new column to the object store, then apply the index
|
|
257
364
|
const sql = ['ALTER TABLE', escapedStoreNameSQL, 'ADD', escapedIndexNameSQL, 'BLOB'].join(' ');
|
|
258
|
-
CFG.DEBUG
|
|
259
|
-
tx.executeSql(
|
|
365
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
366
|
+
tx.executeSql(
|
|
367
|
+
sql, [], addIndexSQL, /** @type {SQLStatementErrorCallback} */ (error)
|
|
368
|
+
);
|
|
260
369
|
}
|
|
261
|
-
}
|
|
370
|
+
});
|
|
262
371
|
};
|
|
263
372
|
|
|
264
373
|
/**
|
|
265
374
|
* Deletes an index from an object store.
|
|
266
|
-
* @param {IDBObjectStore} store
|
|
267
|
-
* @param {
|
|
268
|
-
* @protected
|
|
375
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
376
|
+
* @param {IDBIndexFull} index
|
|
269
377
|
* @returns {void}
|
|
270
378
|
*/
|
|
271
379
|
IDBIndex.__deleteIndex = function (store, index) {
|
|
@@ -280,11 +388,21 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
280
388
|
|
|
281
389
|
// Remove the index in WebSQL
|
|
282
390
|
const {transaction} = store;
|
|
283
|
-
|
|
391
|
+
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
392
|
+
transaction
|
|
393
|
+
).__addNonRequestToTransactionQueue(function deleteIndex (tx, args, success, failure) {
|
|
394
|
+
/**
|
|
395
|
+
* @param {SQLTransaction} tx
|
|
396
|
+
* @param {SQLError} err
|
|
397
|
+
* @returns {void}
|
|
398
|
+
*/
|
|
284
399
|
function error (tx, err) {
|
|
285
400
|
failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
|
|
286
401
|
}
|
|
287
402
|
|
|
403
|
+
/**
|
|
404
|
+
* @returns {void}
|
|
405
|
+
*/
|
|
288
406
|
function finishDeleteIndex () {
|
|
289
407
|
// Update the object store's index list
|
|
290
408
|
IDBIndex.__updateIndexList(store, tx, function (store) {
|
|
@@ -296,7 +414,7 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
296
414
|
delete indexHandle.__pendingDelete;
|
|
297
415
|
}
|
|
298
416
|
success(store);
|
|
299
|
-
}, error);
|
|
417
|
+
}, /** @type {SQLStatementErrorCallback} */ (error));
|
|
300
418
|
}
|
|
301
419
|
|
|
302
420
|
if (!CFG.useSQLiteIndexes) {
|
|
@@ -311,24 +429,31 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
311
429
|
),
|
|
312
430
|
[],
|
|
313
431
|
finishDeleteIndex,
|
|
314
|
-
error
|
|
432
|
+
/** @type {SQLStatementErrorCallback} */ (error)
|
|
315
433
|
);
|
|
316
|
-
}
|
|
434
|
+
});
|
|
317
435
|
};
|
|
318
436
|
|
|
437
|
+
/**
|
|
438
|
+
* @typedef {{[key: string]: IDBIndexProperties}} IndexList
|
|
439
|
+
*/
|
|
440
|
+
|
|
319
441
|
/**
|
|
320
442
|
* Updates index list for the given object store.
|
|
321
|
-
* @param {IDBObjectStore} store
|
|
322
|
-
* @param {
|
|
323
|
-
* @param {
|
|
324
|
-
* @param {
|
|
443
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
444
|
+
* @param {SQLTransaction} tx
|
|
445
|
+
* @param {(store: IDBObjectStore) => void} success
|
|
446
|
+
* @param {(
|
|
447
|
+
* tx: SQLTransaction,
|
|
448
|
+
* err: SQLError
|
|
449
|
+
* ) => boolean} [failure]
|
|
325
450
|
* @returns {void}
|
|
326
451
|
*/
|
|
327
452
|
IDBIndex.__updateIndexList = function (store, tx, success, failure) {
|
|
453
|
+
/** @type {IndexList} **/
|
|
328
454
|
const indexList = {};
|
|
329
455
|
for (let i = 0; i < store.indexNames.length; i++) {
|
|
330
456
|
const idx = store.__indexes[store.indexNames[i]];
|
|
331
|
-
/** @type {IDBIndexProperties} **/
|
|
332
457
|
indexList[idx.name] = {
|
|
333
458
|
columnName: idx.name,
|
|
334
459
|
keyPath: idx.keyPath,
|
|
@@ -336,24 +461,28 @@ IDBIndex.__updateIndexList = function (store, tx, success, failure) {
|
|
|
336
461
|
unique: idx.unique,
|
|
337
462
|
multiEntry: idx.multiEntry
|
|
338
463
|
},
|
|
339
|
-
deleted: Boolean(idx.
|
|
464
|
+
deleted: Boolean(idx.__deleted)
|
|
340
465
|
};
|
|
341
466
|
}
|
|
342
467
|
|
|
343
|
-
CFG.DEBUG
|
|
468
|
+
if (CFG.DEBUG) { console.log('Updating the index list for ' + store.__currentName, indexList); }
|
|
344
469
|
tx.executeSql('UPDATE __sys__ SET "indexList" = ? WHERE "name" = ?', [JSON.stringify(indexList), util.escapeSQLiteStatement(store.__currentName)], function () {
|
|
345
470
|
success(store);
|
|
346
|
-
}, failure);
|
|
471
|
+
}, /** @type {SQLStatementErrorCallback} */ (failure));
|
|
347
472
|
};
|
|
348
473
|
|
|
474
|
+
/**
|
|
475
|
+
* @typedef {any|IDBKeyRange} Query
|
|
476
|
+
*/
|
|
477
|
+
|
|
349
478
|
/**
|
|
350
479
|
* Retrieves index data for the given key.
|
|
351
|
-
* @param {
|
|
352
|
-
* @param {
|
|
480
|
+
* @param {Query} range
|
|
481
|
+
* @param {"value"|"key"|"count"} opType
|
|
353
482
|
* @param {boolean} nullDisallowed
|
|
354
|
-
* @param {number} count
|
|
355
|
-
* @
|
|
356
|
-
* @
|
|
483
|
+
* @param {number} [count]
|
|
484
|
+
* @this {IDBIndexFull}
|
|
485
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
357
486
|
*/
|
|
358
487
|
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, count) {
|
|
359
488
|
const me = this;
|
|
@@ -373,20 +502,24 @@ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, c
|
|
|
373
502
|
}
|
|
374
503
|
|
|
375
504
|
const fetchArgs = buildFetchIndexDataSQL(nullDisallowed, me, range, opType, false);
|
|
376
|
-
return
|
|
377
|
-
|
|
505
|
+
return /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
506
|
+
me.objectStore.transaction
|
|
507
|
+
).__addToTransactionQueue(function (...args) {
|
|
508
|
+
executeFetchIndexData(
|
|
509
|
+
count,
|
|
510
|
+
...fetchArgs,
|
|
511
|
+
// @ts-expect-error It's ok
|
|
512
|
+
...args
|
|
513
|
+
);
|
|
378
514
|
}, undefined, me);
|
|
379
515
|
};
|
|
380
516
|
|
|
381
|
-
/* eslint-disable jsdoc/check-param-names */
|
|
382
517
|
/**
|
|
383
518
|
* Opens a cursor over the given key range.
|
|
384
|
-
* @
|
|
385
|
-
* @
|
|
386
|
-
* @returns {IDBRequest}
|
|
519
|
+
* @this {IDBIndexFull}
|
|
520
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
387
521
|
*/
|
|
388
522
|
IDBIndex.prototype.openCursor = function (/* query, direction */) {
|
|
389
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
390
523
|
const me = this;
|
|
391
524
|
// eslint-disable-next-line prefer-rest-params
|
|
392
525
|
const [query, direction] = arguments;
|
|
@@ -395,15 +528,12 @@ IDBIndex.prototype.openCursor = function (/* query, direction */) {
|
|
|
395
528
|
return cursor.__request;
|
|
396
529
|
};
|
|
397
530
|
|
|
398
|
-
/* eslint-disable jsdoc/check-param-names */
|
|
399
531
|
/**
|
|
400
532
|
* Opens a cursor over the given key range. The cursor only includes key values, not data.
|
|
401
|
-
* @
|
|
402
|
-
* @
|
|
403
|
-
* @returns {IDBRequest}
|
|
533
|
+
* @this {IDBIndexFull}
|
|
534
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
404
535
|
*/
|
|
405
536
|
IDBIndex.prototype.openKeyCursor = function (/* query, direction */) {
|
|
406
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
407
537
|
const me = this;
|
|
408
538
|
// eslint-disable-next-line prefer-rest-params
|
|
409
539
|
const [query, direction] = arguments;
|
|
@@ -412,6 +542,13 @@ IDBIndex.prototype.openKeyCursor = function (/* query, direction */) {
|
|
|
412
542
|
return cursor.__request;
|
|
413
543
|
};
|
|
414
544
|
|
|
545
|
+
/**
|
|
546
|
+
*
|
|
547
|
+
* @param {Query} query
|
|
548
|
+
* @throws {TypeError}
|
|
549
|
+
* @this {IDBIndexFull}
|
|
550
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
551
|
+
*/
|
|
415
552
|
IDBIndex.prototype.get = function (query) {
|
|
416
553
|
if (!arguments.length) { // Per https://heycam.github.io/webidl/
|
|
417
554
|
throw new TypeError('A parameter was missing for `IDBIndex.get`.');
|
|
@@ -419,6 +556,13 @@ IDBIndex.prototype.get = function (query) {
|
|
|
419
556
|
return this.__fetchIndexData(query, 'value', true);
|
|
420
557
|
};
|
|
421
558
|
|
|
559
|
+
/**
|
|
560
|
+
*
|
|
561
|
+
* @param {Query} query
|
|
562
|
+
* @throws {TypeError}
|
|
563
|
+
* @this {IDBIndexFull}
|
|
564
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
565
|
+
*/
|
|
422
566
|
IDBIndex.prototype.getKey = function (query) {
|
|
423
567
|
if (!arguments.length) { // Per https://heycam.github.io/webidl/
|
|
424
568
|
throw new TypeError('A parameter was missing for `IDBIndex.getKey`.');
|
|
@@ -426,18 +570,30 @@ IDBIndex.prototype.getKey = function (query) {
|
|
|
426
570
|
return this.__fetchIndexData(query, 'key', true);
|
|
427
571
|
};
|
|
428
572
|
|
|
573
|
+
/**
|
|
574
|
+
* @this {IDBIndexFull}
|
|
575
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
576
|
+
*/
|
|
429
577
|
IDBIndex.prototype.getAll = function (/* query, count */) {
|
|
430
578
|
// eslint-disable-next-line prefer-rest-params
|
|
431
579
|
const [query, count] = arguments;
|
|
432
580
|
return this.__fetchIndexData(query, 'value', false, count);
|
|
433
581
|
};
|
|
434
582
|
|
|
583
|
+
/**
|
|
584
|
+
* @this {IDBIndexFull}
|
|
585
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
586
|
+
*/
|
|
435
587
|
IDBIndex.prototype.getAllKeys = function (/* query, count */) {
|
|
436
588
|
// eslint-disable-next-line prefer-rest-params
|
|
437
589
|
const [query, count] = arguments;
|
|
438
590
|
return this.__fetchIndexData(query, 'key', false, count);
|
|
439
591
|
};
|
|
440
592
|
|
|
593
|
+
/**
|
|
594
|
+
* @this {IDBIndexFull}
|
|
595
|
+
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
596
|
+
*/
|
|
441
597
|
IDBIndex.prototype.count = function (/* query */) {
|
|
442
598
|
const me = this;
|
|
443
599
|
// eslint-disable-next-line prefer-rest-params
|
|
@@ -454,6 +610,19 @@ IDBIndex.prototype.count = function (/* query */) {
|
|
|
454
610
|
return me.__fetchIndexData(query, 'count', false);
|
|
455
611
|
};
|
|
456
612
|
|
|
613
|
+
/**
|
|
614
|
+
*
|
|
615
|
+
* @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
|
|
616
|
+
* @param {string} oldName
|
|
617
|
+
* @param {string} newName
|
|
618
|
+
* @param {string[][]} colInfoToPreserveArr
|
|
619
|
+
* @param {null|((
|
|
620
|
+
* tx: SQLTransaction,
|
|
621
|
+
* success: ((store: IDBObjectStore) => void)
|
|
622
|
+
* ) => void)} cb
|
|
623
|
+
* @this {IDBIndexFull}
|
|
624
|
+
* @returns {void}
|
|
625
|
+
*/
|
|
457
626
|
IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToPreserveArr = [], cb = null) {
|
|
458
627
|
const newNameType = 'BLOB';
|
|
459
628
|
const storeName = store.__currentName;
|
|
@@ -467,10 +636,20 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
467
636
|
|
|
468
637
|
// We could adapt the approach at http://stackoverflow.com/a/8430746/271577
|
|
469
638
|
// to make the approach reusable without passing column names, but it is a bit fragile
|
|
470
|
-
|
|
639
|
+
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
|
|
640
|
+
store.transaction
|
|
641
|
+
).__addNonRequestToTransactionQueue(function renameIndex (tx, args, success, error) {
|
|
642
|
+
/**
|
|
643
|
+
* @param {SQLTransaction} tx
|
|
644
|
+
* @param {SQLError} err
|
|
645
|
+
* @returns {void}
|
|
646
|
+
*/
|
|
471
647
|
function sqlError (tx, err) {
|
|
472
648
|
error(err);
|
|
473
649
|
}
|
|
650
|
+
/**
|
|
651
|
+
* @returns {void}
|
|
652
|
+
*/
|
|
474
653
|
function finish () {
|
|
475
654
|
if (cb) {
|
|
476
655
|
cb(tx, success);
|
|
@@ -483,19 +662,19 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
483
662
|
// This approach has the advantage of auto-deleting indexes via the DROP TABLE
|
|
484
663
|
const sql = 'CREATE TABLE ' + escapedTmpStoreNameSQL +
|
|
485
664
|
'(' + listColInfoToPreserve + escapedNewIndexNameSQL + ' ' + newNameType + ')';
|
|
486
|
-
CFG.DEBUG
|
|
665
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
487
666
|
tx.executeSql(sql, [], function () {
|
|
488
667
|
const sql = 'INSERT INTO ' + escapedTmpStoreNameSQL + '(' +
|
|
489
668
|
listColsToPreserve + escapedNewIndexNameSQL +
|
|
490
669
|
') SELECT ' + listColsToPreserve + util.escapeIndexNameForSQL(oldName) + ' FROM ' + escapedStoreNameSQL;
|
|
491
|
-
CFG.DEBUG
|
|
670
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
492
671
|
tx.executeSql(sql, [], function () {
|
|
493
672
|
const sql = 'DROP TABLE ' + escapedStoreNameSQL;
|
|
494
|
-
CFG.DEBUG
|
|
673
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
495
674
|
tx.executeSql(sql, [], function () {
|
|
496
675
|
const sql = 'ALTER TABLE ' + escapedTmpStoreNameSQL + ' RENAME TO ' + escapedStoreNameSQL;
|
|
497
|
-
CFG.DEBUG
|
|
498
|
-
tx.executeSql(sql, [], function (tx
|
|
676
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
677
|
+
tx.executeSql(sql, [], function (tx) {
|
|
499
678
|
if (!CFG.useSQLiteIndexes) {
|
|
500
679
|
finish();
|
|
501
680
|
return;
|
|
@@ -507,14 +686,20 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
507
686
|
escapedStoreNameSQL.slice(1, -1) + '^5' + escapedIndexNameSQL.slice(1, -1)
|
|
508
687
|
);
|
|
509
688
|
// const sql = 'DROP INDEX IF EXISTS ' + escapedIndexToRecreate;
|
|
510
|
-
// CFG.DEBUG
|
|
689
|
+
// if (CFG.DEBUG) { console.log(sql); }
|
|
511
690
|
// tx.executeSql(sql, [], function () {
|
|
512
691
|
const sql = 'CREATE INDEX ' +
|
|
513
692
|
escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
|
|
514
|
-
CFG.DEBUG
|
|
515
|
-
tx.executeSql(
|
|
516
|
-
|
|
517
|
-
|
|
693
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
694
|
+
tx.executeSql(
|
|
695
|
+
sql,
|
|
696
|
+
[],
|
|
697
|
+
resolve,
|
|
698
|
+
/** @type {SQLStatementErrorCallback} */
|
|
699
|
+
(function (tx, err) {
|
|
700
|
+
reject(err);
|
|
701
|
+
})
|
|
702
|
+
);
|
|
518
703
|
// }, function (tx, err) {
|
|
519
704
|
// reject(err);
|
|
520
705
|
// });
|
|
@@ -524,32 +709,56 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
524
709
|
const escapedIndexToRecreate = util.sqlQuote('sk_' + escapedStoreNameSQL.slice(1, -1));
|
|
525
710
|
// Chrome erring here if not dropped first; Node does not
|
|
526
711
|
const sql = 'DROP INDEX IF EXISTS ' + escapedIndexToRecreate;
|
|
527
|
-
CFG.DEBUG
|
|
528
|
-
tx.executeSql(
|
|
529
|
-
|
|
530
|
-
'
|
|
531
|
-
|
|
532
|
-
|
|
712
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
713
|
+
tx.executeSql(
|
|
714
|
+
sql, [], function () {
|
|
715
|
+
const sql = 'CREATE INDEX ' + escapedIndexToRecreate +
|
|
716
|
+
' ON ' + escapedStoreNameSQL + '("key")';
|
|
717
|
+
if (CFG.DEBUG) { console.log(sql); }
|
|
718
|
+
tx.executeSql(
|
|
719
|
+
sql, [], resolve,
|
|
720
|
+
/** @type {SQLStatementErrorCallback} */
|
|
721
|
+
(function (tx, err) {
|
|
722
|
+
reject(err);
|
|
723
|
+
})
|
|
724
|
+
);
|
|
725
|
+
},
|
|
726
|
+
/** @type {SQLStatementErrorCallback} */
|
|
727
|
+
(function (tx, err) {
|
|
533
728
|
reject(err);
|
|
534
|
-
})
|
|
535
|
-
|
|
536
|
-
reject(err);
|
|
537
|
-
});
|
|
729
|
+
})
|
|
730
|
+
);
|
|
538
731
|
})
|
|
539
732
|
);
|
|
540
|
-
SyncPromise.all(indexCreations).then(
|
|
733
|
+
SyncPromise.all(indexCreations).then(
|
|
734
|
+
finish,
|
|
735
|
+
/** @type {(reason: any) => PromiseLike<never>} */
|
|
736
|
+
(error)
|
|
737
|
+
).catch((err) => {
|
|
541
738
|
console.log('Index rename error');
|
|
542
739
|
throw err;
|
|
543
740
|
});
|
|
544
|
-
}, sqlError);
|
|
545
|
-
}, sqlError);
|
|
546
|
-
}, sqlError);
|
|
547
|
-
}, sqlError);
|
|
741
|
+
}, /** @type {SQLStatementErrorCallback} */ (sqlError));
|
|
742
|
+
}, /** @type {SQLStatementErrorCallback} */ (sqlError));
|
|
743
|
+
}, /** @type {SQLStatementErrorCallback} */ (sqlError));
|
|
744
|
+
}, /** @type {SQLStatementErrorCallback} */ (sqlError));
|
|
548
745
|
});
|
|
549
746
|
};
|
|
550
747
|
|
|
748
|
+
/**
|
|
749
|
+
* @typedef {any} AnyValue
|
|
750
|
+
*/
|
|
751
|
+
|
|
551
752
|
Object.defineProperty(IDBIndex, Symbol.hasInstance, {
|
|
552
|
-
|
|
753
|
+
/**
|
|
754
|
+
* @param {AnyValue} obj
|
|
755
|
+
* @returns {boolean}
|
|
756
|
+
*/
|
|
757
|
+
value: (obj) => util.isObj(obj) &&
|
|
758
|
+
'openCursor' in obj &&
|
|
759
|
+
typeof obj.openCursor === 'function' &&
|
|
760
|
+
'multiEntry' in obj &&
|
|
761
|
+
typeof obj.multiEntry === 'boolean'
|
|
553
762
|
});
|
|
554
763
|
|
|
555
764
|
util.defineReadonlyOuterInterface(IDBIndex.prototype, readonlyProperties);
|
|
@@ -561,26 +770,61 @@ Object.defineProperty(IDBIndex, 'prototype', {
|
|
|
561
770
|
writable: false
|
|
562
771
|
});
|
|
563
772
|
|
|
564
|
-
|
|
773
|
+
/**
|
|
774
|
+
* @param {number|null} count
|
|
775
|
+
* @param {boolean} unboundedDisallowed
|
|
776
|
+
* @param {IDBIndexFull} index
|
|
777
|
+
* @param {boolean} hasKey
|
|
778
|
+
* @param {import('./Key.js').Value|import('./Key.js').Key} range
|
|
779
|
+
* @param {"value"|"key"|"count"} opType
|
|
780
|
+
* @param {boolean} multiChecks
|
|
781
|
+
* @param {string[]} sql
|
|
782
|
+
* @param {string[]} sqlValues
|
|
783
|
+
* @param {SQLTransaction} tx
|
|
784
|
+
* @param {null|undefined} args
|
|
785
|
+
* @param {(result: number|undefined|[]|AnyValue|AnyValue[]) => void} success
|
|
786
|
+
* @param {(tx: SQLTransaction, err: SQLError) => void} error
|
|
787
|
+
* @returns {void}
|
|
788
|
+
*/
|
|
789
|
+
function executeFetchIndexData (
|
|
790
|
+
count, unboundedDisallowed, index, hasKey, range, opType,
|
|
791
|
+
multiChecks, sql, sqlValues, tx, args, success, error
|
|
792
|
+
) {
|
|
565
793
|
if (unboundedDisallowed) {
|
|
566
794
|
count = 1;
|
|
567
795
|
}
|
|
568
796
|
if (count) {
|
|
569
|
-
sql.push('LIMIT', count);
|
|
797
|
+
sql.push('LIMIT', String(count));
|
|
570
798
|
}
|
|
571
799
|
const isCount = opType === 'count';
|
|
572
|
-
CFG.DEBUG
|
|
800
|
+
if (CFG.DEBUG) { console.log('Trying to fetch data for Index', sql.join(' '), sqlValues); }
|
|
573
801
|
tx.executeSql(sql.join(' '), sqlValues, function (tx, data) {
|
|
574
802
|
const records = [];
|
|
575
803
|
let recordCount = 0;
|
|
576
804
|
const decode = isCount
|
|
577
805
|
? () => { /* */ }
|
|
578
806
|
: (opType === 'key'
|
|
579
|
-
|
|
807
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- JSDoc
|
|
808
|
+
?
|
|
809
|
+
/**
|
|
810
|
+
* @param {{
|
|
811
|
+
* key: string
|
|
812
|
+
* }} record
|
|
813
|
+
* @returns {import('./Key.js').ValueType|undefined}
|
|
814
|
+
*/
|
|
815
|
+
(record) => {
|
|
580
816
|
// Key.convertValueToKey(record.key); // Already validated before storage
|
|
581
817
|
return Key.decode(util.unescapeSQLiteResponse(record.key));
|
|
582
818
|
}
|
|
583
|
-
|
|
819
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- JSDoc
|
|
820
|
+
:
|
|
821
|
+
/**
|
|
822
|
+
* @param {{
|
|
823
|
+
* value: string
|
|
824
|
+
* }} record
|
|
825
|
+
* @returns {AnyValue}
|
|
826
|
+
*/
|
|
827
|
+
(record) => { // when opType is value
|
|
584
828
|
return Sca.decode(util.unescapeSQLiteResponse(record.value));
|
|
585
829
|
});
|
|
586
830
|
if (index.multiEntry) {
|
|
@@ -588,11 +832,23 @@ function executeFetchIndexData (count, unboundedDisallowed, index, hasKey, range
|
|
|
588
832
|
const encodedKey = Key.encode(range, index.multiEntry);
|
|
589
833
|
for (let i = 0; i < data.rows.length; i++) {
|
|
590
834
|
const row = data.rows.item(i);
|
|
591
|
-
const rowKey = Key.
|
|
835
|
+
const rowKey = /** @type {import('./Key.js').ValueTypeArray} */ (
|
|
836
|
+
Key.decode(row[escapedIndexNameForKeyCol])
|
|
837
|
+
);
|
|
592
838
|
let record;
|
|
593
839
|
if (hasKey && (
|
|
594
|
-
(multiChecks && range.some(
|
|
595
|
-
|
|
840
|
+
(multiChecks && range.some(
|
|
841
|
+
/**
|
|
842
|
+
* @param {string} check
|
|
843
|
+
* @returns {boolean}
|
|
844
|
+
*/
|
|
845
|
+
(check) => rowKey.includes(check)
|
|
846
|
+
)) || // More precise than our SQL
|
|
847
|
+
Key.isMultiEntryMatch(
|
|
848
|
+
/** @type {string} */
|
|
849
|
+
(encodedKey),
|
|
850
|
+
row[escapedIndexNameForKeyCol]
|
|
851
|
+
)
|
|
596
852
|
)) {
|
|
597
853
|
recordCount++;
|
|
598
854
|
record = row;
|
|
@@ -625,10 +881,29 @@ function executeFetchIndexData (count, unboundedDisallowed, index, hasKey, range
|
|
|
625
881
|
} else {
|
|
626
882
|
success(unboundedDisallowed ? records[0] : records);
|
|
627
883
|
}
|
|
628
|
-
}, error);
|
|
884
|
+
}, /** @type {SQLStatementErrorCallback} */ (error));
|
|
629
885
|
}
|
|
630
886
|
|
|
631
|
-
|
|
887
|
+
/**
|
|
888
|
+
* @param {boolean} nullDisallowed
|
|
889
|
+
* @param {IDBIndexFull} index
|
|
890
|
+
* @param {import('./Key.js').Value|import('./Key.js').Key} range
|
|
891
|
+
* @param {"value"|"key"|"count"} opType
|
|
892
|
+
* @param {boolean} multiChecks
|
|
893
|
+
* @returns {[
|
|
894
|
+
* nullDisallowed: boolean,
|
|
895
|
+
* index: IDBIndexFull,
|
|
896
|
+
* hasRange: boolean,
|
|
897
|
+
* range: import('./Key.js').Value|import('./Key.js').Key,
|
|
898
|
+
* opType: "value"|"key"|"count",
|
|
899
|
+
* multiChecks: boolean,
|
|
900
|
+
* sql: string[],
|
|
901
|
+
* sqlValues: string[]
|
|
902
|
+
* ]}
|
|
903
|
+
*/
|
|
904
|
+
function buildFetchIndexDataSQL (
|
|
905
|
+
nullDisallowed, index, range, opType, multiChecks
|
|
906
|
+
) {
|
|
632
907
|
const hasRange = nullDisallowed || !util.isNullish(range);
|
|
633
908
|
const col = opType === 'count' ? 'key' : opType; // It doesn't matter which column we use for 'count' as long as it is valid
|
|
634
909
|
const sql = [
|
|
@@ -638,19 +913,27 @@ function buildFetchIndexDataSQL (nullDisallowed, index, range, opType, multiChec
|
|
|
638
913
|
'FROM', util.escapeStoreNameForSQL(index.objectStore.__currentName),
|
|
639
914
|
'WHERE', util.escapeIndexNameForSQL(index.name), 'NOT NULL'
|
|
640
915
|
];
|
|
916
|
+
|
|
917
|
+
/** @type {string[]} */
|
|
641
918
|
const sqlValues = [];
|
|
642
919
|
if (hasRange) {
|
|
643
920
|
if (multiChecks) {
|
|
644
921
|
sql.push('AND (');
|
|
645
|
-
|
|
646
|
-
|
|
922
|
+
/** @type {import('./Key.js').KeyPathArray} */ (
|
|
923
|
+
range
|
|
924
|
+
).forEach((innerKey, i) => {
|
|
925
|
+
if (i > 0) { sql.push('OR'); }
|
|
647
926
|
sql.push(util.escapeIndexNameForSQL(index.name), "LIKE ? ESCAPE '^' ");
|
|
648
|
-
sqlValues.push('%' + util.sqlLIKEEscape(
|
|
927
|
+
sqlValues.push('%' + util.sqlLIKEEscape(
|
|
928
|
+
/** @type {string} */ (Key.encode(innerKey, index.multiEntry))
|
|
929
|
+
) + '%');
|
|
649
930
|
});
|
|
650
931
|
sql.push(')');
|
|
651
932
|
} else if (index.multiEntry) {
|
|
652
933
|
sql.push('AND', util.escapeIndexNameForSQL(index.name), "LIKE ? ESCAPE '^'");
|
|
653
|
-
sqlValues.push('%' + util.sqlLIKEEscape(
|
|
934
|
+
sqlValues.push('%' + util.sqlLIKEEscape(
|
|
935
|
+
/** @type {string} */ (Key.encode(range, index.multiEntry))
|
|
936
|
+
) + '%');
|
|
654
937
|
} else {
|
|
655
938
|
const convertedRange = convertValueToKeyRange(range, nullDisallowed);
|
|
656
939
|
setSQLForKeyRange(convertedRange, util.escapeIndexNameForSQL(index.name), sql, sqlValues, true, false);
|