@livestore/wa-sqlite 1.0.1-dev.9 → 1.0.3-dev.3
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 +18 -1
- package/dist/fts5/wa-sqlite.mjs +16 -0
- package/dist/fts5/wa-sqlite.node.mjs +6314 -0
- package/dist/fts5/wa-sqlite.node.wasm +0 -0
- package/dist/fts5/wa-sqlite.wasm +0 -0
- package/dist/wa-sqlite.mjs +1 -1
- package/dist/wa-sqlite.node.mjs +6312 -0
- package/dist/wa-sqlite.node.wasm +0 -0
- package/dist/wa-sqlite.wasm +0 -0
- package/package.json +3 -4
- package/src/sqlite-api.js +410 -34
- package/src/types/globals.d.ts +3 -3
- package/src/types/index.d.ts +175 -6
- package/test/callbacks.test.js +54 -2
- package/test/data/idbv5.json +1 -0
- package/dist/wa-sqlite-async.mjs +0 -16
- package/dist/wa-sqlite-async.wasm +0 -0
- package/dist/wa-sqlite-jspi.mjs +0 -16
- package/dist/wa-sqlite-jspi.wasm +0 -0
|
Binary file
|
package/dist/wa-sqlite.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/wa-sqlite",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3-dev.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/sqlite-api.js",
|
|
6
6
|
"types": "src/types/index.d.ts",
|
|
@@ -40,6 +40,5 @@
|
|
|
40
40
|
"web-test-runner-jasmine@0.0.6": {
|
|
41
41
|
"unplugged": true
|
|
42
42
|
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/sqlite-api.js
CHANGED
|
@@ -249,16 +249,46 @@ export function Factory(Module) {
|
|
|
249
249
|
};
|
|
250
250
|
})();
|
|
251
251
|
|
|
252
|
+
const SQLITE_SERIALIZE_NOCOPY = 0x0_01
|
|
253
|
+
|
|
252
254
|
sqlite3.serialize = (function() {
|
|
253
255
|
const fname = 'sqlite3_serialize';
|
|
254
256
|
const f = Module.cwrap(fname, ...decl('nsnn:n'));
|
|
255
|
-
return function(db, schema
|
|
257
|
+
return function(db, schema) {
|
|
256
258
|
verifyDatabase(db);
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
const piSize = tmpPtr[0];
|
|
260
|
+
let address = f(db, schema, piSize, 0);
|
|
261
|
+
if (address === 0) {
|
|
262
|
+
address = f(db, schema, piSize, SQLITE_SERIALIZE_NOCOPY);
|
|
263
|
+
const size = Module.getValue(piSize, '*');
|
|
264
|
+
const result = Module.HEAPU8.subarray(address, address + size);
|
|
265
|
+
// NOTE Given that the memory is owned by SQLite, we must copy it.
|
|
266
|
+
return new Uint8Array(result.slice());
|
|
267
|
+
} else {
|
|
268
|
+
const size = Module.getValue(piSize, '*');
|
|
269
|
+
const result = Module.HEAPU8.subarray(address, address + size);
|
|
270
|
+
// Here we're getting a copy of the memory, so we can return it directly.
|
|
271
|
+
return new Uint8Array(result);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
})();
|
|
260
275
|
|
|
261
|
-
|
|
276
|
+
// https://www.sqlite.org/c3ref/backup_finish.html
|
|
277
|
+
// https://www.sqlite.org/backup.html
|
|
278
|
+
sqlite3.backup = (function() {
|
|
279
|
+
const fInit = Module.cwrap('sqlite3_backup_init', ...decl('nsns:n'));
|
|
280
|
+
const fStep = Module.cwrap('sqlite3_backup_step', ...decl('nn:n'));
|
|
281
|
+
const fFinish = Module.cwrap('sqlite3_backup_finish', ...decl('n:n'));
|
|
282
|
+
return function(dest, destName, source, sourceName) {
|
|
283
|
+
verifyDatabase(dest);
|
|
284
|
+
verifyDatabase(source);
|
|
285
|
+
const backup = fInit(dest, destName, source, sourceName);
|
|
286
|
+
if (backup === 0) {
|
|
287
|
+
const errMsg = Module.ccall('sqlite3_errmsg', 'string', ['number'], [dest]);
|
|
288
|
+
throw new SQLiteError(`backup failed: ${errMsg}`, SQLite.SQLITE_ERROR);
|
|
289
|
+
}
|
|
290
|
+
fStep(backup, -1);
|
|
291
|
+
return fFinish(backup);
|
|
262
292
|
};
|
|
263
293
|
})();
|
|
264
294
|
|
|
@@ -458,7 +488,8 @@ export function Factory(Module) {
|
|
|
458
488
|
// return SQLite.SQLITE_OK;
|
|
459
489
|
// };
|
|
460
490
|
sqlite3.exec = function(db, sql, callback) {
|
|
461
|
-
|
|
491
|
+
const stmts = sqlite3.statements(db, sql, { unscoped: true });
|
|
492
|
+
for (const stmt of stmts) {
|
|
462
493
|
let columns;
|
|
463
494
|
while (sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
|
|
464
495
|
if (callback) {
|
|
@@ -468,6 +499,9 @@ export function Factory(Module) {
|
|
|
468
499
|
}
|
|
469
500
|
}
|
|
470
501
|
}
|
|
502
|
+
for (const stmt of stmts) {
|
|
503
|
+
sqlite3.finalize(stmt);
|
|
504
|
+
}
|
|
471
505
|
return SQLite.SQLITE_OK;
|
|
472
506
|
};
|
|
473
507
|
|
|
@@ -523,6 +557,28 @@ export function Factory(Module) {
|
|
|
523
557
|
})();
|
|
524
558
|
|
|
525
559
|
sqlite3.open_v2 = (function() {
|
|
560
|
+
const fname = 'sqlite3_open_v2';
|
|
561
|
+
const f = Module.cwrap(fname, ...decl('snnn:n'), { async });
|
|
562
|
+
return async function(zFilename, flags, zVfs) {
|
|
563
|
+
flags = flags || SQLite.SQLITE_OPEN_CREATE | SQLite.SQLITE_OPEN_READWRITE;
|
|
564
|
+
zVfs = createUTF8(zVfs);
|
|
565
|
+
try {
|
|
566
|
+
// Allow retry operations.
|
|
567
|
+
const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs));
|
|
568
|
+
|
|
569
|
+
const db = Module.getValue(tmpPtr[0], '*');
|
|
570
|
+
databases.add(db);
|
|
571
|
+
|
|
572
|
+
Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
|
|
573
|
+
check(fname, rc, db);
|
|
574
|
+
return db;
|
|
575
|
+
} finally {
|
|
576
|
+
Module._sqlite3_free(zVfs);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
})();
|
|
580
|
+
|
|
581
|
+
sqlite3.open_v2Sync = (function() {
|
|
526
582
|
const fname = 'sqlite3_open_v2';
|
|
527
583
|
const f = Module.cwrap(fname, ...decl('snnn:n'), { async });
|
|
528
584
|
return function(zFilename, flags, zVfs) {
|
|
@@ -537,7 +593,7 @@ export function Factory(Module) {
|
|
|
537
593
|
databases.add(db);
|
|
538
594
|
|
|
539
595
|
Module.ccall('RegisterExtensionFunctions', 'void', ['number'], [db]);
|
|
540
|
-
check(fname, rc);
|
|
596
|
+
check(fname, rc, db);
|
|
541
597
|
return db;
|
|
542
598
|
} finally {
|
|
543
599
|
Module._sqlite3_free(zVfs);
|
|
@@ -545,6 +601,7 @@ export function Factory(Module) {
|
|
|
545
601
|
};
|
|
546
602
|
})();
|
|
547
603
|
|
|
604
|
+
|
|
548
605
|
sqlite3.progress_handler = function(db, nProgressOps, handler, userData) {
|
|
549
606
|
verifyDatabase(db);
|
|
550
607
|
Module.progress_handler(db, nProgressOps, handler, userData);
|
|
@@ -675,9 +732,9 @@ export function Factory(Module) {
|
|
|
675
732
|
};
|
|
676
733
|
function adapt(f) {
|
|
677
734
|
// return f instanceof AsyncFunction ?
|
|
678
|
-
// (async (_, iAction, p3, p4, p5, p6) => f(cvtArgs(_, iAction, p3, p4, p5, p6))) :
|
|
679
|
-
// ((_, iAction, p3, p4, p5, p6) => f(cvtArgs(_, iAction, p3, p4, p5, p6)));
|
|
680
|
-
return ((_, iAction, p3, p4, p5, p6) => f(cvtArgs(_, iAction, p3, p4, p5, p6)));
|
|
735
|
+
// (async (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6))) :
|
|
736
|
+
// ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
|
|
737
|
+
return ((_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)));
|
|
681
738
|
}
|
|
682
739
|
|
|
683
740
|
const result = Module.set_authorizer(db, adapt(xAuth), pApp);
|
|
@@ -702,10 +759,10 @@ export function Factory(Module) {
|
|
|
702
759
|
// { async: true });
|
|
703
760
|
{ async: false });
|
|
704
761
|
|
|
705
|
-
const
|
|
762
|
+
const stmts = [];
|
|
706
763
|
|
|
707
764
|
const onFinally = [];
|
|
708
|
-
try {
|
|
765
|
+
// try {
|
|
709
766
|
// Encode SQL string to UTF-8.
|
|
710
767
|
const utf8 = new TextEncoder().encode(sql);
|
|
711
768
|
|
|
@@ -767,16 +824,16 @@ export function Factory(Module) {
|
|
|
767
824
|
if (stmt) {
|
|
768
825
|
mapStmtToDB.set(stmt, db);
|
|
769
826
|
// yield stmt;
|
|
770
|
-
|
|
827
|
+
stmts.push(stmt);
|
|
771
828
|
}
|
|
772
829
|
} while (stmt);
|
|
773
|
-
} finally {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
830
|
+
// } finally {
|
|
831
|
+
// while (onFinally.length) {
|
|
832
|
+
// onFinally.pop()();
|
|
833
|
+
// }
|
|
834
|
+
// }
|
|
778
835
|
|
|
779
|
-
return
|
|
836
|
+
return stmts;
|
|
780
837
|
};
|
|
781
838
|
|
|
782
839
|
sqlite3.step = (function() {
|
|
@@ -794,6 +851,318 @@ export function Factory(Module) {
|
|
|
794
851
|
};
|
|
795
852
|
})();
|
|
796
853
|
|
|
854
|
+
sqlite3.update_hook = function(db, xUpdateHook) {
|
|
855
|
+
verifyDatabase(db);
|
|
856
|
+
|
|
857
|
+
// Convert SQLite callback arguments to JavaScript-friendly arguments.
|
|
858
|
+
function cvtArgs(iUpdateType, dbName, tblName, lo32, hi32) {
|
|
859
|
+
return [
|
|
860
|
+
iUpdateType,
|
|
861
|
+
Module.UTF8ToString(dbName),
|
|
862
|
+
Module.UTF8ToString(tblName),
|
|
863
|
+
cvt32x2ToBigInt(lo32, hi32)
|
|
864
|
+
];
|
|
865
|
+
};
|
|
866
|
+
function adapt(f) {
|
|
867
|
+
// return f instanceof AsyncFunction ?
|
|
868
|
+
// (async (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32))) :
|
|
869
|
+
// ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
|
|
870
|
+
return ((iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)));
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
Module.update_hook(db, adapt(xUpdateHook));
|
|
874
|
+
};;
|
|
875
|
+
|
|
876
|
+
// Session extension bindings
|
|
877
|
+
sqlite3.session_create = (function() {
|
|
878
|
+
const fname = 'sqlite3session_create';
|
|
879
|
+
const f = Module.cwrap(fname, ...decl('nsn:n'));
|
|
880
|
+
return function(db, zDb) {
|
|
881
|
+
verifyDatabase(db);
|
|
882
|
+
const ppSession = Module._malloc(4);
|
|
883
|
+
const result = f(db, zDb, ppSession);
|
|
884
|
+
|
|
885
|
+
if (result !== SQLite.SQLITE_OK) {
|
|
886
|
+
check(fname, result, db);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const pSession = Module.getValue(ppSession, 'i32');
|
|
890
|
+
return pSession;
|
|
891
|
+
};
|
|
892
|
+
})();
|
|
893
|
+
|
|
894
|
+
sqlite3.session_attach = (function() {
|
|
895
|
+
const fname = 'sqlite3session_attach';
|
|
896
|
+
const f = Module.cwrap(fname, ...decl('ns:n'));
|
|
897
|
+
return function(pSession, zTab) {
|
|
898
|
+
if (typeof pSession !== 'number') {
|
|
899
|
+
throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
|
|
900
|
+
}
|
|
901
|
+
const result = f(pSession, zTab);
|
|
902
|
+
return check(fname, result);
|
|
903
|
+
};
|
|
904
|
+
})();
|
|
905
|
+
|
|
906
|
+
sqlite3.session_enable = (function() {
|
|
907
|
+
const fname = 'sqlite3session_enable';
|
|
908
|
+
const f = Module.cwrap(fname, ...decl('nn:n'));
|
|
909
|
+
return function(pSession, enableBool) {
|
|
910
|
+
const enable = enableBool ? 1 : 0;
|
|
911
|
+
if (typeof pSession !== 'number') {
|
|
912
|
+
throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
|
|
913
|
+
}
|
|
914
|
+
const result = f(pSession, enable);
|
|
915
|
+
if (result !== enable) {
|
|
916
|
+
throw new SQLiteError('Failed to enable session', SQLite.SQLITE_MISUSE);
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
})();
|
|
920
|
+
|
|
921
|
+
sqlite3.session_changeset = (function() {
|
|
922
|
+
const fname = 'sqlite3session_changeset';
|
|
923
|
+
const f = Module.cwrap(fname, ...decl('nnn:n'));
|
|
924
|
+
return function(pSession) {
|
|
925
|
+
if (typeof pSession !== 'number') {
|
|
926
|
+
throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Allocate memory for the size (int) and the changeset pointer (void*)
|
|
930
|
+
const sizePtr = Module._malloc(4);
|
|
931
|
+
const changesetPtrPtr = Module._malloc(4);
|
|
932
|
+
|
|
933
|
+
try {
|
|
934
|
+
const result = f(pSession, sizePtr, changesetPtrPtr);
|
|
935
|
+
if (result === SQLite.SQLITE_OK) {
|
|
936
|
+
// Get the size of the changeset
|
|
937
|
+
const size = Module.getValue(sizePtr, 'i32');
|
|
938
|
+
// Get the pointer to the changeset
|
|
939
|
+
const changesetPtr = Module.getValue(changesetPtrPtr, 'i32');
|
|
940
|
+
|
|
941
|
+
// Ensure the pointer is valid before accessing memory
|
|
942
|
+
if (changesetPtr === 0) {
|
|
943
|
+
throw new SQLiteError('Failed to retrieve changeset pointer', SQLite.SQLITE_ERROR);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Copy the changeset data
|
|
947
|
+
const changeset = new Uint8Array(Module.HEAPU8.subarray(changesetPtr, changesetPtr + size));
|
|
948
|
+
|
|
949
|
+
// Free the allocated changeset memory
|
|
950
|
+
Module._sqlite3_free(changesetPtr);
|
|
951
|
+
|
|
952
|
+
// Return a copy of the changeset
|
|
953
|
+
return {
|
|
954
|
+
result: result,
|
|
955
|
+
size: size,
|
|
956
|
+
changeset: changeset
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
return check(fname, result);
|
|
960
|
+
} finally {
|
|
961
|
+
// Free the allocated memory
|
|
962
|
+
Module._free(sizePtr);
|
|
963
|
+
Module._free(changesetPtrPtr);
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
})();
|
|
967
|
+
|
|
968
|
+
sqlite3.session_delete = (function() {
|
|
969
|
+
const fname = 'sqlite3session_delete';
|
|
970
|
+
const f = Module.cwrap(fname, ...decl('n:v'));
|
|
971
|
+
return function(pSession) {
|
|
972
|
+
if (typeof pSession !== 'number') {
|
|
973
|
+
throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
|
|
974
|
+
}
|
|
975
|
+
const result = f(pSession);
|
|
976
|
+
return result;
|
|
977
|
+
};
|
|
978
|
+
})();
|
|
979
|
+
|
|
980
|
+
sqlite3.changeset_start = (function() {
|
|
981
|
+
const fname = 'sqlite3changeset_start';
|
|
982
|
+
const f = Module.cwrap(fname, ...decl('nnn:n'));
|
|
983
|
+
return function(changesetData) {
|
|
984
|
+
// Allocate memory for the input changeset data
|
|
985
|
+
const inPtr = Module._sqlite3_malloc(changesetData.length);
|
|
986
|
+
Module.HEAPU8.subarray(inPtr).set(changesetData);
|
|
987
|
+
|
|
988
|
+
// Allocate memory for the changeset iterator pointer
|
|
989
|
+
const ppIter = Module._malloc(4);
|
|
990
|
+
|
|
991
|
+
try {
|
|
992
|
+
// Call the wrapped C function
|
|
993
|
+
const result = f(ppIter, changesetData.length, inPtr);
|
|
994
|
+
|
|
995
|
+
if (result !== SQLite.SQLITE_OK) {
|
|
996
|
+
check(fname, result); // Handle errors appropriately
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Retrieve the changeset iterator handle
|
|
1000
|
+
const pIter = Module.getValue(ppIter, 'i32');
|
|
1001
|
+
|
|
1002
|
+
return pIter;
|
|
1003
|
+
} finally {
|
|
1004
|
+
// Free allocated memory
|
|
1005
|
+
Module._sqlite3_free(inPtr);
|
|
1006
|
+
Module._free(ppIter);
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
})();
|
|
1010
|
+
|
|
1011
|
+
sqlite3.changeset_finalize = (function() {
|
|
1012
|
+
const fname = 'sqlite3changeset_finalize';
|
|
1013
|
+
const f = Module.cwrap(fname, ...decl('n:n'));
|
|
1014
|
+
return function(pIter) {
|
|
1015
|
+
const result = f(pIter);
|
|
1016
|
+
return result;
|
|
1017
|
+
};
|
|
1018
|
+
})();
|
|
1019
|
+
|
|
1020
|
+
sqlite3.changeset_invert = (function() {
|
|
1021
|
+
const fname = 'sqlite3changeset_invert';
|
|
1022
|
+
const f = Module.cwrap(fname, ...decl('nn:nn'));
|
|
1023
|
+
return function(changesetData) {
|
|
1024
|
+
// Allocate memory for the input changeset data
|
|
1025
|
+
const inPtr = Module._sqlite3_malloc(changesetData.length);
|
|
1026
|
+
Module.HEAPU8.subarray(inPtr).set(changesetData);
|
|
1027
|
+
|
|
1028
|
+
// Allocate memory for the output changeset length and pointer
|
|
1029
|
+
const outLengthPtr = Module._malloc(4);
|
|
1030
|
+
const outPtrPtr = Module._malloc(4);
|
|
1031
|
+
|
|
1032
|
+
// Call the wrapped C function
|
|
1033
|
+
const result = f(changesetData.length, inPtr, outLengthPtr, outPtrPtr);
|
|
1034
|
+
|
|
1035
|
+
if (result !== SQLite.SQLITE_OK) {
|
|
1036
|
+
check(fname, result); // Handle errors appropriately
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// Retrieve the size and pointer of the inverted changeset
|
|
1040
|
+
const outLength = Module.getValue(outLengthPtr, 'i32');
|
|
1041
|
+
const changesetOutPtr = Module.getValue(outPtrPtr, 'i32');
|
|
1042
|
+
|
|
1043
|
+
// Copy the inverted changeset data
|
|
1044
|
+
const changesetOut = new Uint8Array(Module.HEAPU8.buffer, changesetOutPtr, outLength);
|
|
1045
|
+
|
|
1046
|
+
// Free allocated memory
|
|
1047
|
+
Module._sqlite3_free(inPtr);
|
|
1048
|
+
Module._sqlite3_free(outLengthPtr);
|
|
1049
|
+
Module._sqlite3_free(outPtrPtr);
|
|
1050
|
+
|
|
1051
|
+
return changesetOut;
|
|
1052
|
+
};
|
|
1053
|
+
})();
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Convenience function to get an inverted changeset from a session
|
|
1057
|
+
* without having to call sqlite3session_changeset() and then sqlite3changeset_invert().
|
|
1058
|
+
* It's more efficient as it's reusing the same memory allocation for the changeset.
|
|
1059
|
+
*/
|
|
1060
|
+
sqlite3.session_changeset_inverted = (function() {
|
|
1061
|
+
const fnameChangeset = 'sqlite3session_changeset';
|
|
1062
|
+
const fChangeset = Module.cwrap(fnameChangeset, ...decl('nnn:n'));
|
|
1063
|
+
const fnameInvert = 'sqlite3changeset_invert';
|
|
1064
|
+
const fInvert = Module.cwrap(fnameInvert, ...decl('nn:nn'));
|
|
1065
|
+
return function(pSession) {
|
|
1066
|
+
if (typeof pSession !== 'number') {
|
|
1067
|
+
throw new SQLiteError('Invalid session object', SQLite.SQLITE_MISUSE);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// Allocate memory for the size (int) and the changeset pointer (void*)
|
|
1071
|
+
const sizePtr = Module._malloc(4);
|
|
1072
|
+
const changesetPtrPtr = Module._malloc(4);
|
|
1073
|
+
|
|
1074
|
+
// Allocate memory for the size (int) and the inverted changeset pointer (void*)
|
|
1075
|
+
const sizePtrInvert = Module._malloc(4);
|
|
1076
|
+
const changesetPtrPtrInvert = Module._malloc(4);
|
|
1077
|
+
|
|
1078
|
+
try {
|
|
1079
|
+
const changesetResult = fChangeset(pSession, sizePtr, changesetPtrPtr);
|
|
1080
|
+
if (changesetResult !== SQLite.SQLITE_OK) {
|
|
1081
|
+
return check(fnameChangeset, changesetResult);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Get the size of the changeset
|
|
1085
|
+
const size = Module.getValue(sizePtr, 'i32');
|
|
1086
|
+
// Get the pointer to the changeset
|
|
1087
|
+
const changesetPtr = Module.getValue(changesetPtrPtr, 'i32');
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
const invertedResult = fInvert(size, changesetPtr, sizePtrInvert, changesetPtrPtrInvert);
|
|
1091
|
+
|
|
1092
|
+
if (invertedResult !== SQLite.SQLITE_OK) {
|
|
1093
|
+
return check(fnameInvert, invertedResult);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// Get the size of the changeset
|
|
1097
|
+
const sizeInvert = Module.getValue(sizePtrInvert, 'i32');
|
|
1098
|
+
// Get the pointer to the changeset
|
|
1099
|
+
const changesetPtrInvert = Module.getValue(changesetPtrPtrInvert, 'i32');
|
|
1100
|
+
|
|
1101
|
+
// Copy the changeset data
|
|
1102
|
+
const changesetInvert = new Uint8Array(Module.HEAPU8.buffer, changesetPtrInvert, sizeInvert);
|
|
1103
|
+
|
|
1104
|
+
Module._sqlite3_free(changesetPtr);
|
|
1105
|
+
Module._sqlite3_free(changesetPtrInvert)
|
|
1106
|
+
|
|
1107
|
+
// Return a copy of the changeset
|
|
1108
|
+
return {
|
|
1109
|
+
result: changesetResult,
|
|
1110
|
+
size: size,
|
|
1111
|
+
changeset: new Uint8Array(changesetInvert)
|
|
1112
|
+
};
|
|
1113
|
+
} finally {
|
|
1114
|
+
// Free the allocated memory
|
|
1115
|
+
Module._free(sizePtr);
|
|
1116
|
+
Module._free(changesetPtrPtr);
|
|
1117
|
+
Module._free(sizePtrInvert);
|
|
1118
|
+
Module._free(changesetPtrPtrInvert);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
};
|
|
1122
|
+
})();
|
|
1123
|
+
|
|
1124
|
+
sqlite3.changeset_apply = (function() {
|
|
1125
|
+
const fname = 'sqlite3changeset_apply';
|
|
1126
|
+
const f = Module.cwrap(fname, ...decl('nnnnnn:n'));
|
|
1127
|
+
return function(db, changesetData, options) {
|
|
1128
|
+
/*
|
|
1129
|
+
int sqlite3changeset_apply(
|
|
1130
|
+
sqlite3 *db, Apply change to "main" db of this handle
|
|
1131
|
+
int nChangeset, Size of changeset in bytes
|
|
1132
|
+
void *pChangeset, Changeset blob
|
|
1133
|
+
int(*xFilter)(
|
|
1134
|
+
void *pCtx, Copy of sixth arg to _apply()
|
|
1135
|
+
const char *zTab Table name
|
|
1136
|
+
),
|
|
1137
|
+
int(*xConflict)(
|
|
1138
|
+
void *pCtx, Copy of sixth arg to _apply()
|
|
1139
|
+
int eConflict, DATA, MISSING, CONFLICT, CONSTRAINT
|
|
1140
|
+
sqlite3_changeset_iter *p Handle describing change and conflict
|
|
1141
|
+
),
|
|
1142
|
+
void *pCtx First argument passed to xConflict
|
|
1143
|
+
);
|
|
1144
|
+
*/
|
|
1145
|
+
const inPtr = Module._sqlite3_malloc(changesetData.length);
|
|
1146
|
+
Module.HEAPU8.subarray(inPtr).set(changesetData);
|
|
1147
|
+
|
|
1148
|
+
// https://sqlite.org/session/c_changeset_abort.html
|
|
1149
|
+
const SQLITE_CHANGESET_REPLACE = 1
|
|
1150
|
+
const onConflict = () => {
|
|
1151
|
+
return SQLITE_CHANGESET_REPLACE;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
const result = f(db, changesetData.length, inPtr, null, onConflict, null);
|
|
1155
|
+
|
|
1156
|
+
if (result !== SQLite.SQLITE_OK) {
|
|
1157
|
+
check(fname, result);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
return result;
|
|
1161
|
+
}
|
|
1162
|
+
})();
|
|
1163
|
+
|
|
1164
|
+
// Session extension bindings end
|
|
1165
|
+
|
|
797
1166
|
sqlite3.value = function(pValue) {
|
|
798
1167
|
const type = sqlite3.value_type(pValue);
|
|
799
1168
|
switch (type) {
|
|
@@ -881,11 +1250,18 @@ export function Factory(Module) {
|
|
|
881
1250
|
};
|
|
882
1251
|
})();
|
|
883
1252
|
|
|
1253
|
+
const registeredVfs = new Set();
|
|
1254
|
+
|
|
884
1255
|
sqlite3.vfs_register = function(vfs, makeDefault) {
|
|
1256
|
+
if (registeredVfs.has(vfs.name)) return
|
|
885
1257
|
const result = Module.vfs_register(vfs, makeDefault);
|
|
886
|
-
|
|
1258
|
+
const res = check('sqlite3_vfs_register', result);
|
|
1259
|
+
registeredVfs.add(vfs.name);
|
|
1260
|
+
return res
|
|
887
1261
|
};
|
|
888
1262
|
|
|
1263
|
+
sqlite3.vfs_registered = registeredVfs;
|
|
1264
|
+
|
|
889
1265
|
function check(fname, result, db = null, allowed = [SQLite.SQLITE_OK]) {
|
|
890
1266
|
if (allowed.includes(result)) return result;
|
|
891
1267
|
const message = db ?
|
|
@@ -897,22 +1273,22 @@ export function Factory(Module) {
|
|
|
897
1273
|
// This function is used to automatically retry failed calls that
|
|
898
1274
|
// have pending retry operations that should allow the retry to
|
|
899
1275
|
// succeed.
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1276
|
+
async function retry(f) {
|
|
1277
|
+
let rc;
|
|
1278
|
+
do {
|
|
1279
|
+
// Wait for all pending retry operations to complete. This is
|
|
1280
|
+
// normally empty on the first loop iteration.
|
|
1281
|
+
if (Module.retryOps.length) {
|
|
1282
|
+
await Promise.all(Module.retryOps);
|
|
1283
|
+
Module.retryOps = [];
|
|
1284
|
+
}
|
|
909
1285
|
|
|
910
|
-
|
|
1286
|
+
rc = await f();
|
|
911
1287
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1288
|
+
// Retry on failure with new pending retry operations.
|
|
1289
|
+
} while (rc && Module.retryOps.length);
|
|
1290
|
+
return rc;
|
|
1291
|
+
}
|
|
916
1292
|
|
|
917
1293
|
return sqlite3;
|
|
918
1294
|
}
|
package/src/types/globals.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
declare namespace Asyncify {
|
|
2
|
+
function handleAsync(f: () => Promise<any>);
|
|
3
|
+
}
|
|
4
4
|
|
|
5
5
|
declare function UTF8ToString(ptr: number): string;
|
|
6
6
|
declare function lengthBytesUTF8(s: string): number;
|