1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Merge wasm-session-api branch into trunk, adding the session API to the JS/WASM components.

FossilOrigin-Name: dfb8b651fa4faef2d3307a05512cdc479398484c3a59715827179c363861a777
This commit is contained in:
stephan
2022-12-25 20:25:44 +00:00
9 changed files with 412 additions and 40 deletions

View File

@ -1,3 +1,6 @@
_malloc
_free
_realloc
_sqlite3_aggregate_context _sqlite3_aggregate_context
_sqlite3_bind_blob _sqlite3_bind_blob
_sqlite3_bind_double _sqlite3_bind_double
@ -144,6 +147,45 @@ _sqlite3_vtab_in_next
_sqlite3_vtab_nochange _sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict _sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value _sqlite3_vtab_rhs_value
_malloc _sqlite3changegroup_add
_free _sqlite3changegroup_add_strm
_realloc _sqlite3changegroup_delete
_sqlite3changegroup_new
_sqlite3changegroup_output
_sqlite3changegroup_output_strm
_sqlite3changeset_apply
_sqlite3changeset_apply_strm
_sqlite3changeset_apply_v2
_sqlite3changeset_apply_v2_strm
_sqlite3changeset_concat
_sqlite3changeset_concat_strm
_sqlite3changeset_conflict
_sqlite3changeset_finalize
_sqlite3changeset_fk_conflicts
_sqlite3changeset_invert
_sqlite3changeset_invert_strm
_sqlite3changeset_new
_sqlite3changeset_next
_sqlite3changeset_old
_sqlite3changeset_op
_sqlite3changeset_pk
_sqlite3changeset_start
_sqlite3changeset_start_strm
_sqlite3changeset_start_v2
_sqlite3changeset_start_v2_strm
_sqlite3session_attach
_sqlite3session_changeset
_sqlite3session_changeset_size
_sqlite3session_changeset_strm
_sqlite3session_config
_sqlite3session_create
_sqlite3session_delete
_sqlite3session_diff
_sqlite3session_enable
_sqlite3session_indirect
_sqlite3session_isempty
_sqlite3session_memory_used
_sqlite3session_object_config
_sqlite3session_patchset
_sqlite3session_patchset_strm
_sqlite3session_table_filter

View File

@ -337,6 +337,184 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"] ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
]; ];
// Add session/changeset APIs...
if(wasm.bigIntEnabled && !!wasm.exports.sqlite3changegroup_add){
/* ACHTUNG: 2022-12-23: the session/changeset API bindings are
COMPLETELY UNTESTED. */
/**
FuncPtrAdapter options for session-related callbacks with the
native signature "i(ps)". This proxy converts the 2nd argument
from a C string to a JS string before passing the arguments on
to the client-provided JS callback.
*/
const __ipsProxy = {
signature: 'i(ps)',
callProxy:(callback)=>{
return (p,s)=>{
try{return callback(p, wasm.cstrToJs(s)) | 0}
catch(e){return e.resultCode || capi.SQLITE_ERROR}
}
}
};
wasm.bindingSignatures.int64.push(...[
['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
['sqlite3changegroup_add_strm', 'int', [
'sqlite3_changegroup*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changegroup_delete', undefined, ['sqlite3_changegroup*']],
['sqlite3changegroup_new', 'int', ['**']],
['sqlite3changegroup_output', 'int', ['sqlite3_changegroup*', 'int*', '**']],
['sqlite3changegroup_output_strm', 'int', [
'sqlite3_changegroup*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_apply', 'int', [
'sqlite3*', 'int', 'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xFilter', bindScope: 'transient', ...__ipsProxy
}),
new wasm.xWrap.FuncPtrAdapter({
name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_apply_strm', 'int', [
'sqlite3*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xFilter', bindScope: 'transient', ...__ipsProxy
}),
new wasm.xWrap.FuncPtrAdapter({
name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_apply_v2', 'int', [
'sqlite3*', 'int', 'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xFilter', bindScope: 'transient', ...__ipsProxy
}),
new wasm.xWrap.FuncPtrAdapter({
name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
}),
'void*', '**', 'int*', 'int'
]],
['sqlite3changeset_apply_v2_strm', 'int', [
'sqlite3*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xFilter', bindScope: 'transient', ...__ipsProxy
}),
new wasm.xWrap.FuncPtrAdapter({
name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
}),
'void*', '**', 'int*', 'int'
]],
['sqlite3changeset_concat', 'int', ['int','void*', 'int', 'void*', 'int*', '**']],
['sqlite3changeset_concat_strm', 'int', [
new wasm.xWrap.FuncPtrAdapter({
name: 'xInputA', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInputB', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_conflict', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
['sqlite3changeset_finalize', 'int', ['sqlite3_changeset_iter*']],
['sqlite3changeset_fk_conflicts', 'int', ['sqlite3_changeset_iter*', 'int*']],
['sqlite3changeset_invert', 'int', ['int', 'void*', 'int*', '**']],
['sqlite3changeset_invert_strm', 'int', [
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_new', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
['sqlite3changeset_next', 'int', ['sqlite3_changeset_iter*']],
['sqlite3changeset_old', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
['sqlite3changeset_op', 'int', [
'sqlite3_changeset_iter*', '**', 'int*', 'int*','int*'
]],
['sqlite3changeset_pk', 'int', ['sqlite3_changeset_iter*', '**', 'int*']],
['sqlite3changeset_start', 'int', ['**', 'int', '*']],
['sqlite3changeset_start_strm', 'int', [
'**',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3changeset_start_v2', 'int', ['**', 'int', '*', 'int']],
['sqlite3changeset_start_v2_strm', 'int', [
'**',
new wasm.xWrap.FuncPtrAdapter({
name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*', 'int'
]],
['sqlite3session_attach', 'int', ['sqlite3_session*', 'string']],
['sqlite3session_changeset', 'int', ['sqlite3_session*', 'int*', '**']],
['sqlite3session_changeset_size', 'i64', ['sqlite3_session*']],
['sqlite3session_changeset_strm', 'int', [
'sqlite3_session*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3session_config', 'int', ['int', 'void*']],
['sqlite3session_create', 'int', ['sqlite3*', 'string', '**']],
['sqlite3session_delete', undefined, ['sqlite3_session*']],
['sqlite3session_diff', 'int', ['sqlite3_session*', 'string', 'string', '**']],
['sqlite3session_enable', 'int', ['sqlite3_session*', 'int']],
['sqlite3session_indirect', 'int', ['sqlite3_session*', 'int']],
['sqlite3session_isempty', 'int', ['sqlite3_session*']],
['sqlite3session_memory_used', 'i64', ['sqlite3_session*']],
['sqlite3session_object_config', 'int', ['sqlite3_session*', 'int', 'void*']],
['sqlite3session_patchset', 'int', ['sqlite3_session*', '*', '**']],
['sqlite3session_patchset_strm', 'int', [
'sqlite3_session*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
}),
'void*'
]],
['sqlite3session_table_filter', undefined, [
'sqlite3_session*',
new wasm.xWrap.FuncPtrAdapter({
name: 'xFilter', ...__ipsProxy,
contextKey: (argv,argIndex)=>argv[0/* (sqlite3_session*) */]
}),
'*'
]]
]);
}/*session/changeset APIs*/
/** /**
Functions which are intended solely for API-internal use by the Functions which are intended solely for API-internal use by the
WASM components, not client code. These get installed into WASM components, not client code. These get installed into
@ -406,10 +584,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
if(1){// wasm.xWrap() bindings... if(1){// wasm.xWrap() bindings...
/** /**
Add some descriptive xWrap() aliases for '*' intended to (A) Add some descriptive xWrap() aliases for '*' intended to (A)
initially improve readability/correctness of capi.signatures initially improve readability/correctness of
and (B) provide automatic conversion from higher-level wasm.bindingSignatures and (B) provide automatic conversion
representations, e.g. capi.sqlite3_vfs to `sqlite3_vfs*` via from higher-level representations, e.g. capi.sqlite3_vfs to
capi.sqlite3_vfs.pointer. `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
*/ */
const aPtr = wasm.xWrap.argAdapter('*'); const aPtr = wasm.xWrap.argAdapter('*');
const nilType = function(){}; const nilType = function(){};
@ -417,6 +595,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
('sqlite3_context*', aPtr) ('sqlite3_context*', aPtr)
('sqlite3_value*', aPtr) ('sqlite3_value*', aPtr)
('void*', aPtr) ('void*', aPtr)
('sqlite3_changegroup*', aPtr)
('sqlite3_changeset_iter*', aPtr)
//('sqlite3_rebaser*', aPtr)
('sqlite3_session*', aPtr)
('sqlite3_stmt*', (v)=> ('sqlite3_stmt*', (v)=>
aPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType)) aPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
? v.pointer : v)) ? v.pointer : v))
@ -1001,7 +1183,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson)); wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
// Groups of SQLITE_xyz macros... // Groups of SQLITE_xyz macros...
const defineGroups = ['access', 'authorizer', const defineGroups = ['access', 'authorizer',
'blobFinalizers', 'config', 'dataTypes', 'blobFinalizers', 'changeset',
'config', 'dataTypes',
'dbConfig', 'dbStatus', 'dbConfig', 'dbStatus',
'encodings', 'fcntl', 'flock', 'ioCap', 'encodings', 'fcntl', 'flock', 'ioCap',
'limits', 'openFlags', 'limits', 'openFlags',
@ -1011,7 +1194,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'trace', 'txnState', 'udfFlags', 'trace', 'txnState', 'udfFlags',
'version' ]; 'version' ];
if(wasm.bigIntEnabled){ if(wasm.bigIntEnabled){
defineGroups.push('serialize', 'vtab'); defineGroups.push('serialize', 'session', 'vtab');
} }
for(const t of defineGroups){ for(const t of defineGroups){
for(const e of Object.entries(wasm.ctype[t])){ for(const e of Object.entries(wasm.ctype[t])){

View File

@ -72,7 +72,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.installFunction('i(ippp)', function(t,c,p,x){ wasm.installFunction('i(ippp)', function(t,c,p,x){
if(capi.SQLITE_TRACE_STMT===t){ if(capi.SQLITE_TRACE_STMT===t){
// x == SQL, p == sqlite3_stmt* // x == SQL, p == sqlite3_stmt*
console.log("SQL TRACE #"+(++this.counter), console.log("SQL TRACE #"+(++this.counter)+' via sqlite3@'+c+':',
wasm.cstrToJs(x)); wasm.cstrToJs(x));
} }
}.bind({counter: 0})); }.bind({counter: 0}));
@ -161,7 +161,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
capi.sqlite3_extended_result_codes(pDb, 1); capi.sqlite3_extended_result_codes(pDb, 1);
if(flagsStr.indexOf('t')>=0){ if(flagsStr.indexOf('t')>=0){
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT, capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
__dbTraceToConsole, 0); __dbTraceToConsole, pDb);
} }
}catch( e ){ }catch( e ){
if( pDb ) capi.sqlite3_close_v2(pDb); if( pDb ) capi.sqlite3_close_v2(pDb);

View File

@ -1020,12 +1020,20 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
to the memory. On error, returns throws a WasmAllocError. The to the memory. On error, returns throws a WasmAllocError. The
memory must eventually be released using restore(). memory must eventually be released using restore().
If n is a string, it must be a WASM "IR" value in the set
accepted by wasm.irSizeof(), which is mapped to the size of
that data type. If passed a string not in that set, it throws a
WasmAllocError.
This method always adjusts the given value to be a multiple This method always adjusts the given value to be a multiple
of 8 bytes because failing to do so can lead to incorrect of 8 bytes because failing to do so can lead to incorrect
results when reading and writing 64-bit values from/to the WASM results when reading and writing 64-bit values from/to the WASM
heap. Similarly, the returned address is always 8-byte aligned. heap. Similarly, the returned address is always 8-byte aligned.
*/ */
alloc: (n)=>{ alloc: function(n){
if('string'===typeof n && !(n = wasm.irSizeof(n))){
WasmAllocError.toss("Invalid value for pstack.alloc(",arguments[0],")");
}
return wasm.exports.sqlite3_wasm_pstack_alloc(n) return wasm.exports.sqlite3_wasm_pstack_alloc(n)
|| WasmAllocError.toss("Could not allocate",n, || WasmAllocError.toss("Could not allocate",n,
"bytes from the pstack."); "bytes from the pstack.");
@ -1035,6 +1043,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
returns the addresses as an array of n element, each holding returns the addresses as an array of n element, each holding
the address of one chunk. the address of one chunk.
sz may optionally be an IR string accepted by wasm.irSizeof().
Throws a WasmAllocError if allocation fails. Throws a WasmAllocError if allocation fails.
Example: Example:
@ -1043,7 +1053,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const [p1, p2, p3] = wasm.pstack.allocChunks(3,4); const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
``` ```
*/ */
allocChunks: (n,sz)=>{ allocChunks: function(n,sz){
if('string'===typeof sz && !(sz = wasm.irSizeof(sz))){
WasmAllocError.toss("Invalid size value for allocChunks(",arguments[1],")");
}
const mem = wasm.pstack.alloc(n * sz); const mem = wasm.pstack.alloc(n * sz);
const rc = []; const rc = [];
let i = 0, offset = 0; let i = 0, offset = 0;

View File

@ -99,15 +99,21 @@
#ifndef SQLITE_ENABLE_FTS4 #ifndef SQLITE_ENABLE_FTS4
# define SQLITE_ENABLE_FTS4 1 # define SQLITE_ENABLE_FTS4 1
#endif #endif
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
#endif
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS #ifndef SQLITE_ENABLE_MATH_FUNCTIONS
# define SQLITE_ENABLE_MATH_FUNCTIONS 1 # define SQLITE_ENABLE_MATH_FUNCTIONS 1
#endif #endif
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
#endif
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
# define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
#endif
#ifndef SQLITE_ENABLE_RTREE #ifndef SQLITE_ENABLE_RTREE
# define SQLITE_ENABLE_RTREE 1 # define SQLITE_ENABLE_RTREE 1
#endif #endif
#ifndef SQLITE_ENABLE_SESSION
# define SQLITE_ENABLE_SESSION 1
#endif
#ifndef SQLITE_ENABLE_STMTVTAB #ifndef SQLITE_ENABLE_STMTVTAB
# define SQLITE_ENABLE_STMTVTAB 1 # define SQLITE_ENABLE_STMTVTAB 1
#endif #endif
@ -460,6 +466,22 @@ const char * sqlite3_wasm_enum_json(void){
out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1"); out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1");
} _DefGroup; } _DefGroup;
DefGroup(changeset){
DefInt(SQLITE_CHANGESETSTART_INVERT);
DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
DefInt(SQLITE_CHANGESETAPPLY_INVERT);
DefInt(SQLITE_CHANGESET_DATA);
DefInt(SQLITE_CHANGESET_NOTFOUND);
DefInt(SQLITE_CHANGESET_CONFLICT);
DefInt(SQLITE_CHANGESET_CONSTRAINT);
DefInt(SQLITE_CHANGESET_FOREIGN_KEY);
DefInt(SQLITE_CHANGESET_OMIT);
DefInt(SQLITE_CHANGESET_REPLACE);
DefInt(SQLITE_CHANGESET_ABORT);
} _DefGroup;
DefGroup(config){ DefGroup(config){
DefInt(SQLITE_CONFIG_SINGLETHREAD); DefInt(SQLITE_CONFIG_SINGLETHREAD);
DefInt(SQLITE_CONFIG_MULTITHREAD); DefInt(SQLITE_CONFIG_MULTITHREAD);
@ -796,6 +818,11 @@ const char * sqlite3_wasm_enum_json(void){
DefInt(SQLITE_DESERIALIZE_RESIZEABLE); DefInt(SQLITE_DESERIALIZE_RESIZEABLE);
} _DefGroup; } _DefGroup;
DefGroup(session){
DefInt(SQLITE_SESSION_CONFIG_STRMSIZE);
DefInt(SQLITE_SESSION_OBJCONFIG_SIZE);
} _DefGroup;
DefGroup(sqlite3Status){ DefGroup(sqlite3Status){
DefInt(SQLITE_STATUS_MEMORY_USED); DefInt(SQLITE_STATUS_MEMORY_USED);
DefInt(SQLITE_STATUS_PAGECACHE_USED); DefInt(SQLITE_STATUS_PAGECACHE_USED);

View File

@ -246,6 +246,25 @@ self.WhWasmUtilInstaller = function(target){
cache.utf8Decoder = new TextDecoder(); cache.utf8Decoder = new TextDecoder();
cache.utf8Encoder = new TextEncoder('utf-8'); cache.utf8Encoder = new TextEncoder('utf-8');
/**
For the given IR-like string in the set ('i8', 'i16', 'i32',
'f32', 'float', 'i64', 'f64', 'double', '*'), or any string value
ending in '*', returns the sizeof for that value
(target.ptrSizeof in the latter case). For any other value, it
returns the undefined value.
*/
target.irSizeof = (n)=>{
switch(n){
case 'i8': return 1;
case 'i16': return 2;
case 'i32': case 'f32': case 'float': return 4;
case 'i64': case 'f64': case 'double': return 8;
case '*': return ptrSizeof;
default:
return (''+n).endsWith('*') ? ptrSizeof : undefined;
}
};
/** /**
If (cache.heapSize !== cache.memory.buffer.byteLength), i.e. if If (cache.heapSize !== cache.memory.buffer.byteLength), i.e. if
the heap has grown since the last call, updates cache.HEAPxyz. the heap has grown since the last call, updates cache.HEAPxyz.
@ -447,7 +466,7 @@ self.WhWasmUtilInstaller = function(target){
type(s) of the given function signature, or throws if the type(s) of the given function signature, or throws if the
signature is invalid. */ signature is invalid. */
/******** // only valid for use with the WebAssembly.Function ctor, which /******** // only valid for use with the WebAssembly.Function ctor, which
// is not yet documented on MDN. // is not yet documented on MDN.
sigToWasm: function(sig){ sigToWasm: function(sig){
const rc = {parameters:[], results: []}; const rc = {parameters:[], results: []};
if('v'!==sig[0]) rc.results.push(f.sigTypes(sig[0])); if('v'!==sig[0]) rc.results.push(f.sigTypes(sig[0]));
@ -1590,10 +1609,20 @@ self.WhWasmUtilInstaller = function(target){
not actually bind any functions. Its convertArg() method is not actually bind any functions. Its convertArg() method is
called via xWrap() to perform any bindings. called via xWrap() to perform any bindings.
Shortcomings: function pointers which include C-string arguments Shortcomings:
may still need a level of hand-written wrappers around them,
depending on how they're used, in order to provide the client - These "reverse" bindings, i.e. calling into a JS-defined
with JS strings. function from a WASM-defined function (the generated proxy
wrapper), lack all type conversion support. That means, for
example, that...
- Function pointers which include C-string arguments may still
need a level of hand-written wrappers around them, depending on
how they're used, in order to provide the client with JS
strings. Alternately, clients will need to perform such conversions
on their own, e.g. using cstrtojs(). Or maybe we can find a way
to perform such conversions here, via addition of an xWrap()-style
function signature to the options argument.
*/ */
xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter { xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
constructor(opt) { constructor(opt) {

View File

@ -1010,7 +1010,12 @@ self.sqlite3InitModule = sqlite3InitModule;
T.assert(P.quota >= 4096) T.assert(P.quota >= 4096)
.assert(remaining === P.quota) .assert(remaining === P.quota)
.mustThrowMatching(()=>P.alloc(0), isAllocErr) .mustThrowMatching(()=>P.alloc(0), isAllocErr)
.mustThrowMatching(()=>P.alloc(-1), isAllocErr); .mustThrowMatching(()=>P.alloc(-1), isAllocErr)
.mustThrowMatching(
()=>P.alloc('i33'),
(e)=>e instanceof sqlite3.WasmAllocError
);
;
let p1 = P.alloc(12); let p1 = P.alloc(12);
T.assert(p1 === stack - 16/*8-byte aligned*/) T.assert(p1 === stack - 16/*8-byte aligned*/)
.assert(P.pointer === p1); .assert(P.pointer === p1);
@ -1029,7 +1034,7 @@ self.sqlite3InitModule = sqlite3InitModule;
T.assert(P.pointer === stack); T.assert(P.pointer === stack);
try { try {
const [p1, p2, p3] = P.allocChunks(3,4); const [p1, p2, p3] = P.allocChunks(3,'i32');
T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/) T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/)
.assert(p2 === p1 + 4) .assert(p2 === p1 + 4)
.assert(p3 === p2 + 4); .assert(p3 === p2 + 4);
@ -1143,7 +1148,7 @@ self.sqlite3InitModule = sqlite3InitModule;
} }
} }
}; };
T.assert(wasm.isPtr(db.pointer)) T.assert(wasm.isPtr(db.pointer))
.mustThrowMatching(()=>db.pointer=1, /read-only/) .mustThrowMatching(()=>db.pointer=1, /read-only/)
.assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1)) .assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
@ -1183,7 +1188,7 @@ self.sqlite3InitModule = sqlite3InitModule;
T.assert(0 === rc); T.assert(0 === rc);
const stack = wasm.pstack.pointer; const stack = wasm.pstack.pointer;
try { try {
const [pCur, pHi] = wasm.pstack.allocChunks(2,8); const [pCur, pHi] = wasm.pstack.allocChunks(2,'i64');
rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED, rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED,
pCur, pHi, 0); pCur, pHi, 0);
T.assert(0===rc); T.assert(0===rc);
@ -1729,7 +1734,7 @@ self.sqlite3InitModule = sqlite3InitModule;
// sqlite3_result_xyz() and return undefined. Both are // sqlite3_result_xyz() and return undefined. Both are
// functionally equivalent. // functionally equivalent.
} }
}); });
T.assert(18===db.selectValue('select summerN(1,8,9), summerN(2,3,4)')); T.assert(18===db.selectValue('select summerN(1,8,9), summerN(2,3,4)'));
T.mustThrowMatching(()=>{ T.mustThrowMatching(()=>{
db.createFunction('nope',{ db.createFunction('nope',{
@ -1856,7 +1861,6 @@ self.sqlite3InitModule = sqlite3InitModule;
.assert('select 2;' === rc[1]) .assert('select 2;' === rc[1])
.assert('-- empty\n; select 3' === rc[2] .assert('-- empty\n; select 3' === rc[2]
/* Strange but true. */); /* Strange but true. */);
T.mustThrowMatching(()=>{ T.mustThrowMatching(()=>{
db.exec({sql:'', returnValue: 'nope'}); db.exec({sql:'', returnValue: 'nope'});
}, /^Invalid returnValue/); }, /^Invalid returnValue/);
@ -2635,6 +2639,79 @@ self.sqlite3InitModule = sqlite3InitModule;
}/*OPFS util sanity checks*/) }/*OPFS util sanity checks*/)
;/* end OPFS tests */ ;/* end OPFS tests */
T.g('Session API')
.t({
name: 'Session API sanity checks',
predicate: ()=>!!capi.sqlite3changegroup_add,
test: function(sqlite3){
warn("The session API tests could use some expansion.");
const db1 = new sqlite3.oo1.DB(), db2 = new sqlite3.oo1.DB();
const sqlInit = [
"create table t(rowid INTEGER PRIMARY KEY,a,b); ",
"insert into t(rowid,a,b) values",
"(1,'a1','b1'),",
"(2,'a2','b2'),",
"(3,'a3','b3');"
].join('');
db1.exec(sqlInit);
db2.exec(sqlInit);
T.assert(3 === db1.selectValue("select count(*) from t"))
.assert('b3' === db1.selectValue('select b from t where rowid=3'));
const stackPtr = wasm.pstack.pointer;
try{
let ppOut = wasm.pstack.allocPtr();
let rc = capi.sqlite3session_create(db1, "main", ppOut);
T.assert(0===rc);
let pSession = wasm.peekPtr(ppOut);
T.assert(pSession && wasm.isPtr(pSession));
if(1){
capi.sqlite3session_table_filter(pSession, (pCtx, tbl)=>{
T.assert('t' === tbl).assert( 99 === pCtx );
return 1;
}, 99);
}else{
rc = capi.sqlite3session_attach(pSession, "t");
T.assert( 0 === rc );
}
db1.exec([
"update t set b='bTwo' where rowid=2;",
"update t set a='aThree' where rowid=3;",
"delete from t where rowid=1;",
"insert into t(rowid,a,b) values(4,'a4','b4')"
]);
T.assert('bTwo' === db1.selectValue("select b from t where rowid=2"))
.assert(undefined === db1.selectValue('select a from t where rowid=1'))
.assert('b4' === db1.selectValue('select b from t where rowid=4'));
let pnChanges = wasm.pstack.alloc('i32'),
ppChanges = wasm.pstack.allocPtr();
rc = capi.sqlite3session_changeset(pSession, pnChanges, ppChanges);
T.assert( 0 === rc );
capi.sqlite3session_delete(pSession);
pSession = 0;
const pChanges = wasm.peekPtr(ppChanges),
nChanges = wasm.peek32(pnChanges);
T.assert( pChanges && wasm.isPtr( pChanges ) ).assert( nChanges > 0 );
pnChanges = ppChanges = 0;
//log("pnChanges =", pnChanges, wasm.peek32(pnChanges), '@', pChanges);
rc = capi.sqlite3changeset_apply(
db2, nChanges, pChanges, 0, (pCtx, eConflict, pIter)=>{
return pCtx ? 1 : 0
}, 1
);
wasm.dealloc( pChanges );
T.assert( 0 === rc )
.assert( 3 === db2.selectValue('select count(*) from t'))
.assert( 'b4' === db2.selectValue('select b from t where rowid=4') );
}finally{
wasm.pstack.restore(stackPtr);
db1.close();
db2.close();
}
}
})
;/*end of session API group*/;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
log("Loading and initializing sqlite3 WASM module..."); log("Loading and initializing sqlite3 WASM module...");
if(!self.sqlite3InitModule && !isUIThread()){ if(!self.sqlite3InitModule && !isUIThread()){

View File

@ -1,5 +1,5 @@
C Add\stests\sconfirming\sthat\sJS\ssqlite3_exec()'s\sSQL\sargument\sparticipates\sin\sthe\s'string:flexible'\stype\sconversion. C Merge\swasm-session-api\sbranch\sinto\strunk,\sadding\sthe\ssession\sAPI\sto\sthe\sJS/WASM\scomponents.
D 2022-12-25T17:12:24.209 D 2022-12-25T20:25:44.871
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -494,7 +494,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a
F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20 F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9 F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 7e0468ad0294786da90b2062043288f734a65243a458a541f2f880a785be0bb9 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api beec6b5993e234153446aaa48e68d2a75db590b3c7eed26bd61e5fb5f8c9a881
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54 F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
@ -503,16 +503,16 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4 F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
F ext/wasm/api/sqlite3-api-glue.js 7e8bbf3a987b7220db8220045c4d575744bac9faa0d6bc2924ce93e89d1176e3 F ext/wasm/api/sqlite3-api-glue.js 594741f7cbff68f0b4a0c1a066bce335146de1124366377292e27d30f9a5f751
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b F ext/wasm/api/sqlite3-api-oo1.js ae4f6950913b4703b767f640a533675b45e9e6c462bf01e357cec16bc68943e2
F ext/wasm/api/sqlite3-api-prologue.js 30dc037af2f33e773ea6c5e0362a44f1de69e174d729dd33e8049cf2d0676fa2 F ext/wasm/api/sqlite3-api-prologue.js 9dfbb41ebc0aadfac9c41ae8d050187af39819fff4e4f22ac6a8a4f3008f722b
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24 F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 325ca43b982ef608243493c42249ba4e6b2e549f7cbd9b332e2f7ee8227d2ae3 F ext/wasm/api/sqlite3-wasm.c 2bee083def8f832c863d5f0a0fcbff86c236412663c6d3458128db154c0fccc8
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54 F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
@ -521,7 +521,7 @@ F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c07
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
F ext/wasm/common/whwasmutil.js 02d04a086a16130e97dc2a04555686dc19c48bd41842a96934737365678ca839 F ext/wasm/common/whwasmutil.js 77aedbe53b05bfe08f4ca52e96d520eb14d792df09e107df6e3d1300de37e02f
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508 F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6 F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9 F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406 F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
F ext/wasm/tester1.c-pp.js 1396611f11d75fc124ffb7600dc05d3ad7cc25885c4a8f842b9291ea9e0b8abd F ext/wasm/tester1.c-pp.js 314e7bdbc73f558cf12c050c5af42f866195ee17bf451d63f7337052fcf44c7a
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70 F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@ -2067,8 +2067,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 4888957baf18c6763f959fbba998a74156ff656368779107f502b926e9e9d949 P 926d0c61a391c601adc2804d3fdaa8b667ae2abd565939cddfa12d5151b098f8 64e032602cf420851c8029603c76f5512000d1c9a40fa7a545528d69d6d1d4cc
R cfaf4d7e6ebced21987511a642eb3cd6 R 5a9d5d7e14f03170b616d0bb48ba8894
T +closed 64e032602cf420851c8029603c76f5512000d1c9a40fa7a545528d69d6d1d4cc Closed\sby\sintegrate-merge.
U stephan U stephan
Z c6e0af2cef9d9cd33fe188241216b8ea Z 42f975ba9994385873d5d768be40b720
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
926d0c61a391c601adc2804d3fdaa8b667ae2abd565939cddfa12d5151b098f8 dfb8b651fa4faef2d3307a05512cdc479398484c3a59715827179c363861a777