1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-27 20:41:58 +03:00

Move JS-to-C binding signatures from sqlite3-api-prologue.js to sqlite3-api-glue.js to allow for use of the new/experimental sqlite3.wasm.xWrap() feature which automatically binds JS functions to WASM/C as needed, which simplifies creation of bindings which take C function pointers. Reimplement sqlite3_exec(), sqlite3_create_collation(), sqlite3_progress_handler() to use this new feature.

FossilOrigin-Name: 9386d6f634680b4e0fa5487c34c63acb29f0b7a6ae738b8f6164ad084a229b62
This commit is contained in:
stephan
2022-12-12 14:31:38 +00:00
parent 5dbfc0dfdd
commit 124fc52d96
6 changed files with 475 additions and 331 deletions

View File

@ -878,250 +878,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
) ? !!capi.sqlite3_compileoption_used(optName) : false;
}/*compileOptionUsed()*/;
/**
Signatures for the WASM-exported C-side functions. Each entry
is an array with 2+ elements:
[ "c-side name",
"result type" (wasm.xWrap() syntax),
[arg types in xWrap() syntax]
// ^^^ this needn't strictly be an array: it can be subsequent
// elements instead: [x,y,z] is equivalent to x,y,z
]
Note that support for the API-specific data types in the
result/argument type strings gets plugged in at a later phase in
the API initialization process.
*/
wasm.bindingSignatures = [
// Please keep these sorted by function name!
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
/* TODO: we should arguably write a custom wrapper which knows
how to handle Blob, TypedArrays, and JS strings. */
],
["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
["sqlite3_bind_pointer", "int",
"sqlite3_stmt*", "int", "*", "string:static", "*"],
["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int"
/* We should arguably create a hand-written binding of
bind_text() which does more flexible text conversion, along
the lines of sqlite3_prepare_v3(). The slightly problematic
part is the final argument (text destructor). */
],
//["sqlite3_busy_handler","int", "sqlite3*", "*", "*"],
// ^^^^ TODO: custom binding which auto-converts JS function arg
// to a WASM function, noting that calling it multiple times
// would introduce a leak.
["sqlite3_busy_timeout","int", "sqlite3*", "int"],
["sqlite3_close_v2", "int", "sqlite3*"],
["sqlite3_changes", "int", "sqlite3*"],
["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
["sqlite3_column_count", "int", "sqlite3_stmt*"],
["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
["sqlite3_compileoption_get", "string", "int"],
["sqlite3_compileoption_used", "int", "string"],
["sqlite3_complete", "int", "string:flexible"],
/* sqlite3_create_function(), sqlite3_create_function_v2(), and
sqlite3_create_window_function() use hand-written bindings to
simplify handling of their function-type arguments. */
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
use hand-written bindings to simplify passing of the callback
function.
["sqlite3_create_collation", "int",
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
"*", "*"],
["sqlite3_create_collation_v2", "int",
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
"*", "*", "*"],
*/
["sqlite3_data_count", "int", "sqlite3_stmt*"],
["sqlite3_db_filename", "string", "sqlite3*", "string"],
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
["sqlite3_db_name", "string", "sqlite3*", "int"],
["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
/* Careful! Short version: de/serialize() are problematic because they
might use a different allocator than the user for managing the
deserialized block. de/serialize() are ONLY safe to use with
sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
["sqlite3_errcode", "int", "sqlite3*"],
["sqlite3_errmsg", "string", "sqlite3*"],
["sqlite3_error_offset", "int", "sqlite3*"],
["sqlite3_errstr", "string", "int"],
/*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
Handled seperately to perform translation of the callback
into a WASM-usable one. ],*/
["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
["sqlite3_extended_errcode", "int", "sqlite3*"],
["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
["sqlite3_finalize", "int", "sqlite3_stmt*"],
["sqlite3_free", undefined,"*"],
["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
["sqlite3_initialize", undefined],
/*["sqlite3_interrupt", undefined, "sqlite3*"
^^^ we cannot actually currently support this because JS is
single-threaded and we don't have a portable way to access a DB
from 2 SharedWorkers concurrently. ],*/
["sqlite3_keyword_count", "int"],
["sqlite3_keyword_name", "int", ["int", "**", "*"]],
["sqlite3_keyword_check", "int", ["string", "int"]],
["sqlite3_libversion", "string"],
["sqlite3_libversion_number", "int"],
["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
["sqlite3_malloc", "*","int"],
["sqlite3_open", "int", "string", "*"],
["sqlite3_open_v2", "int", "string", "*", "int", "string"],
/* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
separately due to us requiring two different sets of semantics
for those, depending on how their SQL argument is provided. */
/* sqlite3_randomness() uses a hand-written wrapper to extend
the range of supported argument types. */
//TODO: hand-written wrapper to convert function-type arg:
//void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
//
//!TODO!: accept arg/result conversion descriptions which are objects
//following an interface and a FuncPtr impl which does that conversion.
//That would require moving these bindings int sqlite3-api-glue.js, after
//whwasmutil.js is loaded.
["sqlite3_progress_handler", undefined, ["sqlite3*","int", "*", "*"]],
["sqlite3_realloc", "*","*","int"],
["sqlite3_reset", "int", "sqlite3_stmt*"],
["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
["sqlite3_result_null", undefined, "sqlite3_context*"],
["sqlite3_result_pointer", undefined,
"sqlite3_context*", "*", "string:static", "*"],
["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
["sqlite3_set_auxdata", undefined, "sqlite3_context*", "int", "*", "*"/* => v(*) */],
["sqlite3_shutdown", undefined],
["sqlite3_sourceid", "string"],
["sqlite3_sql", "string", "sqlite3_stmt*"],
["sqlite3_status", "int", "int", "*", "*", "int"],
["sqlite3_step", "int", "sqlite3_stmt*"],
["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
["sqlite3_strglob", "int", "string","string"],
["sqlite3_stricmp", "int", "string", "string"],
["sqlite3_strlike", "int", "string", "string","int"],
["sqlite3_strnicmp", "int", "string", "string", "int"],
["sqlite3_table_column_metadata", "int",
"sqlite3*", "string", "string", "string",
"**", "**", "*", "*", "*"],
["sqlite3_total_changes", "int", "sqlite3*"],
["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"],
["sqlite3_txn_state", "int", ["sqlite3*","string"]],
/* Note that sqlite3_uri_...() have very specific requirements for
their first C-string arguments, so we cannot perform any value
conversion on those. */
["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
["sqlite3_user_data","void*", "sqlite3_context*"],
["sqlite3_value_blob", "*", "sqlite3_value*"],
["sqlite3_value_bytes","int", "sqlite3_value*"],
["sqlite3_value_double","f64", "sqlite3_value*"],
["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
["sqlite3_value_free", undefined, "sqlite3_value*"],
["sqlite3_value_frombind", "int", "sqlite3_value*"],
["sqlite3_value_int","int", "sqlite3_value*"],
["sqlite3_value_nochange", "int", "sqlite3_value*"],
["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
["sqlite3_value_subtype", "int", "sqlite3_value*"],
["sqlite3_value_text", "string", "sqlite3_value*"],
["sqlite3_value_type", "int", "sqlite3_value*"],
["sqlite3_vfs_find", "*", "string"],
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
]/*wasm.bindingSignatures*/;
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
/* ^^^ "the problem" is that this is an option feature and the
build-time function-export list does not currently take
optional features into account. */
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
}
/**
Functions which require BigInt (int64) support are separated from
the others because we need to conditionally bind them or apply
dummy impls, depending on the capabilities of the environment.
Note that not all of these functions directly require int64
but are only for use with APIs which require int64. For example,
the vtab-related functions.
*/
wasm.bindingSignatures.int64 = [
["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
["sqlite3_changes64","i64", ["sqlite3*"]],
["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
["sqlite3_create_module", "int",
["sqlite3*","string","sqlite3_module*","*"]],
["sqlite3_create_module_v2", "int",
["sqlite3*","string","sqlite3_module*","*","*"]],
["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
["sqlite3_malloc64", "*","i64"],
["sqlite3_msize", "i64", "*"],
["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
["sqlite3_realloc64", "*","*", "i64"],
["sqlite3_result_int64", undefined, "*", "i64"],
["sqlite3_result_zeroblob64", "int", "*", "i64"],
["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
["sqlite3_status64", "int", "int", "*", "*", "int"],
["sqlite3_total_changes64", "i64", ["sqlite3*"]],
["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
["sqlite3_value_int64","i64", "sqlite3_value*"],
["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
/*["sqlite3_vtab_config" is variadic and requires a hand-written
proxy.] */
["sqlite3_vtab_nochange","int", "sqlite3_context*"],
["sqlite3_vtab_on_conflict","int", "sqlite3*"],
["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
];
/**
Functions which are intended solely for API-internal use by the
WASM components, not client code. These get installed into
sqlite3.wasm. Some of them get exposed to clients via variants
named sqlite3_js_...().
*/
wasm.bindingSignatures.wasm = [
["sqlite3_wasm_db_reset", "int", "sqlite3*"],
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
["sqlite3_wasm_vfs_create_file", "int",
"sqlite3_vfs*","string","*", "int"],
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
];
/**
sqlite3.wasm.pstack (pseudo-stack) holds a special-case
stack-style allocator intended only for use with _small_ data of