@livestore/wa-sqlite 0.0.0-snapshot-b9a2e1dee494215d8c403be013e25cbf4d2cf380

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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/README.md +64 -0
  4. package/dist/fts5/wa-sqlite.mjs +2 -0
  5. package/dist/fts5/wa-sqlite.node.mjs +2 -0
  6. package/dist/fts5/wa-sqlite.node.wasm +0 -0
  7. package/dist/fts5/wa-sqlite.wasm +0 -0
  8. package/dist/wa-sqlite-async.mjs +2 -0
  9. package/dist/wa-sqlite-async.wasm +0 -0
  10. package/dist/wa-sqlite-jspi.mjs +2 -0
  11. package/dist/wa-sqlite-jspi.wasm +0 -0
  12. package/dist/wa-sqlite.mjs +2 -0
  13. package/dist/wa-sqlite.node.mjs +2 -0
  14. package/dist/wa-sqlite.node.wasm +0 -0
  15. package/dist/wa-sqlite.wasm +0 -0
  16. package/package.json +57 -0
  17. package/src/FacadeVFS.js +681 -0
  18. package/src/VFS.js +222 -0
  19. package/src/WebLocksMixin.js +414 -0
  20. package/src/examples/AccessHandlePoolVFS.js +458 -0
  21. package/src/examples/IDBBatchAtomicVFS.js +827 -0
  22. package/src/examples/IDBMirrorVFS.js +889 -0
  23. package/src/examples/MemoryAsyncVFS.js +100 -0
  24. package/src/examples/MemoryVFS.js +176 -0
  25. package/src/examples/OPFSAdaptiveVFS.js +437 -0
  26. package/src/examples/OPFSAnyContextVFS.js +300 -0
  27. package/src/examples/OPFSCoopSyncVFS.js +590 -0
  28. package/src/examples/OPFSPermutedVFS.js +1217 -0
  29. package/src/examples/README.md +89 -0
  30. package/src/examples/tag.js +82 -0
  31. package/src/sqlite-api.js +1339 -0
  32. package/src/sqlite-constants.js +275 -0
  33. package/src/types/globals.d.ts +60 -0
  34. package/src/types/index.d.ts +1531 -0
  35. package/src/types/tsconfig.json +6 -0
  36. package/test/AccessHandlePoolVFS.test.js +27 -0
  37. package/test/IDBBatchAtomicVFS.test.js +97 -0
  38. package/test/IDBMirrorVFS.test.js +27 -0
  39. package/test/MemoryAsyncVFS.test.js +27 -0
  40. package/test/MemoryVFS.test.js +27 -0
  41. package/test/OPFSAdaptiveVFS.test.js +27 -0
  42. package/test/OPFSAnyContextVFS.test.js +27 -0
  43. package/test/OPFSCoopSyncVFS.test.js +27 -0
  44. package/test/OPFSPermutedVFS.test.js +27 -0
  45. package/test/TestContext.js +96 -0
  46. package/test/WebLocksMixin.test.js +521 -0
  47. package/test/api.test.js +49 -0
  48. package/test/api_exec.js +89 -0
  49. package/test/api_misc.js +63 -0
  50. package/test/api_statements.js +447 -0
  51. package/test/callbacks.test.js +581 -0
  52. package/test/data/idbv5.json +1 -0
  53. package/test/sql.test.js +64 -0
  54. package/test/sql_0001.js +49 -0
  55. package/test/sql_0002.js +52 -0
  56. package/test/sql_0003.js +83 -0
  57. package/test/sql_0004.js +81 -0
  58. package/test/sql_0005.js +76 -0
  59. package/test/test-worker.js +204 -0
  60. package/test/vfs_xAccess.js +2 -0
  61. package/test/vfs_xClose.js +52 -0
  62. package/test/vfs_xOpen.js +91 -0
  63. package/test/vfs_xRead.js +38 -0
  64. package/test/vfs_xWrite.js +36 -0
@@ -0,0 +1,1339 @@
1
+ // Copyright 2021 Roy T. Hashimoto. All Rights Reserved.
2
+
3
+ import * as SQLite from './sqlite-constants.js';
4
+ export * from './sqlite-constants.js';
5
+
6
+ const MAX_INT64 = 0x7fffffffffffffffn;
7
+ const MIN_INT64 = -0x8000000000000000n;
8
+
9
+ // const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
10
+
11
+ export class SQLiteError extends Error {
12
+ constructor(message, code) {
13
+ super(message);
14
+ this.code = code;
15
+ }
16
+ }
17
+
18
+ // const async = true;
19
+ const async = false;
20
+
21
+ /**
22
+ * Builds a Javascript API from the Emscripten module. This API is still
23
+ * low-level and closely corresponds to the C API exported by the module,
24
+ * but differs in some specifics like throwing exceptions on errors.
25
+ * @param {*} Module SQLite Emscripten module
26
+ * @returns {SQLiteAPI}
27
+ */
28
+ export function Factory(Module) {
29
+ /** @type {SQLiteAPI} */ const sqlite3 = {};
30
+
31
+ Module.retryOps = [];
32
+ const sqliteFreeAddress = Module._getSqliteFree();
33
+
34
+ // Allocate some space for 32-bit returned values.
35
+ const tmp = Module._malloc(8);
36
+ const tmpPtr = [tmp, tmp + 4];
37
+
38
+ const textEncoder = new TextEncoder();
39
+ // Convert a JS string to a C string. sqlite3_malloc is used to allocate
40
+ // memory (use sqlite3_free to deallocate).
41
+ function createUTF8(s) {
42
+ if (typeof s !== 'string') return 0;
43
+ const utf8 = textEncoder.encode(s);
44
+ const zts = Module._sqlite3_malloc(utf8.byteLength + 1);
45
+ Module.HEAPU8.set(utf8, zts);
46
+ Module.HEAPU8[zts + utf8.byteLength] = 0;
47
+ return zts;
48
+ }
49
+
50
+ /**
51
+ * Concatenate 32-bit numbers into a 64-bit (signed) BigInt.
52
+ * @param {number} lo32
53
+ * @param {number} hi32
54
+ * @returns {bigint}
55
+ */
56
+ function cvt32x2ToBigInt(lo32, hi32) {
57
+ return (BigInt(hi32) << 32n) | (BigInt(lo32) & 0xffffffffn);
58
+ }
59
+
60
+ /**
61
+ * Concatenate 32-bit numbers and return as number or BigInt, depending
62
+ * on the value.
63
+ * @param {number} lo32
64
+ * @param {number} hi32
65
+ * @returns {number|bigint}
66
+ */
67
+ const cvt32x2AsSafe = (function() {
68
+ const hiMax = BigInt(Number.MAX_SAFE_INTEGER) >> 32n;
69
+ const hiMin = BigInt(Number.MIN_SAFE_INTEGER) >> 32n;
70
+
71
+ return function(lo32, hi32) {
72
+ if (hi32 > hiMax || hi32 < hiMin) {
73
+ // Can't be expressed as a Number so use BigInt.
74
+ return cvt32x2ToBigInt(lo32, hi32);
75
+ } else {
76
+ // Combine the upper and lower 32-bit numbers. The complication is
77
+ // that lo32 is a signed integer which makes manipulating its bits
78
+ // a little tricky - the sign bit gets handled separately.
79
+ return (hi32 * 0x100000000) + (lo32 & 0x7fffffff) - (lo32 & 0x80000000);
80
+ }
81
+ }
82
+ })();
83
+
84
+ const databases = new Set();
85
+ function verifyDatabase(db) {
86
+ if (!databases.has(db)) {
87
+ throw new SQLiteError('not a database', SQLite.SQLITE_MISUSE);
88
+ }
89
+ }
90
+
91
+ const mapStmtToDB = new Map();
92
+ function verifyStatement(stmt) {
93
+ if (!mapStmtToDB.has(stmt)) {
94
+ throw new SQLiteError('not a statement', SQLite.SQLITE_MISUSE);
95
+ }
96
+ }
97
+
98
+ sqlite3.bind_collection = function(stmt, bindings) {
99
+ verifyStatement(stmt);
100
+ const isArray = Array.isArray(bindings);
101
+ const nBindings = sqlite3.bind_parameter_count(stmt);
102
+ for (let i = 1; i <= nBindings; ++i) {
103
+ const key = isArray ? i - 1 : sqlite3.bind_parameter_name(stmt, i);
104
+ const value = bindings[key];
105
+ if (value !== undefined) {
106
+ sqlite3.bind(stmt, i, value);
107
+ }
108
+ }
109
+ return SQLite.SQLITE_OK;
110
+ };
111
+
112
+ sqlite3.bind = function(stmt, i, value) {
113
+ verifyStatement(stmt);
114
+ switch (typeof value) {
115
+ case 'number':
116
+ if (value === (value | 0)) {
117
+ return sqlite3.bind_int(stmt, i, value);
118
+ } else {
119
+ return sqlite3.bind_double(stmt, i, value);
120
+ }
121
+ case 'string':
122
+ return sqlite3.bind_text(stmt, i, value);
123
+ case "boolean":
124
+ return sqlite3.bind_int(stmt, i, value ? 1 : 0);
125
+ default:
126
+ if (value instanceof Uint8Array || Array.isArray(value)) {
127
+ return sqlite3.bind_blob(stmt, i, value);
128
+ } else if (value === null) {
129
+ return sqlite3.bind_null(stmt, i);
130
+ } else if (typeof value === 'bigint') {
131
+ return sqlite3.bind_int64(stmt, i, value);
132
+ } else if (value === undefined) {
133
+ // Existing binding (or NULL) will be used.
134
+ return SQLite.SQLITE_NOTICE;
135
+ } else {
136
+ console.warn('unknown binding converted to null', value);
137
+ return sqlite3.bind_null(stmt, i);
138
+ }
139
+ }
140
+ };
141
+
142
+ sqlite3.bind_blob = (function() {
143
+ const fname = 'sqlite3_bind_blob';
144
+ const f = Module.cwrap(fname, ...decl('nnnnn:n'));
145
+ return function(stmt, i, value) {
146
+ verifyStatement(stmt);
147
+ // @ts-ignore
148
+ const byteLength = value.byteLength ?? value.length;
149
+ const ptr = Module._sqlite3_malloc(byteLength);
150
+ Module.HEAPU8.subarray(ptr).set(value);
151
+ const result = f(stmt, i, ptr, byteLength, sqliteFreeAddress);
152
+ return check(fname, result, mapStmtToDB.get(stmt));
153
+ };
154
+ })();
155
+
156
+ sqlite3.bind_parameter_count = (function() {
157
+ const fname = 'sqlite3_bind_parameter_count';
158
+ const f = Module.cwrap(fname, ...decl('n:n'));
159
+ return function(stmt) {
160
+ verifyStatement(stmt);
161
+ const result = f(stmt);
162
+ return result;
163
+ };
164
+ })();
165
+
166
+ sqlite3.bind_double = (function() {
167
+ const fname = 'sqlite3_bind_double';
168
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
169
+ return function(stmt, i, value) {
170
+ verifyStatement(stmt);
171
+ const result = f(stmt, i, value);
172
+ return check(fname, result, mapStmtToDB.get(stmt));
173
+ };
174
+ })();
175
+
176
+ sqlite3.bind_int = (function() {
177
+ const fname = 'sqlite3_bind_int';
178
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
179
+ return function(stmt, i, value) {
180
+ verifyStatement(stmt);
181
+ if (value > 0x7fffffff || value < -0x80000000) return SQLite.SQLITE_RANGE;
182
+
183
+ const result = f(stmt, i, value);
184
+ return check(fname, result, mapStmtToDB.get(stmt));
185
+ };
186
+ })();
187
+
188
+ sqlite3.bind_int64 = (function() {
189
+ const fname = 'sqlite3_bind_int64';
190
+ const f = Module.cwrap(fname, ...decl('nnnn:n'));
191
+ return function(stmt, i, value) {
192
+ verifyStatement(stmt);
193
+ if (value > MAX_INT64 || value < MIN_INT64) return SQLite.SQLITE_RANGE;
194
+
195
+ const lo32 = value & 0xffffffffn;
196
+ const hi32 = value >> 32n;
197
+ const result = f(stmt, i, Number(lo32), Number(hi32));
198
+ return check(fname, result, mapStmtToDB.get(stmt));
199
+ };
200
+ })();
201
+
202
+ sqlite3.bind_null = (function() {
203
+ const fname = 'sqlite3_bind_null';
204
+ const f = Module.cwrap(fname, ...decl('nn:n'));
205
+ return function(stmt, i) {
206
+ verifyStatement(stmt);
207
+ const result = f(stmt, i);
208
+ return check(fname, result, mapStmtToDB.get(stmt));
209
+ };
210
+ })();
211
+
212
+ sqlite3.bind_parameter_name = (function() {
213
+ const fname = 'sqlite3_bind_parameter_name';
214
+ const f = Module.cwrap(fname, ...decl('n:s'));
215
+ return function(stmt, i) {
216
+ verifyStatement(stmt);
217
+ const result = f(stmt, i);
218
+ return result;
219
+ };
220
+ })();
221
+
222
+ sqlite3.bind_text = (function() {
223
+ const fname = 'sqlite3_bind_text';
224
+ const f = Module.cwrap(fname, ...decl('nnnnn:n'));
225
+ return function(stmt, i, value) {
226
+ verifyStatement(stmt);
227
+ const ptr = createUTF8(value);
228
+ const result = f(stmt, i, ptr, -1, sqliteFreeAddress);
229
+ return check(fname, result, mapStmtToDB.get(stmt));
230
+ };
231
+ })();
232
+
233
+ sqlite3.changes = (function() {
234
+ const fname = 'sqlite3_changes';
235
+ const f = Module.cwrap(fname, ...decl('n:n'));
236
+ return function(db) {
237
+ verifyDatabase(db);
238
+ const result = f(db);
239
+ return result;
240
+ };
241
+ })();
242
+
243
+ sqlite3.deserialize = (function() {
244
+ const fname = 'sqlite3_deserialize';
245
+ const f = Module.cwrap(fname, ...decl('nnnnnn:n'));
246
+ return function(db, schema, data, szDb, szBuf, flags) {
247
+ verifyDatabase(db);
248
+ const ptr = Module._sqlite3_malloc(szDb);
249
+ Module.HEAPU8.subarray(ptr).set(data);
250
+ const result = f(db, schema, ptr, szDb, szBuf, flags);
251
+ return result;
252
+ };
253
+ })();
254
+
255
+ const SQLITE_SERIALIZE_NOCOPY = 0x0_01
256
+
257
+ sqlite3.serialize = (function() {
258
+ const fname = 'sqlite3_serialize';
259
+ const f = Module.cwrap(fname, ...decl('nsnn:n'));
260
+ return function(db, schema) {
261
+ verifyDatabase(db);
262
+ const piSize = tmpPtr[0];
263
+ let address = f(db, schema, piSize, 0); // 0 means no flags
264
+ if (address === 0) {
265
+ address = f(db, schema, piSize, SQLITE_SERIALIZE_NOCOPY);
266
+ const size = Module.getValue(piSize, '*');
267
+ const result = Module.HEAPU8.subarray(address, address + size);
268
+ // NOTE Given that the memory is owned by SQLite, we must copy it.
269
+ // Warning: We're not super confident yet about this code path. There might be dragons.
270
+ return new Uint8Array(result.slice());
271
+ } else {
272
+ const size = Module.getValue(piSize, '*');
273
+ const result = Module.HEAPU8.subarray(address, address + size);
274
+ // Copy the data immediately, then free the SQLite buffer to prevent ref-count issues
275
+ const copy = new Uint8Array(result);
276
+ Module._sqlite3_free(address);
277
+ return copy;
278
+ }
279
+ };
280
+ })();
281
+
282
+ // https://www.sqlite.org/c3ref/backup_finish.html
283
+ // https://www.sqlite.org/backup.html
284
+ sqlite3.backup = (function() {
285
+ const fInit = Module.cwrap('sqlite3_backup_init', ...decl('nsns:n'));
286
+ const fStep = Module.cwrap('sqlite3_backup_step', ...decl('nn:n'));
287
+ const fFinish = Module.cwrap('sqlite3_backup_finish', ...decl('n:n'));
288
+ return function(dest, destName, source, sourceName) {
289
+ verifyDatabase(dest);
290
+ verifyDatabase(source);
291
+ const backup = fInit(dest, destName, source, sourceName);
292
+ if (backup === 0) {
293
+ const errMsg = Module.ccall('sqlite3_errmsg', 'string', ['number'], [dest]);
294
+ throw new SQLiteError(`backup failed: ${errMsg}`, SQLite.SQLITE_ERROR);
295
+ }
296
+ // TODO also allow run in chunks with some yielding mechanism
297
+ fStep(backup, -1); // -1 means do it in one go
298
+ return fFinish(backup);
299
+ };
300
+ })();
301
+
302
+
303
+ // TODO implement this at some point
304
+ // sqlite3.backup_step = (function() {
305
+
306
+ sqlite3.clear_bindings = (function() {
307
+ const fname = 'sqlite3_clear_bindings';
308
+ const f = Module.cwrap(fname, ...decl('n:n'));
309
+ return function(stmt) {
310
+ verifyStatement(stmt);
311
+ const result = f(stmt);
312
+ return check(fname, result, mapStmtToDB.get(stmt));
313
+ };
314
+ })();
315
+
316
+ sqlite3.close = (function() {
317
+ const fname = 'sqlite3_close';
318
+ const f = Module.cwrap(fname, ...decl('n:n'), { async });
319
+ // return async function(db) {
320
+ return function(db) {
321
+ verifyDatabase(db);
322
+ // const result = await f(db);
323
+ const result = f(db);
324
+ databases.delete(db);
325
+ return check(fname, result, db);
326
+ };
327
+ })();
328
+
329
+ sqlite3.column = function(stmt, iCol) {
330
+ verifyStatement(stmt);
331
+ const type = sqlite3.column_type(stmt, iCol);
332
+ switch (type) {
333
+ case SQLite.SQLITE_BLOB:
334
+ return sqlite3.column_blob(stmt, iCol);
335
+ case SQLite.SQLITE_FLOAT:
336
+ return sqlite3.column_double(stmt, iCol);
337
+ case SQLite.SQLITE_INTEGER:
338
+ const lo32 = sqlite3.column_int(stmt, iCol);
339
+ const hi32 = Module.getTempRet0();
340
+ return cvt32x2AsSafe(lo32, hi32);
341
+ case SQLite.SQLITE_NULL:
342
+ return null;
343
+ case SQLite.SQLITE_TEXT:
344
+ return sqlite3.column_text(stmt, iCol);
345
+ default:
346
+ throw new SQLiteError('unknown type', type);
347
+ }
348
+ };
349
+
350
+ sqlite3.column_blob = (function() {
351
+ const fname = 'sqlite3_column_blob';
352
+ const f = Module.cwrap(fname, ...decl('nn:n'));
353
+ return function(stmt, iCol) {
354
+ verifyStatement(stmt);
355
+ const nBytes = sqlite3.column_bytes(stmt, iCol);
356
+ const address = f(stmt, iCol);
357
+ if (address === 0) {
358
+ return null; // Handle NULL BLOBs
359
+ }
360
+ const result = Module.HEAPU8.subarray(address, address + nBytes);
361
+ return new Uint8Array(result); // Ensure a copy is returned
362
+ };
363
+ })();
364
+
365
+ sqlite3.column_bytes = (function() {
366
+ const fname = 'sqlite3_column_bytes';
367
+ const f = Module.cwrap(fname, ...decl('nn:n'));
368
+ return function(stmt, iCol) {
369
+ verifyStatement(stmt);
370
+ const result = f(stmt, iCol);
371
+ return result;
372
+ };
373
+ })();
374
+
375
+ sqlite3.column_count = (function() {
376
+ const fname = 'sqlite3_column_count';
377
+ const f = Module.cwrap(fname, ...decl('n:n'));
378
+ return function(stmt) {
379
+ verifyStatement(stmt);
380
+ const result = f(stmt);
381
+ return result;
382
+ };
383
+ })();
384
+
385
+ sqlite3.column_double = (function() {
386
+ const fname = 'sqlite3_column_double';
387
+ const f = Module.cwrap(fname, ...decl('nn:n'));
388
+ return function(stmt, iCol) {
389
+ verifyStatement(stmt);
390
+ const result = f(stmt, iCol);
391
+ return result;
392
+ };
393
+ })();
394
+
395
+ sqlite3.column_int = (function() {
396
+ // Retrieve int64 but use only the lower 32 bits. The upper 32-bits are
397
+ // accessible with Module.getTempRet0().
398
+ const fname = 'sqlite3_column_int64';
399
+ const f = Module.cwrap(fname, ...decl('nn:n'));
400
+ return function(stmt, iCol) {
401
+ verifyStatement(stmt);
402
+ const result = f(stmt, iCol);
403
+ return result;
404
+ };
405
+ })();
406
+
407
+ sqlite3.column_int64 = (function() {
408
+ const fname = 'sqlite3_column_int64';
409
+ const f = Module.cwrap(fname, ...decl('nn:n'));
410
+ return function(stmt, iCol) {
411
+ verifyStatement(stmt);
412
+ const lo32 = f(stmt, iCol);
413
+ const hi32 = Module.getTempRet0();
414
+ const result = cvt32x2ToBigInt(lo32, hi32);
415
+ return result;
416
+ };
417
+ })();
418
+
419
+ sqlite3.column_name = (function() {
420
+ const fname = 'sqlite3_column_name';
421
+ const f = Module.cwrap(fname, ...decl('nn:s'));
422
+ return function(stmt, iCol) {
423
+ verifyStatement(stmt);
424
+ const result = f(stmt, iCol);
425
+ return result;
426
+ };
427
+ })();
428
+
429
+ sqlite3.column_names = function(stmt) {
430
+ const columns = [];
431
+ const nColumns = sqlite3.column_count(stmt);
432
+ for (let i = 0; i < nColumns; ++i) {
433
+ columns.push(sqlite3.column_name(stmt, i));
434
+ }
435
+ return columns;
436
+ };
437
+
438
+ sqlite3.column_text = (function() {
439
+ const fname = 'sqlite3_column_text';
440
+ const f = Module.cwrap(fname, ...decl('nn:s'));
441
+ return function(stmt, iCol) {
442
+ verifyStatement(stmt);
443
+ const result = f(stmt, iCol);
444
+ return result;
445
+ };
446
+ })();
447
+
448
+ sqlite3.column_type = (function() {
449
+ const fname = 'sqlite3_column_type';
450
+ const f = Module.cwrap(fname, ...decl('nn:n'));
451
+ return function(stmt, iCol) {
452
+ verifyStatement(stmt);
453
+ const result = f(stmt, iCol);
454
+ return result;
455
+ };
456
+ })();
457
+
458
+ sqlite3.create_function = function(db, zFunctionName, nArg, eTextRep, pApp, xFunc, xStep, xFinal) {
459
+ verifyDatabase(db);
460
+
461
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
462
+ function adapt(f) {
463
+ // return f instanceof AsyncFunction ?
464
+ // (async (ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n))) :
465
+ // ((ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)));
466
+ return ((ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)));
467
+ }
468
+
469
+ const result = Module.create_function(
470
+ db,
471
+ zFunctionName,
472
+ nArg,
473
+ eTextRep,
474
+ pApp,
475
+ xFunc && adapt(xFunc),
476
+ xStep && adapt(xStep),
477
+ xFinal);
478
+ return check('sqlite3_create_function', result, db);
479
+ };
480
+
481
+ sqlite3.data_count = (function() {
482
+ const fname = 'sqlite3_data_count';
483
+ const f = Module.cwrap(fname, ...decl('n:n'));
484
+ return function(stmt) {
485
+ verifyStatement(stmt);
486
+ const result = f(stmt);
487
+ return result;
488
+ };
489
+ })();
490
+
491
+ // sqlite3.exec = async function(db, sql, callback) {
492
+ // for await (const stmt of sqlite3.statements(db, sql)) {
493
+ // let columns;
494
+ // while (await sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
495
+ // if (callback) {
496
+ // columns = columns ?? sqlite3.column_names(stmt);
497
+ // const row = sqlite3.row(stmt);
498
+ // await callback(row, columns);
499
+ // }
500
+ // }
501
+ // }
502
+ // return SQLite.SQLITE_OK;
503
+ // };
504
+ sqlite3.exec = function(db, sql, callback) {
505
+ const stmts = sqlite3.statements(db, sql, { unscoped: true });
506
+ for (const stmt of stmts) {
507
+ let columns;
508
+ while (sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
509
+ if (callback) {
510
+ columns = columns ?? sqlite3.column_names(stmt);
511
+ const row = sqlite3.row(stmt);
512
+ callback(row, columns);
513
+ }
514
+ }
515
+ }
516
+ for (const stmt of stmts) {
517
+ sqlite3.finalize(stmt);
518
+ }
519
+ return SQLite.SQLITE_OK;
520
+ };
521
+
522
+ sqlite3.finalize = (function() {
523
+ const fname = 'sqlite3_finalize';
524
+ const f = Module.cwrap(fname, ...decl('n:n'), { async });
525
+ // return async function(stmt) {
526
+ // const result = await f(stmt);
527
+ return function(stmt) {
528
+ const result = f(stmt);
529
+ mapStmtToDB.delete(stmt)
530
+
531
+ // Don't throw on error here. Typically the error has already been
532
+ // thrown and finalize() is part of the cleanup.
533
+ return result;
534
+ };
535
+ })();
536
+
537
+ sqlite3.get_autocommit = (function() {
538
+ const fname = 'sqlite3_get_autocommit';
539
+ const f = Module.cwrap(fname, ...decl('n:n'));
540
+ return function(db) {
541
+ const result = f(db);
542
+ return result;
543
+ };
544
+ })();
545
+
546
+ sqlite3.libversion = (function() {
547
+ const fname = 'sqlite3_libversion';
548
+ const f = Module.cwrap(fname, ...decl(':s'));
549
+ return function() {
550
+ const result = f();
551
+ return result;
552
+ };
553
+ })();
554
+
555
+ sqlite3.libversion_number = (function() {
556
+ const fname = 'sqlite3_libversion_number';
557
+ const f = Module.cwrap(fname, ...decl(':n'));
558
+ return function() {
559
+ const result = f();
560
+ return result;
561
+ };
562
+ })();
563
+
564
+ sqlite3.limit = (function() {
565
+ const fname = 'sqlite3_limit';
566
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
567
+ return function(db, id, newVal) {
568
+ const result = f(db, id, newVal);
569
+ return result;
570
+ };
571
+ })();
572
+
573
+ sqlite3.open_v2 = (function() {
574
+ const fname = 'sqlite3_open_v2';
575
+ const f = Module.cwrap(fname, ...decl('snnn:n'), { async });
576
+ return async function(zFilename, flags, zVfs) {
577
+ flags = flags || SQLite.SQLITE_OPEN_CREATE | SQLite.SQLITE_OPEN_READWRITE;
578
+ zVfs = createUTF8(zVfs);
579
+ try {
580
+ // Allow retry operations.
581
+ const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs));
582
+
583
+ const db = Module.getValue(tmpPtr[0], '*');
584
+ databases.add(db);
585
+
586
+ Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
587
+ check(fname, rc, db);
588
+ return db;
589
+ } finally {
590
+ Module._sqlite3_free(zVfs);
591
+ }
592
+ };
593
+ })();
594
+
595
+ sqlite3.open_v2Sync = (function() {
596
+ const fname = 'sqlite3_open_v2';
597
+ const f = Module.cwrap(fname, ...decl('snnn:n'), { async });
598
+ return function(zFilename, flags, zVfs) {
599
+ flags = flags || SQLite.SQLITE_OPEN_CREATE | SQLite.SQLITE_OPEN_READWRITE;
600
+ zVfs = createUTF8(zVfs);
601
+ try {
602
+ // Allow retry operations.
603
+ // const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs));
604
+ const rc = f(zFilename, tmpPtr[0], flags, zVfs);
605
+
606
+ const db = Module.getValue(tmpPtr[0], '*');
607
+ databases.add(db);
608
+
609
+ Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
610
+ check(fname, rc, db);
611
+ return db;
612
+ } finally {
613
+ Module._sqlite3_free(zVfs);
614
+ }
615
+ };
616
+ })();
617
+
618
+
619
+ sqlite3.progress_handler = function(db, nProgressOps, handler, userData) {
620
+ verifyDatabase(db);
621
+ Module.progress_handler(db, nProgressOps, handler, userData);
622
+ };;
623
+
624
+ sqlite3.reset = (function() {
625
+ const fname = 'sqlite3_reset';
626
+ const f = Module.cwrap(fname, ...decl('n:n'), { async });
627
+ return function(stmt) {
628
+ verifyStatement(stmt);
629
+ const result = f(stmt);
630
+ return check(fname, result, mapStmtToDB.get(stmt));
631
+ };
632
+ })();
633
+
634
+ sqlite3.result = function(context, value) {
635
+ switch (typeof value) {
636
+ case 'number':
637
+ if (value === (value | 0)) {
638
+ sqlite3.result_int(context, value);
639
+ } else {
640
+ sqlite3.result_double(context, value);
641
+ }
642
+ break;
643
+ case 'string':
644
+ sqlite3.result_text(context, value);
645
+ break;
646
+ default:
647
+ if (value instanceof Uint8Array || Array.isArray(value)) {
648
+ sqlite3.result_blob(context, value);
649
+ } else if (value === null) {
650
+ sqlite3.result_null(context);
651
+ } else if (typeof value === 'bigint') {
652
+ return sqlite3.result_int64(context, value);
653
+ } else {
654
+ console.warn('unknown result converted to null', value);
655
+ sqlite3.result_null(context);
656
+ }
657
+ break;
658
+ }
659
+
660
+ };
661
+
662
+ sqlite3.result_blob = (function() {
663
+ const fname = 'sqlite3_result_blob';
664
+ const f = Module.cwrap(fname, ...decl('nnnn:n'));
665
+ return function(context, value) {
666
+ // @ts-ignore
667
+ const byteLength = value.byteLength ?? value.length;
668
+ const ptr = Module._sqlite3_malloc(byteLength);
669
+ Module.HEAPU8.subarray(ptr).set(value);
670
+ f(context, ptr, byteLength, sqliteFreeAddress); // void return
671
+ };
672
+ })();
673
+
674
+ sqlite3.result_double = (function() {
675
+ const fname = 'sqlite3_result_double';
676
+ const f = Module.cwrap(fname, ...decl('nn:n'));
677
+ return function(context, value) {
678
+ f(context, value); // void return
679
+ };
680
+ })();
681
+
682
+ sqlite3.result_int = (function() {
683
+ const fname = 'sqlite3_result_int';
684
+ const f = Module.cwrap(fname, ...decl('nn:n'));
685
+ return function(context, value) {
686
+ f(context, value); // void return
687
+ };
688
+ })();
689
+
690
+ sqlite3.result_int64 = (function() {
691
+ const fname = 'sqlite3_result_int64';
692
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
693
+ return function(context, value) {
694
+ if (value > MAX_INT64 || value < MIN_INT64) return SQLite.SQLITE_RANGE;
695
+
696
+ const lo32 = value & 0xffffffffn;
697
+ const hi32 = value >> 32n;
698
+ f(context, Number(lo32), Number(hi32)); // void return
699
+ };
700
+ })();
701
+
702
+ sqlite3.result_null = (function() {
703
+ const fname = 'sqlite3_result_null';
704
+ const f = Module.cwrap(fname, ...decl('n:n'));
705
+ return function(context) {
706
+ f(context); // void return
707
+ };
708
+ })();
709
+
710
+ sqlite3.result_text = (function() {
711
+ const fname = 'sqlite3_result_text';
712
+ const f = Module.cwrap(fname, ...decl('nnnn:n'));
713
+ return function(context, value) {
714
+ const ptr = createUTF8(value);
715
+ f(context, ptr, -1, sqliteFreeAddress); // void return
716
+ };
717
+ })();
718
+
719
+ sqlite3.row = function(stmt) {
720
+ const row = [];
721
+ const nColumns = sqlite3.data_count(stmt);
722
+ for (let i = 0; i < nColumns; ++i) {
723
+ const value = sqlite3.column(stmt, i);
724
+
725
+ // Copy blob if aliasing volatile WebAssembly memory. This avoids an
726
+ // unnecessary copy if users monkey patch column_blob to copy.
727
+ // @ts-ignore
728
+ row.push(value?.buffer === Module.HEAPU8.buffer ? value.slice() : value);
729
+ }
730
+ return row;
731
+ };
732
+
733
+ sqlite3.set_authorizer = function(db, xAuth, pApp) {
734
+ verifyDatabase(db);
735
+
736
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
737
+ function cvtArgs(_, iAction, p3, p4, p5, p6) {
738
+ return [
739
+ _,
740
+ iAction,
741
+ Module.UTF8ToString(p3),
742
+ Module.UTF8ToString(p4),
743
+ Module.UTF8ToString(p5),
744
+ Module.UTF8ToString(p6)
745
+ ];
746
+ };
747
+ function adapt(f) {
748
+ // return f instanceof AsyncFunction ?
749
+ // (async (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6))) :
750
+ // ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
751
+ return ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
752
+ }
753
+
754
+ const result = Module.set_authorizer(db, adapt(xAuth), pApp);
755
+ return check('sqlite3_set_authorizer', result, db);
756
+ };;
757
+
758
+ sqlite3.sql = (function() {
759
+ const fname = 'sqlite3_sql';
760
+ const f = Module.cwrap(fname, ...decl('n:s'));
761
+ return function(stmt) {
762
+ verifyStatement(stmt);
763
+ const result = f(stmt);
764
+ return result;
765
+ };
766
+ })();
767
+
768
+ sqlite3.statements = function(db, sql, options = {}) {
769
+ const prepare = Module.cwrap(
770
+ 'sqlite3_prepare_v3',
771
+ 'number',
772
+ ['number', 'number', 'number', 'number', 'number', 'number'],
773
+ // { async: true });
774
+ { async: false });
775
+
776
+ const stmts = [];
777
+
778
+ // return (async function*() {
779
+ const onFinally = [];
780
+ // try {
781
+ // Encode SQL string to UTF-8.
782
+ const utf8 = textEncoder.encode(sql);
783
+
784
+ // Copy encoded string to WebAssembly memory. The SQLite docs say
785
+ // zero-termination is a minor optimization so add room for that.
786
+ // Also add space for the statement handle and SQL tail pointer.
787
+ const allocSize = utf8.byteLength - (utf8.byteLength % 4) + 12;
788
+ const pzHead = Module._sqlite3_malloc(allocSize);
789
+ const pzEnd = pzHead + utf8.byteLength + 1;
790
+ onFinally.push(() => Module._sqlite3_free(pzHead));
791
+ Module.HEAPU8.set(utf8, pzHead);
792
+ Module.HEAPU8[pzEnd - 1] = 0;
793
+
794
+ // Use extra space for the statement handle and SQL tail pointer.
795
+ const pStmt = pzHead + allocSize - 8;
796
+ const pzTail = pzHead + allocSize - 4;
797
+
798
+ // Ensure that statement handles are not leaked.
799
+ let stmt;
800
+ function maybeFinalize() {
801
+ if (stmt && !options.unscoped) {
802
+ sqlite3.finalize(stmt);
803
+ }
804
+ stmt = 0;
805
+ }
806
+ onFinally.push(maybeFinalize);
807
+
808
+ // Loop over statements.
809
+ Module.setValue(pzTail, pzHead, '*');
810
+ do {
811
+ // Reclaim resources for the previous iteration.
812
+ maybeFinalize();
813
+
814
+ // Call sqlite3_prepare_v3() for the next statement.
815
+ // Allow retry operations.
816
+ const zTail = Module.getValue(pzTail, '*');
817
+ const rc = prepare(
818
+ db,
819
+ zTail,
820
+ pzEnd - pzTail,
821
+ options.flags || 0,
822
+ pStmt,
823
+ pzTail);
824
+
825
+ if (rc !== SQLite.SQLITE_OK) {
826
+ check('sqlite3_prepare_v3', rc, db);
827
+ }
828
+
829
+ stmt = Module.getValue(pStmt, '*');
830
+ if (stmt) {
831
+ mapStmtToDB.set(stmt, db);
832
+ // yield stmt;
833
+ stmts.push(stmt);
834
+ }
835
+ } while (stmt);
836
+ // } finally {
837
+ // while (onFinally.length) {
838
+ // onFinally.pop()();
839
+ // }
840
+ // }
841
+
842
+ return stmts;
843
+ };
844
+
845
+ sqlite3.step = (function() {
846
+ const fname = 'sqlite3_step';
847
+ const f = Module.cwrap(fname, ...decl('n:n'), { async });
848
+ // return async function(stmt) {
849
+ return function(stmt) {
850
+ verifyStatement(stmt);
851
+
852
+ // Allow retry operations.
853
+ // const rc = await retry(() => f(stmt));
854
+ const rc = f(stmt);
855
+
856
+ return check(fname, rc, mapStmtToDB.get(stmt), [SQLite.SQLITE_ROW, SQLite.SQLITE_DONE]);
857
+ };
858
+ })();
859
+
860
+ sqlite3.commit_hook = function(db, xCommitHook) {
861
+ verifyDatabase(db);
862
+ Module.commit_hook(db, xCommitHook);
863
+ };
864
+
865
+ sqlite3.update_hook = function(db, xUpdateHook) {
866
+ verifyDatabase(db);
867
+
868
+ // Convert SQLite callback arguments to JavaScript-friendly arguments.
869
+ function cvtArgs(iUpdateType, dbName, tblName, lo32, hi32) {
870
+ return [
871
+ iUpdateType,
872
+ Module.UTF8ToString(dbName),
873
+ Module.UTF8ToString(tblName),
874
+ cvt32x2ToBigInt(lo32, hi32)
875
+ ];
876
+ };
877
+ function adapt(f) {
878
+ // return f instanceof AsyncFunction ?
879
+ // (async (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32))) :
880
+ // ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
881
+ return ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
882
+ }
883
+
884
+ Module.update_hook(db, adapt(xUpdateHook));
885
+ };;
886
+
887
+ // Session extension bindings
888
+ sqlite3.session_create = (function() {
889
+ const fname = 'sqlite3session_create';
890
+ const f = Module.cwrap(fname, ...decl('nsn:n'));
891
+ return function(db, zDb) {
892
+ verifyDatabase(db);
893
+ const ppSession = Module._malloc(4);
894
+ const result = f(db, zDb, ppSession);
895
+
896
+ if (result !== SQLite.SQLITE_OK) {
897
+ check(fname, result, db);
898
+ }
899
+
900
+ const pSession = Module.getValue(ppSession, 'i32');
901
+ return pSession;
902
+ };
903
+ })();
904
+
905
+ sqlite3.session_attach = (function() {
906
+ const fname = 'sqlite3session_attach';
907
+ const f = Module.cwrap(fname, ...decl('ns:n'));
908
+ return function(pSession, zTab) {
909
+ if (typeof pSession !== 'number') {
910
+ throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
911
+ }
912
+ const result = f(pSession, zTab);
913
+ return check(fname, result);
914
+ };
915
+ })();
916
+
917
+ sqlite3.session_enable = (function() {
918
+ const fname = 'sqlite3session_enable';
919
+ const f = Module.cwrap(fname, ...decl('nn:n'));
920
+ return function(pSession, enableBool) {
921
+ const enable = enableBool ? 1 : 0;
922
+ if (typeof pSession !== 'number') {
923
+ throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
924
+ }
925
+ const result = f(pSession, enable);
926
+ if (result !== enable) {
927
+ throw new SQLiteError('Failed to enable session', SQLite.SQLITE_MISUSE);
928
+ }
929
+ };
930
+ })();
931
+
932
+ sqlite3.session_changeset = (function() {
933
+ const fname = 'sqlite3session_changeset';
934
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
935
+ return function(pSession) {
936
+ if (typeof pSession !== 'number') {
937
+ throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
938
+ }
939
+
940
+ // Allocate memory for the size (int) and the changeset pointer (void*)
941
+ const sizePtr = Module._malloc(4);
942
+ const changesetPtrPtr = Module._malloc(4);
943
+
944
+ try {
945
+ const result = f(pSession, sizePtr, changesetPtrPtr);
946
+ if (result === SQLite.SQLITE_OK) {
947
+ // Get the size of the changeset
948
+ const size = Module.getValue(sizePtr, 'i32');
949
+ // Get the pointer to the changeset
950
+ const changesetPtr = Module.getValue(changesetPtrPtr, 'i32');
951
+
952
+ // Ensure the pointer is valid before accessing memory
953
+ if (changesetPtr === 0) {
954
+ return {
955
+ result: result,
956
+ size: 0,
957
+ changeset: null
958
+ }
959
+ }
960
+
961
+ // Copy the changeset data
962
+ const changeset = new Uint8Array(Module.HEAPU8.subarray(changesetPtr, changesetPtr + size));
963
+
964
+ // Free the allocated changeset memory
965
+ Module._sqlite3_free(changesetPtr);
966
+
967
+ // Return a copy of the changeset
968
+ return {
969
+ result: result,
970
+ size: size,
971
+ changeset: changeset
972
+ };
973
+ }
974
+ return check(fname, result);
975
+ } finally {
976
+ // Free the allocated memory
977
+ Module._free(sizePtr);
978
+ Module._free(changesetPtrPtr);
979
+ }
980
+ };
981
+ })();
982
+
983
+ sqlite3.session_delete = (function() {
984
+ const fname = 'sqlite3session_delete';
985
+ const f = Module.cwrap(fname, ...decl('n:v'));
986
+ return function(pSession) {
987
+ if (typeof pSession !== 'number') {
988
+ throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
989
+ }
990
+ const result = f(pSession);
991
+ return result;
992
+ };
993
+ })();
994
+
995
+ sqlite3.changeset_start = (function() {
996
+ const fname = 'sqlite3changeset_start';
997
+ const f = Module.cwrap(fname, ...decl('nnn:n'));
998
+ return function(changesetData) {
999
+ // Allocate memory for the input changeset data
1000
+ const inPtr = Module._sqlite3_malloc(changesetData.length);
1001
+ Module.HEAPU8.subarray(inPtr).set(changesetData);
1002
+
1003
+ // Allocate memory for the changeset iterator pointer
1004
+ const ppIter = Module._malloc(4);
1005
+
1006
+ try {
1007
+ // Call the wrapped C function
1008
+ const result = f(ppIter, changesetData.length, inPtr);
1009
+
1010
+ if (result !== SQLite.SQLITE_OK) {
1011
+ check(fname, result); // Handle errors appropriately
1012
+ }
1013
+
1014
+ // Retrieve the changeset iterator handle
1015
+ const pIter = Module.getValue(ppIter, 'i32');
1016
+
1017
+ return pIter;
1018
+ } finally {
1019
+ // Free allocated memory
1020
+ Module._sqlite3_free(inPtr);
1021
+ Module._free(ppIter);
1022
+ }
1023
+ };
1024
+ })();
1025
+
1026
+ sqlite3.changeset_finalize = (function() {
1027
+ const fname = 'sqlite3changeset_finalize';
1028
+ const f = Module.cwrap(fname, ...decl('n:n'));
1029
+ return function(pIter) {
1030
+ const result = f(pIter);
1031
+ return result;
1032
+ };
1033
+ })();
1034
+
1035
+ sqlite3.changeset_invert = (function() {
1036
+ const fname = 'sqlite3changeset_invert';
1037
+ const f = Module.cwrap(fname, ...decl('nn:nn'));
1038
+ return function(changesetData) {
1039
+ // Allocate memory for the input changeset data
1040
+ const inPtr = Module._sqlite3_malloc(changesetData.length);
1041
+ Module.HEAPU8.subarray(inPtr).set(changesetData);
1042
+
1043
+ // Allocate memory for the output changeset length and pointer
1044
+ const outLengthPtr = Module._malloc(4);
1045
+ const outPtrPtr = Module._malloc(4);
1046
+
1047
+ // Call the wrapped C function
1048
+ const result = f(changesetData.length, inPtr, outLengthPtr, outPtrPtr);
1049
+
1050
+ if (result !== SQLite.SQLITE_OK) {
1051
+ check(fname, result); // Handle errors appropriately
1052
+ }
1053
+
1054
+ // Retrieve the size and pointer of the inverted changeset
1055
+ const outLength = Module.getValue(outLengthPtr, 'i32');
1056
+ const changesetOutPtr = Module.getValue(outPtrPtr, 'i32');
1057
+
1058
+ // Copy the inverted changeset data
1059
+ const changesetOut = new Uint8Array(Module.HEAPU8.buffer, changesetOutPtr, outLength).slice();
1060
+
1061
+ // Free allocated memory
1062
+ Module._sqlite3_free(inPtr);
1063
+
1064
+ // TODO investigate why freeing these pointers causes a crash
1065
+ // RuntimeError: Out of bounds memory access (evaluating 'Module._sqlite3_free(outLengthPtr)')
1066
+ // Repro: https://gist.github.com/schickling/08b10b6fda8583601e586cb0bea333ce
1067
+
1068
+ // Module._sqlite3_free(outLengthPtr);
1069
+ // Module._sqlite3_free(outPtrPtr);
1070
+
1071
+ Module._sqlite3_free(changesetOutPtr);
1072
+
1073
+ return changesetOut;
1074
+ };
1075
+ })();
1076
+
1077
+ /**
1078
+ * Convenience function to get an inverted changeset from a session
1079
+ * without having to call sqlite3session_changeset() and then sqlite3changeset_invert().
1080
+ * It's more efficient as it's reusing the same memory allocation for the changeset.
1081
+ */
1082
+ sqlite3.session_changeset_inverted = (function() {
1083
+ const fnameChangeset = 'sqlite3session_changeset';
1084
+ const fChangeset = Module.cwrap(fnameChangeset, ...decl('nnn:n'));
1085
+ const fnameInvert = 'sqlite3changeset_invert';
1086
+ const fInvert = Module.cwrap(fnameInvert, ...decl('nn:nn'));
1087
+ return function(pSession) {
1088
+ if (typeof pSession !== 'number') {
1089
+ throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
1090
+ }
1091
+
1092
+ // Allocate memory for the size (int) and the changeset pointer (void*)
1093
+ const sizePtr = Module._malloc(4);
1094
+ const changesetPtrPtr = Module._malloc(4);
1095
+
1096
+ // Allocate memory for the size (int) and the inverted changeset pointer (void*)
1097
+ const sizePtrInvert = Module._malloc(4);
1098
+ const changesetPtrPtrInvert = Module._malloc(4);
1099
+
1100
+ try {
1101
+ const changesetResult = fChangeset(pSession, sizePtr, changesetPtrPtr);
1102
+ if (changesetResult !== SQLite.SQLITE_OK) {
1103
+ return check(fnameChangeset, changesetResult);
1104
+ }
1105
+
1106
+ // Get the size of the changeset
1107
+ const size = Module.getValue(sizePtr, 'i32');
1108
+ // Get the pointer to the changeset
1109
+ const changesetPtr = Module.getValue(changesetPtrPtr, 'i32');
1110
+
1111
+
1112
+ const invertedResult = fInvert(size, changesetPtr, sizePtrInvert, changesetPtrPtrInvert);
1113
+
1114
+ if (invertedResult !== SQLite.SQLITE_OK) {
1115
+ return check(fnameInvert, invertedResult);
1116
+ }
1117
+
1118
+ // Get the size of the changeset
1119
+ const sizeInvert = Module.getValue(sizePtrInvert, 'i32');
1120
+ // Get the pointer to the changeset
1121
+ const changesetPtrInvert = Module.getValue(changesetPtrPtrInvert, 'i32');
1122
+
1123
+ // Copy the changeset data
1124
+ const changesetInvert = new Uint8Array(Module.HEAPU8.buffer, changesetPtrInvert, sizeInvert);
1125
+
1126
+ Module._sqlite3_free(changesetPtr);
1127
+ Module._sqlite3_free(changesetPtrInvert)
1128
+
1129
+ // Return a copy of the changeset
1130
+ return {
1131
+ result: changesetResult,
1132
+ size: size,
1133
+ changeset: new Uint8Array(changesetInvert)
1134
+ };
1135
+ } finally {
1136
+ // Free the allocated memory
1137
+ Module._free(sizePtr);
1138
+ Module._free(changesetPtrPtr);
1139
+ Module._free(sizePtrInvert);
1140
+ Module._free(changesetPtrPtrInvert);
1141
+ }
1142
+
1143
+ };
1144
+ })();
1145
+
1146
+ sqlite3.changeset_apply = (function() {
1147
+ const fname = 'sqlite3changeset_apply';
1148
+ const f = Module.cwrap(fname, ...decl('nnnnnn:n'));
1149
+ return function(db, changesetData, options) {
1150
+ /*
1151
+ int sqlite3changeset_apply(
1152
+ sqlite3 *db, Apply change to "main" db of this handle
1153
+ int nChangeset, Size of changeset in bytes
1154
+ void *pChangeset, Changeset blob
1155
+ int(*xFilter)(
1156
+ void *pCtx, Copy of sixth arg to _apply()
1157
+ const char *zTab Table name
1158
+ ),
1159
+ int(*xConflict)(
1160
+ void *pCtx, Copy of sixth arg to _apply()
1161
+ int eConflict, DATA, MISSING, CONFLICT, CONSTRAINT
1162
+ sqlite3_changeset_iter *p Handle describing change and conflict
1163
+ ),
1164
+ void *pCtx First argument passed to xConflict
1165
+ );
1166
+ */
1167
+ const inPtr = Module._sqlite3_malloc(changesetData.length);
1168
+ Module.HEAPU8.subarray(inPtr).set(changesetData);
1169
+
1170
+ // https://sqlite.org/session/c_changeset_abort.html
1171
+ const SQLITE_CHANGESET_REPLACE = 1
1172
+ const onConflict = () => {
1173
+ return SQLITE_CHANGESET_REPLACE;
1174
+ }
1175
+
1176
+ const result = f(db, changesetData.length, inPtr, null, onConflict, null);
1177
+
1178
+ Module._sqlite3_free(inPtr);
1179
+
1180
+ if (result !== SQLite.SQLITE_OK) {
1181
+ check(fname, result);
1182
+ }
1183
+
1184
+ return result;
1185
+ }
1186
+ })();
1187
+
1188
+ // Session extension bindings end
1189
+
1190
+ sqlite3.value = function(pValue) {
1191
+ const type = sqlite3.value_type(pValue);
1192
+ switch (type) {
1193
+ case SQLite.SQLITE_BLOB:
1194
+ return sqlite3.value_blob(pValue);
1195
+ case SQLite.SQLITE_FLOAT:
1196
+ return sqlite3.value_double(pValue);
1197
+ case SQLite.SQLITE_INTEGER:
1198
+ const lo32 = sqlite3.value_int(pValue);
1199
+ const hi32 = Module.getTempRet0();
1200
+ return cvt32x2AsSafe(lo32, hi32);
1201
+ case SQLite.SQLITE_NULL:
1202
+ return null;
1203
+ case SQLite.SQLITE_TEXT:
1204
+ return sqlite3.value_text(pValue);
1205
+ default:
1206
+ throw new SQLiteError('unknown type', type);
1207
+ }
1208
+ };
1209
+
1210
+ sqlite3.value_blob = (function() {
1211
+ const fname = 'sqlite3_value_blob';
1212
+ const f = Module.cwrap(fname, ...decl('n:n'));
1213
+ return function(pValue) {
1214
+ const nBytes = sqlite3.value_bytes(pValue);
1215
+ const address = f(pValue);
1216
+ const result = Module.HEAPU8.subarray(address, address + nBytes);
1217
+ return result;
1218
+ };
1219
+ })();
1220
+
1221
+ sqlite3.value_bytes = (function() {
1222
+ const fname = 'sqlite3_value_bytes';
1223
+ const f = Module.cwrap(fname, ...decl('n:n'));
1224
+ return function(pValue) {
1225
+ const result = f(pValue);
1226
+ return result;
1227
+ };
1228
+ })();
1229
+
1230
+ sqlite3.value_double = (function() {
1231
+ const fname = 'sqlite3_value_double';
1232
+ const f = Module.cwrap(fname, ...decl('n:n'));
1233
+ return function(pValue) {
1234
+ const result = f(pValue);
1235
+ return result;
1236
+ };
1237
+ })();
1238
+
1239
+ sqlite3.value_int = (function() {
1240
+ const fname = 'sqlite3_value_int64';
1241
+ const f = Module.cwrap(fname, ...decl('n:n'));
1242
+ return function(pValue) {
1243
+ const result = f(pValue);
1244
+ return result;
1245
+ };
1246
+ })();
1247
+
1248
+ sqlite3.value_int64 = (function() {
1249
+ const fname = 'sqlite3_value_int64';
1250
+ const f = Module.cwrap(fname, ...decl('n:n'));
1251
+ return function(pValue) {
1252
+ const lo32 = f(pValue);
1253
+ const hi32 = Module.getTempRet0();
1254
+ const result = cvt32x2ToBigInt(lo32, hi32);
1255
+ return result;
1256
+ };
1257
+ })();
1258
+
1259
+ sqlite3.value_text = (function() {
1260
+ const fname = 'sqlite3_value_text';
1261
+ const f = Module.cwrap(fname, ...decl('n:s'));
1262
+ return function(pValue) {
1263
+ const result = f(pValue);
1264
+ return result;
1265
+ };
1266
+ })();
1267
+
1268
+ sqlite3.value_type = (function() {
1269
+ const fname = 'sqlite3_value_type';
1270
+ const f = Module.cwrap(fname, ...decl('n:n'));
1271
+ return function(pValue) {
1272
+ const result = f(pValue);
1273
+ return result;
1274
+ };
1275
+ })();
1276
+
1277
+ const registeredVfs = new Set();
1278
+
1279
+ sqlite3.vfs_register = function(vfs, makeDefault) {
1280
+ if (registeredVfs.has(vfs.name)) return
1281
+ const result = Module.vfs_register(vfs, makeDefault);
1282
+ const res = check('sqlite3_vfs_register', result);
1283
+ registeredVfs.add(vfs.name);
1284
+ return res
1285
+ };
1286
+
1287
+ sqlite3.vfs_registered = registeredVfs;
1288
+
1289
+ function check(fname, result, db = null, allowed = [SQLite.SQLITE_OK]) {
1290
+ if (allowed.includes(result)) return result;
1291
+ const message = db ?
1292
+ Module.ccall('sqlite3_errmsg', 'string', ['number'], [db]) :
1293
+ fname;
1294
+ throw new SQLiteError(message, result);
1295
+ }
1296
+
1297
+ // This function is used to automatically retry failed calls that
1298
+ // have pending retry operations that should allow the retry to
1299
+ // succeed.
1300
+ async function retry(f) {
1301
+ let rc;
1302
+ do {
1303
+ // Wait for all pending retry operations to complete. This is
1304
+ // normally empty on the first loop iteration.
1305
+ if (Module.retryOps.length) {
1306
+ await Promise.all(Module.retryOps);
1307
+ Module.retryOps = [];
1308
+ }
1309
+
1310
+ rc = await f();
1311
+
1312
+ // Retry on failure with new pending retry operations.
1313
+ } while (rc && Module.retryOps.length);
1314
+ return rc;
1315
+ }
1316
+
1317
+ return sqlite3;
1318
+ }
1319
+
1320
+ // Helper function to use a more compact signature specification.
1321
+ function decl(s) {
1322
+ const result = [];
1323
+ const m = s.match(/([ns@]*):([nsv@])/);
1324
+ switch (m[2]) {
1325
+ case 'n': result.push('number'); break;
1326
+ case 's': result.push('string'); break;
1327
+ case 'v': result.push(null); break;
1328
+ }
1329
+
1330
+ const args = [];
1331
+ for (let c of m[1]) {
1332
+ switch (c) {
1333
+ case 'n': args.push('number'); break;
1334
+ case 's': args.push('string'); break;
1335
+ }
1336
+ }
1337
+ result.push(args);
1338
+ return result;
1339
+ }