aboutsummaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api48
-rw-r--r--ext/wasm/api/sqlite3-api-glue.js198
-rw-r--r--ext/wasm/api/sqlite3-wasm.c31
-rw-r--r--ext/wasm/common/whwasmutil.js20
4 files changed, 281 insertions, 16 deletions
diff --git a/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api b/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
index 47a7e4a06..a6559cbb3 100644
--- a/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
+++ b/ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
@@ -1,3 +1,6 @@
+_malloc
+_free
+_realloc
_sqlite3_aggregate_context
_sqlite3_bind_blob
_sqlite3_bind_double
@@ -144,6 +147,45 @@ _sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
-_malloc
-_free
-_realloc
+_sqlite3changegroup_add
+_sqlite3changegroup_add_strm
+_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
diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js
index 85c549ae3..fc5e2823d 100644
--- a/ext/wasm/api/sqlite3-api-glue.js
+++ b/ext/wasm/api/sqlite3-api-glue.js
@@ -314,6 +314,187 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["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. Additionally, the callback-taking APIs
+ have a shortcoming which will make using those which take
+ string-type arguments more painful than it should be. How best
+ to resolve that, such that we can perform the same type conversions
+ as we do when binding in "the other direction," is as yet
+ undetermined.
+ */
+ /* TODO: we need hand-written wrappers to adapt callbacks which
+ take string arguments. Or we need to find a way to do this sort
+ of reverse-binding which includes type conversions. */
+ 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', signature: 'i(ps)', bindScope: 'transient'
+ }),
+ 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', signature: 'i(ps)', bindScope: 'transient'
+ }),
+ 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', signature: 'i(ps)', bindScope: 'transient'
+ }),
+ new wasm.xWrap.FuncPtrAdapter({
+ name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
+ }),
+ 'void*', '**', 'int*', 'int'
+
+ ]],
+ ['sqlite3changeset_apply_v2', 'int', [
+ 'sqlite3*', 'int', 'void*',
+ new wasm.xWrap.FuncPtrAdapter({
+ name: 'xFilter', signature: 'i(ps)', bindScope: 'transient'
+ }),
+ 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', signature: 'i(ps)', bindScope: 'transient'
+ }),
+ 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', signature: 'i(ps)',
+ contextKey: (argIndex,argv)=>argv[0/* (sqlite3_session*) */]
+ }),
+ '*'
+ ]]
+ ]);
+ }/*session/changeset APIs*/
+
/**
Functions which are intended solely for API-internal use by the
WASM components, not client code. These get installed into
@@ -383,10 +564,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
if(1){// wasm.xWrap() bindings...
/**
Add some descriptive xWrap() aliases for '*' intended to (A)
- initially improve readability/correctness of capi.signatures
- and (B) provide automatic conversion from higher-level
- representations, e.g. capi.sqlite3_vfs to `sqlite3_vfs*` via
- capi.sqlite3_vfs.pointer.
+ initially improve readability/correctness of
+ wasm.bindingSignatures and (B) provide automatic conversion
+ from higher-level representations, e.g. capi.sqlite3_vfs to
+ `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
*/
const aPtr = wasm.xWrap.argAdapter('*');
const nilType = function(){};
@@ -394,6 +575,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
('sqlite3_context*', aPtr)
('sqlite3_value*', aPtr)
('void*', aPtr)
+ ('sqlite3_changegroup*', aPtr)
+ ('sqlite3_changeset_iter*', aPtr)
+ //('sqlite3_rebaser*', aPtr)
+ ('sqlite3_session*', aPtr)
('sqlite3_stmt*', (v)=>
aPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
? v.pointer : v))
@@ -1021,7 +1206,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
// Groups of SQLITE_xyz macros...
const defineGroups = ['access', 'authorizer',
- 'blobFinalizers', 'config', 'dataTypes',
+ 'blobFinalizers', 'changeset',
+ 'config', 'dataTypes',
'dbConfig', 'dbStatus',
'encodings', 'fcntl', 'flock', 'ioCap',
'limits', 'openFlags',
@@ -1031,7 +1217,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'trace', 'txnState', 'udfFlags',
'version' ];
if(wasm.bigIntEnabled){
- defineGroups.push('serialize', 'vtab');
+ defineGroups.push('serialize', 'session', 'vtab');
}
for(const t of defineGroups){
for(const e of Object.entries(wasm.ctype[t])){
diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c
index 5c9b53318..b39e252b1 100644
--- a/ext/wasm/api/sqlite3-wasm.c
+++ b/ext/wasm/api/sqlite3-wasm.c
@@ -99,15 +99,21 @@
#ifndef SQLITE_ENABLE_FTS4
# define SQLITE_ENABLE_FTS4 1
#endif
+#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
+# define SQLITE_ENABLE_MATH_FUNCTIONS 1
+#endif
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
#endif
-#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
-# define SQLITE_ENABLE_MATH_FUNCTIONS 1
+#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
+# define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
#endif
#ifndef SQLITE_ENABLE_RTREE
# define SQLITE_ENABLE_RTREE 1
#endif
+#ifndef SQLITE_ENABLE_SESSION
+# define SQLITE_ENABLE_SESSION 1
+#endif
#ifndef SQLITE_ENABLE_STMTVTAB
# define SQLITE_ENABLE_STMTVTAB 1
#endif
@@ -460,6 +466,22 @@ const char * sqlite3_wasm_enum_json(void){
out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1");
} _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){
DefInt(SQLITE_CONFIG_SINGLETHREAD);
DefInt(SQLITE_CONFIG_MULTITHREAD);
@@ -796,6 +818,11 @@ const char * sqlite3_wasm_enum_json(void){
DefInt(SQLITE_DESERIALIZE_RESIZEABLE);
} _DefGroup;
+ DefGroup(session){
+ DefInt(SQLITE_SESSION_CONFIG_STRMSIZE);
+ DefInt(SQLITE_SESSION_OBJCONFIG_SIZE);
+ } _DefGroup;
+
DefGroup(sqlite3Status){
DefInt(SQLITE_STATUS_MEMORY_USED);
DefInt(SQLITE_STATUS_PAGECACHE_USED);
diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js
index 8e1858612..c296a946b 100644
--- a/ext/wasm/common/whwasmutil.js
+++ b/ext/wasm/common/whwasmutil.js
@@ -447,7 +447,7 @@ self.WhWasmUtilInstaller = function(target){
type(s) of the given function signature, or throws if the
signature is invalid. */
/******** // 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){
const rc = {parameters:[], results: []};
if('v'!==sig[0]) rc.results.push(f.sigTypes(sig[0]));
@@ -1590,10 +1590,20 @@ self.WhWasmUtilInstaller = function(target){
not actually bind any functions. Its convertArg() method is
called via xWrap() to perform any bindings.
- Shortcomings: 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.
+ Shortcomings:
+
+ - These "reverse" bindings, i.e. calling into a JS-defined
+ 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 {
constructor(opt) {