See also: WASM utilities, Gotchas
- Symbolic Constants
- JavaScript Exceptions
- Achtung: Allocators
- Argument and Result Type Conversions
- WASM APIs Which Differ from Their C Counterparts
- sqlite3_bind_blob()
- sqlite3_bind_text()
- sqlite3_close_v2()
- sqlite3_config()
- sqlite3_create_collation() and friends
- sqlite3_create_function() and friends
- sqlite3_db_config()
- sqlite3_deserialize()
- sqlite3_exec()
- sqlite3_prepare_v2() and v3
- sqlite3_randomness()
- sqlite3_result_subtype()
- sqlite3_set_authorizer()
- Auto-extension APIs
- Session and Changeset APIs
- Hook APIs
- WASM-Specific C-style Functions
- sqlite3_column_js()
- sqlite3_js_aggregate_context()
- sqlite3_js_db_export()
- sqlite3_js_db_uses_vfs()
- sqlite3_js_db_vfs()
- sqlite3_js_kvvfs_...()
- sqlite3_js_posix_create_file()
- sqlite3_js_rc_str()
- sqlite3_js_sql_to_string()
sqlite3_js_vfs_create_file()- sqlite3_js_vfs_list()
- sqlite3_result_error_js()
- sqlite3_result_js()
- sqlite3_value_to_js()
- sqlite3_values_to_js()
The C-style API actually has two flavors:
- The version directly exported by WASM is a "low-level" one which
deals only in WASM-native types (i.e. numbers). It cannot, for
example, handle JS-native strings as arguments, nor can it return
them. These are "direct" exports of C functions, and function
exactly as documented in the main C API docs. It is
not expected that most clients will ever need to use this, so these
docs do not cover them except to mention that they are accessible
via the
sqlite3.wasm.exports
object. - An ever-so-slightly higher-level binding lives in the
sqlite3.capi
namespace. The primary difference from the lower-level one is that it is configured to perform limited data type conversions on its arguments and result types, as documented below.
In both cases, the canonical C API documentation applies, with the exception that some APIs in the latter category have extended semantics in JavaScript, as covered throughout this document.
It is not expected that most JS clients will want or need to deal with most of these APIs because doing so can, for some commonly-used features, require careful attention to detail with regards to passing certain data between JS and WASM (notably pointer-to-pointer "output arguments" in the C APIs).
Instead, it is expected that clients will primarily use the
oo1 or Worker 1 APIs, possibly
falling back to the C-style APIs for innocuous routines like
sqlite3_libversion()
(noting that the C-style API is not available
to clients who "remote-control" database connections via Worker
messages).
The C-style API, for the most part, functions like its C counterpart. Most of the APIs behave identically to their native C variants and their JS/WASM bindings are not explicitly documented because the C documentation already serves that purpose. Exceptions exist, however, where differences in JS-style and C-style argument handling necessitate slightly different semantics which warrant explicit documention. Such cases are documented below.
Symbolic Constants (SQLITE_...
)
The sqlite3 API makes heavy use of symbolic constants for function
result codes and flags-style function arguments. All such symbols
which are potentially required by WASM-bound C functions are defined
in the sqlite3.capi
namespace object. For example,
sqlite3.capi.SQLITE_ERROR
. The entire list of C-side constants
is at:
noting that only those relevant to WASM-bound APIs are made available to JS.
The JS API extends that list with:
SQLITE_WASM_DEALLOC
is a pointer to a WASM-bound dealloctor intended for use in scenarios whereSQLITE_TRANSIENT
orSQLITE_STATIC
might otherwise be used. It is guaranteed to refer to the same underlying function aswasm.dealloc()
but is guaranteed to be a WASM function pointer (that is, an index into the WASM indirection function table), whereaswasm.dealloc()
is permitted to be either an exported-from-WASM function or a JS wrapper around that function.
For result code constants, the function sqlite3_js_rc_str()
accepts
an integer argument and returns the JS string form of its
corresponding symbolic name, or returns undefined
if no match is
found.
Even though the SQLITE_...
constant values are exceedingly unlikely
to ever change, due to backwards compatibility constraints, JS code
should avoid using any such numeric values directly in code. The
symbolic names should always be preferred.
JavaScript Exceptions
With only a single exception (as it were) the C-level APIs never
throw, but some of the higher-level C-style APIs do and the
object-oriented APIs use exceptions exclusively to report errors. The
one exception is sqlite3.wasm.alloc()
, which will throw an
sqlite3.WasmAllocError
if it cannot allocate memory (which can
normally be considered a fatal error).
Note that there's a distinction between "C-level" and "C-level-adjacent." The C-level API is specifically the public sqlite3 API functions which are exported directly from WASM to JavaScript. Some of the utility code intended to work with the C-level API does indeed throw, but it does so in ways which will, when properly used, never allow an exception to propagate back through the JS/WASM boundary, as doing so would be disastrous to the C-level code.
SQLite3Error
An Error subclass specifically for reporting DB-level errors and enabling clients to unambiguously identify such exceptions. Its constructor behaves differently depending on its arguments:
If it's passed only a single integer argument, it is assumed to be an sqlite3 C API result code. The message becomes the result of
sqlite3.capi.sqlite3_js_rc_str()
or (if that returns falsy) a synthesized string which contains that integer.If passed 2 arguments and the 2nd is an object, it behaves like the
Error(string,object)
constructor except that the first argument is subject to the is-integer semantics from the previous point.Else all arguments are concatenated with a space between each one, using
args.join(' ')
, to create the error message.
Achtung: Allocators
In C it is always important that dynamically-allocated memory is freed in a manner which corresponds to how it was allocated.
By way of example, either of these two are legal:
void * m = malloc(100);
free(m);
m = sqlite3_malloc(100);
sqlite3_free(m);
but neither of these are legal:
void * m = malloc(100);
sqlite3_free(m); // NO!
m = sqlite3_malloc(100);
free(m); // NO!
Depending on how sqlite3_malloc()
and sqlite3_free()
are defined,
which may differ from one build of sqlite3 to the next, they might or
might not be simply proxies for malloc()
resp. free()
. If they
are, then the second example would work... until the definition of the
former pair changed, in which case the second example leads to
undefined behavior.
Depending on how sqlite3.js
is built, sqlite3_malloc()
might
be the module's default allocator. This project's canonical builds all
use sqlite3's allocator as the module-wide default since 2022-11-30,
and guaranty to do so in all future versions.
However, clients creating custom builds for different
WASM environments may change that, in which case any JavaScript code
written for such builds needs to be careful about how it uses
dynamically-allocated memory, to ensure that different memory
management APIs are never intermixed. That is, that calls to
malloc()
, free()
, and realloc()
must never intermixed with
sqlite3_malloc()
, sqlite3_free()
, and sqlite3_realloc()
. Mixing
them will lead to undefined results.
For a real-world example of an sqlite3 API where this distinction is
critical, see sqlite3_deserialize()
.
Argument and Result Type Conversion in the C-style API
See also: api-wasm.md#wasm-type-conversion
Many of the sqlite3.capi.sqlite3_...()
routines may perform some
type of JS-to-WASM conversion on their arguments or return
values. This section covers those.
64-bit Integers (BigInt)
In short, when built with BigInt support, the JS API transparently (or mostly so) treats C-level int64 values as JS BigInt values. There are cases where clients need to be aware that they're using BigInt values, as not all numeric operations support a mix of Number and BigInt values, e.g. bitwise operations.
See the build notes for details.
String Conversion
The JS bindings of the C APIs which live in the sqlite3.capi
namespace are configured to do automatic conversion of string
arguments to and from WASM/JS. Thus:
const v = capi.sqlite3_vfs_find("foo");
will convert "foo"
to a C-style string before calling the WASM-bound
function and will free the associated memory before returning. Similarly,
result values of C-style strings will be converted to JS:
console.log(capi.sqlite3_libversion());
Where such APIs accept C-string arguments, they may be passed either
a JS string or a WASM-side string pointer, noting that such uses
must be NUL-terminated or results are undefined. The JS/WASM
compatibility glue will treat numeric arguments to string parameters
as WASM pointers. When used that way, it is up to the caller to
ensure that they are passing valid pointers. Unlike C compilers, which
have at least a moderate degree of type safety when passing pointers
around, WASM's only notion of pointers is equivalent to a void*
in C. That is, pointers completely lack any type information,
making it easy to "shoot oneself in the foot," as the saying goes.
UTF-8 Only!
C-style strings in arguments and results are always assumed to be UTF-8 encoded and results are undefined if any WASM-bound sqlite3 API is passed, or returns, a string which has a different encoding. That differs from JS strings, which use JS's native 16-bit encoding (which is either UTF-16 or UCS-2 (see also)).
Though the sqlite3 C API has routines for working with UTF-16, this API targets only the web and UTF-8 is the encoding of the web. There are no current plans to expose the UTF-16 APIs via the JS interface.
"Flexible Strings"
Certain WASM-bound APIs, where explicitly noted, have additional string-type argument conversions colloquially known as "flexible strings." Such string arguments may be in any of these forms:
- A number is assumed to be a WASM C-string pointer and is passed on to WASM as-is.
- A JS string is converted to a WASM C-string, as are the results of...
- A byte-oriented TypedArray (Uint8Array or Int8Array) is assumed to hold UTF-8-encoded text and is converted to a string. Similarly, an ArrayBuffer value is wrapped by a Uint8Array for that purposes.
- A JS array gets converted to a string using
theArray.join('')
(i.e. concatenated as-is, with no space between each entry). Though JS supports multi-line string literals with the backtick syntax, it is frequently convenient to write out longer SQL constructs as arrays.
This support is generally reserved for arguments which expect SQL
strings, as such strings are often large and frequently come from
external sources, e.g. byte arrays loaded from local
files, over XHR requests, or using
fetch()
. Functions which take filename strings, and simlilar
"small" strings, do not use this feature.
Function Pointers
Many sqlite3 APIs take function pointers as arguments. Though such
pointers can be created and managed from JS code, it is often tedious
to do so, so most such bindings will automatically convert
Function-type values to function pointers for purposes of such APIs
(for example, sqlite3_exec()
).
Such conversions are convenient but come with some caveats:
- Converting a JS function to a function pointer requires installing a new function in the WASM environment.
- Depending on the context of the conversion, this may lead to a leak of the WASM-side binding of the function. Namely, certain conversions may be required to install the pointer in such a way that it's no longer possible to ensure that the new binding will ever be cleaned up. Repeated use of such conversions can lead to bloating of the WASM function table, and eventually to a crash.
To be clear: all such leaks do not reflect any flaw in the core sqlite3 library, but are side effects of automated conversions from JS-native types to WASM/C-level equivalents.
When passed pointers, such APIs do no conversion - they pass the pointers through as-is to the C APIs. They only "convert" JS functions to WASM by installing a WASM-visible function pointer associated with the JS function.
Functions which take one-time-use callbacks (like sqlite3_exec()
)
will install such conversions only for the duration of the call, and
will then uninstall them before returning.
Longer-lived bindings, e.g. custom SQL functions created using one of
the sqlite3_create_function()
variants
or collations installed using
sqlite3_create_collation()
, are bound
in such a way that the binding can be tracked and cleaned up when
either (A) they are replaced or uninstalled by a subsequent call to
the function which installed them or (B) the database handle is closed
using the JS binding of sqlite3_close_v2()
.
Minor caveat: such tracking only happens via the JS bindings of those functions installed in the
sqlite3.capi
namespace. Such tracking is bypassed if the lower-levelsqlite3.wasm.exports
bindings are called.
If clients want to perform their own handling of JS-to-WASM function conversion, client code needs to:
- Use
wasm.installFunction()
to create a WASM-bound function which acts as a proxy to a given JS function. This step includes assignment of a WASM-side function pointer for the function. - Pass that pointer around to the appropriate C APIs.
- If necessary, eventually pass the pointer from the first step to
wasm.uninstallFunction()
to remove it from the WASM environment. If this is not done, the function binding effectively leaks.
If that sounds tedious, that's because it is! The good news is that the provided bindings take care of that for all common cases, so low-level care-taking of such details should generally not be necessary from client code.
There are a small handful of cases where such automatic conversions cannot be cleaned up by the JS bindings because they're handled deep in the C API, far out of view of the JS bindings. The currently-known "problem cases" are:
sqlite3_set_auxdata()
optionally binds a destructor function to ansqlite3_context
object. The cleanup for that happens at a lower level than the JS API can see, so we cannot automate the cleanup of such JS-to-WASM function conversions. However, that particular case will almost always want thecapi.SQLITE_WASM_DEALLOC
pointer, which requires no automated conversions and therefore has no potential for a leak.
Struct-type Pointers
How certain C-level structs are exposed to JavaScript, and how client code can interact with and manipulate them, is covered in detail in its own document. The following sections summarize automatic type conversions which may happen for function arguments.
No automated conversions are performed on struct pointer result values. They are always returned to JS as WASM pointers.
sqlite3*
Functions which are declared as taking a sqlite3*
argument may
perform the following argument-type conversions:
- A WASM pointer is passed on as-is.
- A
oo1.DB
instance and its subclasses: itspointer
property value is used.
sqlite3_stmt*
Functions which are declared as taking a sqlite3_stmt*
argument may
perform the following argument-type conversions:
- A WASM pointer is passed on as-is.
- A
oo1.Stmt
instance: itspointer
property value is used.
sqlite3_vfs*
Functions which are declared as taking a sqlite3_vfs*
argument may
perform the following argument-type conversions:
- A WASM pointer is passed on as-is.
- A JS string: the result of
capi.sqlite3_vfs_find()
is used and it throws if that function returns 0.
Note that WASM C-strings (pointers) are not accepted because they are indistinguishable fromsqlite3_vfs*
. - A
capi.sqlite3_vfs
instance: itspointer
property value is used.
WASM APIs Which Differ from Their C Counterparts
Every effort is made to keep the WASM bindings of the C APIs working as closely to their C counterparts as is feasible for the sake of consistency and the ability to use the C-level documentation with the WASM API. Some APIs, however, benefit greatly from the addition of custom wrappers which simplify particular cases which are unduly onerous to handle at the client-code level in JS.
This section describes sqlite3.capi
member APIs which have semantics
which, depending on how they are used, may differ from their C
counterparts.
Unless specifically noted otherwise, for consistency with the C API,
all JS-customized bindings of the C APIs require the same number of
arguments as their C counterparts and will return
capi.SQLITE_MISUSE
if passed any other argument count.
In all cases, when passed arguments which are not accounted for in JS-specific customization, they pass their arguments on as-is to the underlying C APIs and behave as the C documentation says they do. When passed certain JS types, however, they may behave differently, either gaining or losing features, depending on the context.
The affected APIs are listed below.
Certain more general aspects of these APIs, such as how to deal with output pointers from JS, are detailed in the WASM utilities docs.
sqlite3_bind_blob()
C reference: www:/c3ref/bind_blob.html
sqlite3_bind_blob()
works exactly like its C counterpart unless its
3rd argument is one of:
JS string: the 3rd argument is converted to a C string, the 4th argument is ignored, and the C-string's length is used in its place.
Array: converted to a string as defined for "flexible strings" and then it's treated as a JS string.
Int8Array, Uint8Array, or ArrayBuffer:
wasm.allocFromTypedArray()
is used to convert the memory to the WASM heap. If the 4th argument is 0 or greater, it is used as-is, otherwise the array'sbyteLength
value is used. This is an exception to the C API's undefined behavior for a negative 4th argument, but results are undefined if the given 4th argument value is greater than thebyteLength
of the input array.
In all of those cases, the final argument (text destructor) is ignored
and SQLITE_WASM_DEALLOC
is assumed.
A 3rd argument of null
is treated as if it were a WASM pointer of 0.
If the 3rd argument is neither a WASM pointer nor one of the
above-described types, capi.SQLITE_MISUSE
is returned.
sqlite3_bind_text()
C reference: www:/c3ref/bind_blob.html
sqlite3_bind_text()
works exactly like its C counterpart unless its
3rd argument is one of:
JS string: the 3rd argument is converted to a C string, the 4th argument is ignored, and the C-string's length is used in its place.
Array: converted to a string as defined for "flexible strings". The 4th argument is ignored and a value of -1 is assumed.
Int8Array, Uint8Array, or ArrayBuffer: is assumed to contain UTF-8 text, is converted to a string. The 4th argument is ignored, replaced by the array's byteLength value.
In each of those cases, the final argument (text destructor) is
ignored and SQLITE_WASM_DEALLOC
is assumed.
A 3rd argument of null
is treated as if it were a WASM pointer of 0.
If the 3rd argument is neither a WASM pointer nor one of the
above-described types, capi.SQLITE_MISUSE
is returned.
If client code needs to bind partial strings, it needs to either parcel the string up before passing it in here or it must pass in a WASM pointer for the 3rd argument and a valid 4th-argument value, taking care not to pass a value which truncates a multi-byte UTF-8 character. When passing WASM-format strings, it is important that the final argument be valid or unexpected content can result, or even a crash if the application reads past the WASM heap bounds.
sqlite3_close_v2()
sqlite3_close_v2()
differs from its native counterpart only in that
it attempts to perform certain JS-binding-related cleanup before it
calls the native implementation. In short, it makes an effort to clean
up any WASM function table entries which were automatatically
installed on behalf of the being-closed database
handle.
The following db-bound bindings are cleaned up by sqlite3_close_v2()
:
sqlite3_busy_handler()
sqlite3_commit_hook()
sqlite3_create_collation()
variantssqlite3_create_function()
variantssqlite3_preupdate_hook()
sqlite3_progress_handler()
sqlite3_rollback_hook()
sqlite3_set_authorizer()
sqlite3_trace_v2()
sqlite3_update_hook()
For details about why these cleanups are useful, see the section on automated function pointer conversions.
sqlite3_config()
The JS binding of sqlite3_config()
wraps
only a small subset of configuration operations, eliding any which
either do not make sense for this environment or are considered too
low-level for this environment. Only the call forms listed below are
are accepted. Any other config options will return
capi.SQLITE_NOTFOUND
. Passing in fewer than 2 arguments will
trigger a return of capi.SQLITE_MISUSE
.
Significant usage caveat: sqlite3_config()
cannot be legally
called after the library has been "started," returning SQLITE_MISUSE
if it is. Initialization of the JS bindings necessarily requires
using the library in such a way that makes later calls to
sqlite3_config()
illegal. Clients can use sqlite3_shutdown()
to
"uninitialize" the library in order to make use of sqlite3_config()
legal again, but doing so may cause certain JS API features to
disappear, such as JS-registered VFSes.
sqlite3_config(X, int)
:
capi.SQLITE_CONFIG_COVERING_INDEX_SCAN
capi.SQLITE_CONFIG_MEMSTATUS
capi.SQLITE_CONFIG_SMALL_MALLOC
capi.SQLITE_CONFIG_SORTERREF_SIZE
capi.SQLITE_CONFIG_STMTJRNL_SPILL
capi.SQLITE_CONFIG_URI
sqlite3_config(X, int, int)
:
capi.SQLITE_CONFIG_LOOKASIDE
sqlite3_config(X, int64)
:
capi.SQLITE_CONFIG_MEMDB_MAXSIZE
Noting that the latter requires BigInt support.
sqlite3_create_collation()
and friends
C reference: www:/c3ref/create_collation.html
sqlite3_create_collation()
and sqlite3_create_collation_v2()
work exactly like their C-side equivalents except that:
They return
capi.SQLITE_FORMAT
if the 3rd argument contains any encoding-related value other thancapi.SQLITE_UTF8
. No other encodings are supported. As a special case, if the bottom 4 bits of that argument are 0,SQLITE_UTF8
is assumed.They accept JS functions for their function-pointer arguments, for which they will install WASM-bound proxies. The proxies are uninstalled automatically if a subsequent call to this function replaces them (either with NULL or a different function) or when containing database is closed.
Returns 0 on success, non-0 on error, in which case the error
state of its sqlite3*
argument may contain more information.
sqlite3_create_function()
and friends
C reference: www:/c3ref/create_function.html
The argument names used below refer directly to the argument names from the native C documentation:
int sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
int sqlite3_create_function_v2(
sqlite3 *db,
const char *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*)
);
int sqlite3_create_window_function(
sqlite3 *db,
const char *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*)
);
sqlite3_create_function()
, sqlite3_create_function_v2()
,
and sqlite3_create_window_function()
differ from their native
counterpart only in the following ways:
The fourth argument (
eTextRep
) argument must not specify any encoding other thansqlite3.capi.SQLITE_UTF8
. The JS API does not currently support any other encoding and likely never will. If any other encoding flag is provided,sqlite3.capi.SQLITE_FORMAT
is returned. To simplify usage, any falsy value is interpreted asSQLITE_UTF8
. Seesqlite3_result_subtype()
for an important caveat regarding theSQLITE_RESULT_SUBTYPE
flag.Any of the function pointer arguments may be either WASM pointers (assumed to be function pointers) or JS Functions. In the latter case, each gets bound to WASM using
sqlite3.wasm.installFunction()
and that wrapper is passed on to the native implementation.
The semantics of generated JS wrappers are:
xFunc()
: passed(pCtx, ...values)
. Its return value becomes the new SQL function's result.xStep()
andxInverse()
(window functions): passed(pCtx, ...values)
. The return value is ignored.xFinal()
: is passed(pCtx)
. Its return value becomes the new aggregate SQL function's result.xDestroy()
: is passed(void*)
. Its return value is ignored. The pointer passed to it is the one from the 5th argument tosqlite3_create_function_v2()
orsqlite3_create_window_function()
.
Note that:
pCtx
in the above descriptions is asqlite3_context*
. The overwhelming majority of the time, that initial argument will be irrelevant for JS UDF bindings, but it needs to be there so that the uses case where it is relevant, in particular with window and aggregate functions, have full access to the lower-level sqlite3 APIs.When wrapping JS functions, the remaining arguments are passed to them as positional arguments, not as an array of arguments, because that allows callback definitions to be more JS-idiomatic than C-like. For example:
(pCtx,a,b)=>a+b
is more intuitive and legible than(pCtx,args)=>args[0]+args[1]
For cases where an array of arguments would be more convenient, the callbacks simply need to be declared like(pCtx,...args)=>{...}
in which caseargs
will be an array.If a JS wrapper throws, it gets translated to
sqlite3_result_error()
orsqlite3_result_error_nomem()
, depending on whether the exception is ansqlite3.WasmAllocError
object or not.When passing on WASM function pointers, arguments are not converted or reformulated. They are passed on as-is in raw pointer form using their native C signatures. Only JS functions passed in to this routine, and thus wrapped by this routine, get automatic conversions of arguments and result values.
- The routines which perform those conversions are exposed for
client-side use as:
sqlite3_values_to_js()
sqlite3_result_js()
sqlite3_result_error_js()
- The routines which perform those conversions are exposed for
client-side use as:
For xFunc()
, xStep()
, xInverse()
, and xFinal()
:
- When called from SQL, arguments to the UDF, and its result, will be converted between JS and SQL with as much fidelity as is feasible, triggering an exception if a type conversion cannot be determined. Some freedom is afforded to numeric conversions due to friction between the JS and C worlds: integers which are larger than 32 bits may be treated as doubles or BigInts.
If any JS-side bound functions throw, those exceptions are
intercepted and converted to database-side errors with the
exception of xDestroy()
: any exception from it is ignored,
possibly generating a console.error()
message. Destructors
must not throw.
Once installed, there is currently no way to uninstall the
automatically-converted WASM-bound JS functions from WASM. They can be
uninstalled from the database as documented in the C API, but this
wrapper currently has no infrastructure in place to also free the
WASM-bound JS wrappers, effectively resulting in a memory leak if the
client uninstalls the UDF. Removing client-installed UDFs is rare in
practice. If this factor is relevant for a given client, they can
create WASM-bound JS functions themselves, hold on to their pointers,
and pass the pointers in to here. Later on, they can free those
pointers (using wasm.uninstallFunction()
or equivalent).
Clients who wish more control over their bindings can create their own
WASM-bound JS functions using sqlite3.wasm.installFunction()
.
The helper methods described in the following subsections can assist
with that and are exposed as properties of all 3 of the
create-function functions to assist such implementations.
pCtx
argument to the JS-bound wrappers
was a painful decision but it boiled down to API consistency. By and
large, that argument is irrelevant for JS bindings, so is just noise
for most client-side UDFs. If it were elided, however, more advanced
uses of UDFs would be much more painful to write, forcing the users
to write their own WASM-bound wrappers to get at that
argument. Including it in the JS callback interface ensures that the
interface is more consistent with the C callback interface (sans the
way SQL-side arguments are provided to them) and enables Power User
use cases to be developed. It is expected, however, that folks will
often forget to add it, which will cause their UDF argument lists to
be "off by one." It is hoped that having to add that seemingly
extraneous argument to client-side UDF signatures will soon seem
like second nature to folks writing UDFs, in the same way that
Python programmers have to add an explicit self
argument to their
object-oriented methods (whereas C++, JavaScript, and most other
languages make that argument implicit).
udfConvertArgs()
udfConvertArgs()
This function is a deprecated alias for
sqlite3_values_to_js()
and predates
that function's addition to the API.
udfSetError()
udfSetError()
This function is a deprecated alias for
sqlite3_result_error_js()
and
predates that function's addition to the API.
udfSetResult()
udfSetResult()
This function is a deprecated alias for
sqlite3_result_js()
and predates
that function's addition to the API.
sqlite3_db_config()
sqlite3_db_config()
differs from its C counterpart only in a small
technicality: the C function is variadic, and such functions cannot be
bound directly to WASM, but the hand-written JS-side wrapper for it
supports all of the C APIs combinations of arguments, as
documented at at www:/c3ref/c_dbconfig_defensive.html.
sqlite3_deserialize()
C reference: www:/c3ref/deserialize.html
sqlite3_deserialize()
does not materially differ from its C-side
counterpart but does have subtle caveats regarding memory allocation.
The documentation regarding allocators covers this
issue in more abstract terms, but sqlite3_deserialize()
provides a
concrete example of a case where it is critical that one be aware the
definition of the environment's C-level memory allocator.
Depending on how sqlite3_deserialize()
is used, the memory passed to
it may be required to come from sqlite3_malloc()
,
sqlite3_realloc()
, or their 64-bit counterparts.
The sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE
flag can be passed to
this function to enable automatic growth of the new in-memory
databases on demand but the memory passed to
sqlite3_deserialize()
in that case must come from
sqlite3_malloc()
or sqlite3_realloc()
(or their 64-bit
counterparts) or else results are undefined.
For example, let's consider this snippet which downloads a remote database and deserializes it:
// Do not copy/paste without reading the docs below!
const db = new sqlite3.oo1.DB();
await fetch('my.db')
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
const bytes = new Uint8Array(arrayBuffer);
const p = sqlite3.wasm.allocFromTypedArray(bytes);
db.onclose = {after: function(){sqlite3.wasm.dealloc(p)}};
const rc = sqlite3.capi.sqlite3_deserialize(
db.pointer, 'main', p, bytes.length, bytes.length,
0
);
db.checkRc(rc);
});
That use of sqlite3_deserialize()
is legal, but only because it
defines a fixed-sized memory region of memory not managed by
sqlite3. In this scenario, sqlite3 is a read-only user of memory owned
by the client application.
If the SQLITE_DESERIALIZE_FREEONCLOSE
and/or
SQLITE_DESERIALIZE_RESIZEABLE
flags were used in the final argument
to the deserialize call above, the result would, abstractly
speaking, be undefined behavior (but see below for why it may not
be).
Abstractly speaking, sqlite3.wasm.allocFromTypedArray()
uses the
system-level allocator, and it is not semantically legal to pass
memory alloced from sqlite3.wasm.alloc()
(i.e. from C's malloc()
)
to sqlite3_free()
or sqlite3_realloc()
. In order to support the
above-mentioned flags in the example above, the call to
allocFromTypedArray()
would need to be replaced by an equivalent
function which allocates the memory using
sqlite3_alloc()
. However, as of 2022-11-30, this project's
canonical builds use the sqlite3_malloc()
family of functions as the
module-wide allocator, meaning that this is a non-issue in canonical
builds but might be an issue in custom builds, depending on how
they're constructed.
sqlite3_exec()
C reference: www:/c3ref/exec.html
sqlite3_exec()
, if called with a non-Function object as its 3rd
argument:
sqlite3_exec(myDbPtr, "drop table x", 0, 0, 0);
works exactly like all other WASM-bound functions, including the automatic conversion of its 2nd argument (SQL), which supports flexible string conversion.
If, however, it is called with a JS function as its 3rd argument then it performs the following translations...
For the duration of the sqlite3_exec()
call, it installs a WASM-side
function which hooks the provided callback into WASM. That binding is
removed immediately before sqlite3_exec()
returns.
The callback's C signature is:
callback(void *, int colCount, char** pColValues, char** pColNames)
but the callback's WASM-bound proxy calls it like:
callback(array colValues, array colNames)
i.e. it converts the C-style string arrays to JS arrays of strings.
The initial void pointer argument is elided because a JS closure can
bind such state into the callback, if needed, and the column count is
available via the length
property of the two array arguments.
If the callback throws or returns any non-0 value, the proxy catches
that and converts it to a C result, which the native sqlite3_exec()
implementation will translate to a SQLITE_ABORT
result. If it does
not throw, its return value is coerced to be a 32-bit integer. Thus an
implicit return (the undefined
value) equates to a result code of 0
(i.e. success).
Example:
const db = new sqlite3.oo1.DB().exec(
"create table t(a); insert into t(a) values(3),(6),(9)"
);
sqlite3.capi.sqlite3_exec(
db, // resolves to db.pointer, the underlying (sqlite3*)
"select a from t",
(vals,names)=>{
console.log(names[0],vals[0]);
},
0, 0
);
Will output:
a 3
a 6
a 9
Note that sqlite3_exec()
, for consistency with the C API, requires
all 5 arguments, though the final two are almost always 0.
If a specific use case genuinely needs the C-style signature for the
callback, that can be achieved by manually installing the callback
into WASM (using the signature string "i(pipp)"
)
and then passing its pointer to sqlite3_exec()
, as demonstrated
here:
const pCb = wasm.installFunction('i(pipp)', function(pVoid,nCols,aVals,aCols){
// wasm.cArgvToJs() can be used to convert aVals and aCols to arrays:
const vals = wasm.cArgvToJs(nCols, aVals);
// Noting that the aCols list is constant across each sqlite3_exec()
// invocation and can be cached _if_ this function will only ever
// be used with a single specific query.
// Alternately, individual name and value columns can be converted
// to JS strings like:
const strAt = (ndx)=>{
return ndx<nCols
? wasm.cstrToJs(wasm.peekPtr(aVals + (ndx * wasm.ptrSizeof)))
: undefined;
};
const val0 = strAt(0), val1 = strAt(1), val2 = strAt(2);
// To coerce them to numbers, simply prefix the JS strings with a plus
// sign, e.g. +strAt(...).
return 0;
});
try {
let rc = capi.sqlite3_exec(db, "select a, a*2 from foo", pCb, 0, 0);
...
}finally{
// If the callback will be used repeated, skip this part:
wasm.uninstallFunction(pCb);
}
sqlite3_prepare_v2()
and sqlite3_prepare_v3()
C reference: www:/c3ref/prepare.html
Like in the C API, sqlite3_prepare_v2()
is simply a proxy for sqlite3_prepare_v3()
which passes on a default set of flags to that function. sqlite3_prepare_v3()
,
due to disparities between JS and C, has two distinctly different usages
As a point of reference, the native signatures of these functions are:
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
int sqlite3_prepare_v3(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
The sqlite3_prepare_v3()
binding handles two different uses
with differing JS/WASM semantics:
For the cases that the SQL argument is a JS string:
int sqlite3_prepare_v3(pDb, sqlString, -1, prepFlags, ppStmt , null)
The SQL length argument (the 3rd argument) must always be negative because it must be a byte length and that value is expensive to calculate from JS (where only the character length of strings is readily available). It is retained in this API's interface for code/documentation compatibility reasons but is currently always ignored except as noted below.For the case that the SQL argument is a WASM pointer to a C-string.
int sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)
The 3rd argument is used as-is but it is still critical that the C-style input string (2nd argument) be terminated with a 0 byte.
In usage (1), if the second the 2nd argument must be a flexible
string other than a WASM pointer. If it is,
sqlite3_prepare_v3()
assumes case (1) and calls the underyling C
function with the equivalent of:
(pDb, sqlAsString, -1, prepFlags, ppStmt, null)
The final argument, pzTail
, is ignored in this case because its result is
meaningless when a string-type value is passed through: the
string goes through another level of internal conversion for WASM's
sake and the result pointer would refer to that transient conversion's
memory, not the passed-in string.
If the SQL is a Uint8Array or Int8Array then it is assumed to hold a
UTF-8 string, is converted to a C-string, and the byte array's length
is used as the sqlByteLen
argument.
If the SQL argument is not a string or one of the above-mentioned
array types, it must be a pointer to a NUL-terminated string which
was allocated in WASM memory (e.g. using wasm.alloc()
, from the
C stack, or equivalent). In that case, the final argument may be
0/null
/undefined
or must be a pointer to which the "tail" of the
compiled SQL is written, as documented for the C-side
sqlite3_prepare_v3()
. In case (2), the underlying C function is
called with the equivalent of:
(pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)
It returns its result and compiled statement as documented in the C API.
Fetching the output pointers (5th and 6th parameters) requires
using wasm.peek()
(or equivalent - see
below) and the pzTail
will point to an address
relative to the sqlAsPointer
value.
If passed an invalid 2nd argument type, this function will return
SQLITE_MISUSE
and capi.sqlite3_errmsg()
will contain a string
describing the problem.
Side-note: if given an empty string, or one which contains only
comments or an empty SQL expression, 0 is returned but the result
output pointer will be NULL
.
sqlite3_randomness()
C reference: www:/c3ref/randomness.html
Usages:
void sqlite3_randomness(int n, int outputPtr)
TypedArray sqlite3_randomness(typedArray)
If passed a single argument which appears to be a byte-oriented
TypedArray (Int8Array or Uint8Array), this function treats that
TypedArray as an output target, fetches theArray.byteLength
bytes of
randomness, and populates the whole array with it. As a special case,
if the array's length is 0, this function behaves as if it were passed
(0,0). When called this way, it returns its argument, else it returns
the undefined
value.
If called with any other arguments, they are passed on as-is to the C API. Results are undefined if passed any incompatible values.
sqlite3_result_subtype()
C reference: www:/c3ref/result_subtype.html
This function does not materialy differ from its C counterpart but comes with a small caveat:
The canonical WASM build includes the SQLITE_STRICT_SUBTYPE
compile-time flag, which means that
any user-defined functions which meet any
of the following conditions must include the SQLITE_RESULT_SUBTYPE
flag when defining them via sqlite3_create_function()
and
friends:
- They explicitly call
sqlite3_result_subtype()
or - Versions 3.45.x, 3.44.1, and 3.44.2 only: they call
sqlite3_result_value()
(or a proxy for it) to pass one of the function's own arguments back as the result, in which case they may indirectly return result subtype information. (This case is handled implicitly as of 3.46 because it's normally not practical for UDFs to always know for certain whether they will pass on a subtype-using value.)
See the C API docs for the full details.
sqlite3_set_authorizer()
C reference: www:/c3ref/set_authorizer.html
sqlite3_set_authorizer()
works just like in the C API unless it is
passed a JS function as its second argument, in which case it installs
a proxy which will convert the C-string (pointer) arguments to JS strings
before passing them on to the client-provided function. That is, the C-native
call has this signature:
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*)
And this function wraps that up in a JS call in this form:
int func(void*, int, string, string, string, string)
If the JS function returns a falsy value (e.g. via an implicit return
of the undefined
value), it is coerced to integer 0. If the JS
function throws, it is caught and translated to a db-level error.
If passed a non-function second argument, e.g. a WASM pointer or
null
, it is passed on as-is to the underlying binding. Clients who
want to receive C-style string arguments in their JS authorizer
callback can install their callback using wasm.installFunction()
and
pass the function pointer returned from that function into this one,
in which case no additional layer of
type-conversion/exception-handling proxy is installed. In such cases
it is important that such proxies not throw/propagate exceptions,
noting that any failed memory allocation may trigger an
sqlite3.WasmAllocError
.
Auto-extension APIs
C reference: www:/c3ref/auto_extension.html
The auto-extension API behaves mostly like its C counterpart, with only the following minor differences:
sqlite3_auto_extension()
accepts a JS function, converts it to a WASM function, and records that conversion so that any later call tosqlite3_reset_auto_extension()
can uninstall it. If passed no arguments, or a non-function/non-pointer argument, it returnscapi.SQLITE_MISUSE
. If passed a pointer, instead of a JS function, it does not record that pointer for later deinstallation.sqlite3_reset_auto_extension()
calls the underlying C implementation and uninstalls any WASM functions created bysqlite3_auto_extension()
.sqlite3_cancel_auto_extension()
requires a function pointer, just like the C API. It does not accept a JS function because the converted pointer of such a function could never possibly match an installed auto-extension handler. If passed no arguments, or a non-function/non-pointer argument, it returns 0.
These differences, for practical purposes, mean the following:
- If you will only ever install, and never uninstall, and auto-extension handler, it is sensible to rely on the automatic conversion of JS functions to WASM functions.
- If, on the other hand, you want to add and remove auto-extension
handlers, instead use
wasm.installFunction()
with a function signature string of"i(ppp)"
to create the WASM function pointer, then pass it tosqlite3_auto_extension()
andsqlite3_cancel_auto_extension()
.
Session and Changeset APIs
The session API bindings differ from their C counterparts only in that:
- They optionally accept JS functions for their function-pointer arguments. They will automatically convert JS-function-type arguments to function pointers, as described elsewhere in this document.
sqlite3session_delete()
will clean up any auto-installed function pointers added viasqlite3session_table_filter()
.
Most of the function-pointer argument types take only WASM-compatible values which are passed on as-is to the JS function. However, any with the following native signature undergo argument conversion before calling the provided JS function:
int (*)(void *, const char *)
That applies to xFilter
callback argument of the following
functions:
sqlite3changeset_apply()
sqlite3changeset_apply_strm()
sqlite3changeset_apply_v2()
sqlite3changeset_apply_v2_strm()
sqlite3session_table_filter()
The only argument conversion which happens there is that the 2nd
argument is converted to a JS string before passing it to the JS
function. If, for some unsual case, the client code instead requires
the C-string pointers, than can be achieved by manually installing
the callback function and then passing its pointer
(provided by the installation process) to the sqlite3 API instead of
passing a JS function. That inhibits any automatic conversion. For
the installation, use the signature string "i(ps)"
.
The JS-installed proxies are installed only for the duration of the
call except for sqlite3session_table_filter()
, which is installed
associated with the sqlite3_session
object passed to that function.
sqlite3session_delete()
will clean up any such proxies installed
by sqlite3session_table_filter()
.
Session API Extensions
mixed sqlite3changeset_new_js(pChangesetIter, iCol)
mixed sqlite3changeset_old_js(pChangesetIter, iCol)
These are thin wrappers around sqlite3changeset_new()
and
sqlite3changeset_old()
, respectively, which fetch the
sqlite3_value*
from the column specified by the 2nd argument and
then return the result of passing it to
sqlite3_value_to_js()
. Both of these
functions throw on error, including when the underlying functions
return non-0. If sqlite3changeset_new()
returns 0 but sets the
output value to NULL, this function returns the undefined
value,
which is never a valid conversion from an sqlite3_value
, so is
unambiguous.
Hook APIs
C references:
The sqlite3_commit_hook()
, sqlite3_rollback_hook()
,
sqlite3_update_hook()
functions, and the sqlite3_preupdate_hook()
family of functions, do not fundmantally differ from their C
counterparts, but sqlite3_update_hook()
and
sqlite3_preupdate_hook()
take part in automatic JS-to-WASM function
conversion and such conversions are subject to
cleanup in sqlite3_close_v2()
. Note that sqlite3_update_hook()
and
sqlite3_preupdate_hook()
requires BigInt support.
If sqlite3_update_hook()
or sqlite3_preupdate_hook()
are passed a
JS function, it undergoes argument conversion for the two C-string
arguments. That is, the native signature of those callback are:
// sqlite3_update_hook() callback:
void (*)(void *, int, char const *, char const *, sqlite3_int64)
// sqlite3_preupdate_hook() callback:
void (*)(void *, sqlite3*, int, char const *, char const *, sqlite3_int64, sqlite3_int64)
and the JS signatures are:
// sqlite3_update_hook() callback:
void (void *, int, string, string, BigInt)
// sqlite3_preupdate_hook() callback:
void (void *, sqlite3*, int, string, string, BigInt, BigInt)
The hook callbacks must not propagate any exceptions. They are not caught automatically by this layer because there is no way to report an error via sqlite3 from the rollback and (pre)update hooks.
Pre-update Hook Extensions
mixed sqlite3_preupdate_new_js(pDb, iCol)
mixed sqlite3_preupdate_old_js(pDb, iCol)
These are thin wrappers around sqlite3_preupdate_new()
and
sqlite3_preupdate_old()
, respectively, which fetch the
sqlite3_value*
from the column specified by the 2nd argument and
then return the result of passing it to
sqlite3_value_to_js()
. Both of these
functions throw on error, including when the underlying functions
return non-0.
WASM-Specific C-style Functions
This section documents C-style functions which live in the
sqlite3.capi
namespace but are specific to the WASM/JS APIs. Note
that the sqlite3.wasm
API has some C-like functions which are
not documented here because they are not part of the public API and
are not intended for use outside of this project's own code.
sqlite3_column_js()
mixed sqlite3_column_js(pStmt, iCol [,throwIfCannotConvert=true])
Returns the result of passing the result of
sqlite3_column_value(pStmt,iCol)
to
sqlite3_value_to_js()
. The 3rd argument of
this function is ignored by this function except to pass it on as the
second argument of sqlite3_value_to_js()
. If the
sqlite3_column_value()
returns NULL (e.g. because the column index
is out of range), this function returns undefined
, regardless of the
3rd argument. If the 3rd argument is falsy and conversion fails,
undefined
will be returned.
sqlite3_js_aggregate_context()
pointer sqlite3_js_aggregate_context(pCtx, n)
A thin wrapper around sqlite3.capi.sqlite3_aggregate_context()
which
behaves the same except that if that function returns 0 and n
is truthy,
it throws a WasmAllocError
. If n
is falsy, it simply returns 0 if
that function returns 0. That behavior is intended to assist in developing
xFinal()
implementations.
Example, using the OO1 API:
const capi = sqlite3.capi,
wasm = sqlite3.wasm,
sjac = capi.sqlite3_js_aggregate_context;
db.createFunction({
name: 'summer',
xStep: (pCtx, n)=>{
const ac = sjac(pCtx, 4);
wasm.poke32(ac, wasm.peek32(ac) + Number(n));
},
xFinal: (pCtx)=>{
const ac = sjac(pCtx, 0);
return ac ? wasm.peek32(ac) : 0;
}
});
When a given aggregate is run multiple times in one SQL statement, the
aggregate context pointer will (in contrast to the pCtx
pointer)
remain stable across calls, enabling users to keep the state of each
call separate from each other. For example, if it's called twice in
one statement, one set of calls to the aggregate will have an
aggregate context of X and the other will have an aggregate context of
Y. That pointer can be used as a key in a client-side lookup table in
order to map arbitrarily complex data to the aggregate, but the client
must be sure to remove the mapping in their xFinal()
implementation.
sqlite3_js_db_export()
Uint8Array sqlite3_js_db_export(pDb [, schema=0])
A convenience wrapper around
sqlite3_serialize() which serializes the
given sqlite3*
pointer or sqlite3.oo1.DB
instance to a Uint8Array.
On success it returns a Uint8Array. If the schema is empty, an empty array is returned.
schema
is the schema to serialize. It may be a WASM C-string pointer
or a JS string. If it is falsy, it defaults to "main"
.
On error it throws with a description of the problem.
Note that this operation is restricted by the library's build-time
max-single-allocation limit (SQLITE_MAX_ALLOCATION_SIZE
) and cannot
export databases larger than approximately that size. Prior to
version 3.44 that was approximately 536mb. As of 3.44 the core
library's default limit of 2gb is used.
sqlite3_js_db_uses_vfs()
boolean sqlite3_js_db_uses_vfs(pDb, vfsName, dbName)
Given an sqlite3*
, an sqlite3_vfs
name, and an optional db name
(defaults to "main"
), returns a truthy value (see below) if that db
handle uses that VFS, else returns false. If pDb
is falsy then the
3rd argument is ignored and this function returns a truthy value if
the default VFS name matches that of the 2nd argument. Results are
undefined if pDb
is truthy but refers to an invalid pointer. The 3rd
argument specifies the database name of the given database connection
to check, defaulting to the main db.
The 2nd and 3rd arguments may either be a JS string or a WASM C-string. If the 2nd argument is a NULL WASM pointer, the default VFS is assumed.
The truthy value it returns is a pointer to the sqlite3_vfs
object.
To permit safe use of this function from APIs which may be called via the C stack (like SQL UDFs), this function does not throw: if bad arguments cause a conversion error when passing into wasm-space, false is returned.
sqlite3_js_db_vfs()
pointer sqlite3_js_db_vfs(dbPointer, dbName=0)
Given a sqlite3*
and a database name (JS string or WASM
C-string pointer, which may be 0), returns a pointer to the
sqlite3_vfs responsible for it. If the given db name is null/0,
or not provided, then "main"
is assumed.
sqlite3_js_kvvfs_...()
See the KVVFS docs for details of the KVVFS-specific functions.
sqlite3_js_db_uses_vfs()
boolean sqlite3_js_db_uses_vfs(pDb,vfsName,dbName=0)
Given an sqlite3*
, an sqlite3_vfs name, and an optional db name
(defaulting to "main"), returns a truthy value (see below) if that db
uses that VFS, else returns false. If pDb is falsy then the 3rd
argument is ignored and this function returns a truthy value if the
default VFS name matches that of the 2nd argument. Results are
undefined if pDb is truthy but refers to an invalid pointer. The 3rd
argument specifies the database name of the given database connection
to check, defaulting to the main db.
The 2nd and 3rd arguments may either be a JS string or a WASM C-string. If the 2nd argument is a NULL WASM pointer, the default VFS is assumed. If the 3rd is a NULL WASM pointer, "main" is assumed.
The truthy value it returns is a pointer to the sqlite3_vfs
object.
To permit safe use of this function from APIs which may be called via the C stack (like SQL UDFs), this function does not throw: if bad arguments cause a conversion error when passing into wasm-space, false is returned.
sqlite3_js_posix_create_file()
(Added in version 3.43 as an alternative to the deprecated
sqlite3_js_vfs_create_file().)
int sqlite3_js_posix_create_file(fiename, data[, dataLen = data.byteLength])
If the current environment supports the POSIX file APIs, this routine creates (or overwrites) the given file using those APIs. This is primarily intended for use in Emscripten-based builds where the POSIX APIs are transparently proxied by an in-memory virtual filesystem. It may behave differently in other environments.
The first argument must be either a JS string or WASM C-string holding the filename. Note that this routine does not create intermediary directories if the filename has a directory part.
The 2nd argument may either a valid WASM memory pointer, an ArrayBuffer, or a Uint8Array. The 3rd must be the length, in bytes, of the data array to copy. If the 2nd argument is an ArrayBuffer or Uint8Array and the 3rd is not a positive integer then the 3rd defaults to the array's byteLength value.
Results are undefined if data is a WASM pointer and dataLen is exceeds data's bounds.
Throws if any arguments are invalid or if creating or writing to the file fails.
sqlite3_js_rc_str()
string sqlite3_js_rc_str(int)
Given one of the SQLITE_...
constant values, this function returns
the string form of that constant, or undefined
if no match is found,
noting that some constants available in the C API are not exported to
WASM because they simply are not used there. Example:
sqlite3_js_rc_str(sqlite3.capi.SQLITE_ERROR); // ==> "SQLITE_ERROR"
sqlite3_js_sql_to_string()
Added in 3.44.
string sqlite3_js_sql_to_string(v)
Converts SQL input from a variety of convenient formats to plain strings.
If v is a string, it is returned as-is. If it is-a Array, its
join("")
result is returned. If is is a Uint8Array, Int8Array,
or ArrayBuffer, it is assumed to hold UTF-8-encoded text and is
decoded to a string. If it looks like a WASM pointer,
wasm.cstrToJs(v)
is returned. Else undefined
is returned.
sqlite3_js_vfs_create_file()
sqlite3_js_vfs_create_file()
Alternative options:
"unix" VFS and its variants can get equivalent functionality with
sqlite3_js_posix_create_file()
.OPFS: use either
sqlite3.oo1.OpfsDb.importDb()
, for the "opfs" VFS, or theimportDb()
method of the PoolUtil object provided by the "opfs-sahpool" VFS (noting that its VFS name may differ depending on client-side configuration). We cannot proxy those from here because they are necessarily asynchronous.
Usages:
void sqlite3_js_vfs_create_file(vfs, filename, dataPointer, dataLen)
void sqlite3_js_vfs_create_file(vfs, filename, Uint8Array|ArrayBuffer data [, dataLen=data.byteLength])
Creates (or overwrites) a file using the storage appropriate for the
given sqlite3_vfs
. The first argument may be a VFS name (JS string
only, NOT a WASM C-string), WASM-managed sqlite3_vfs*
, or a
capi.sqlite3_vfs
instance. Pass 0 (a NULL pointer) to use the
default VFS. If passed a string which does not resolve using
sqlite3_vfs_find()
, an exception is thrown. (Note that a WASM
C-string is not accepted because it is impossible to distinguish from
a C-level sqlite3_vfs*
.)
The second argument, the filename, must be a JS or WASM C-string.
The 3rd may either be falsy, a valid WASM memory pointer, an ArrayBuffer, or Uint8Array. The 4th must be the length, in bytes, of the data array to copy. If the 3rd argument is a Uint8Array or ArrayBuffer and the 4th is not a positive integer then the 4th defaults to the array's byteLength value.
If data is falsy then a file is created with dataLen bytes filled with
uninitialized data (whatever truncate()
leaves there). If data is
not falsy then a file is created or truncated and it is filled with
the first dataLen bytes of the data source.
Throws if any arguments are invalid or if creating or writing to the file fails.
Note that most VFSes do not automatically create directory parts of filenames, nor do all VFSes have a concept of directories. If the given filename is not valid for the given VFS, an exception will be thrown. This function exists primarily to assist in implementing file-upload capability, with the caveat that clients must have some idea of the VFS into which they want to upload and that VFS must support the operation.
VFS-specific notes:
- "memdb": results are undefined.
- "kvvfs": does not work with this function.
- "unix" and its variants: will use the WASM build's equivalent of the POSIX I/O APIs. For Emscripten-based builds this is a virtual in-memory filesystem. Directory parts of the filename are not created automatically.
- "opfs": if available, uses OPFS storage and does create directory parts of the filename.
sqlite3_js_vfs_list()
array sqlite3_js_vfs_list()
Returns an array of the names of all currently-registered sqlite3 VFSes.
sqlite3_result_error_js()
void sqlite3_result_error_js(sqlite3_context * pCtx, Error e)
Calls either sqlite3_result_error_nomem()
, if e
is-a
WasmAllocError
, or sqlite3_result_error()
. In the latter case, the
second arugment is coerced to a string to create the error message.
Does not throw.
sqlite3_result_js()
void sqlite3_result_js(pCtx, value)
This acts as a proxy for one of the other sqlite3_result_...()
routines, depending on the type of its 2nd argument:
- If (val instanceof Error), this function passes it to
sqlite3_result_error_js()
. null
:sqlite3_result_null()
boolean
:sqlite3_result_int()
with a value of 0 or 1.number
:sqlite3_result_int()
,sqlite3_result_int64()
, orsqlite3_result_double()
, depending on the range of the number and whether or not int64 support is enabled.bigint
: similar tonumber
but will trigger an error if the value is too big to store in an int64.string
:sqlite3_result_text()
- Uint8Array or Int8Array:
sqlite3_result_blob()
undefined
: is a no-op provided to simplify certain use cases.
On error, it calls sqlite3_result_error()
with a description
of the problem.
The first argument to this function is a (sqlite3_context*)
.
Does not throw.
sqlite3_value_to_js()
mixed sqlite3_value_to_js(sqlite3_value* v, throwIfCannotConvert=true)
Given a (sqlite3_value*
), this function attempts to convert it
to an equivalent JS value with as much fidelity as feasible and
return it.
By default it throws if it cannot determine any sensible
conversion. If passed a falsy second argument, it instead returns
undefined
if no suitable conversion is found. Note that there is no
conversion from SQL to JS which results in the undefined
value. It
always throws a WasmAllocError
if allocating memory for a conversion
fails.
sqlite3_values_to_js()
array sqlite3_values_to_js(int argc, sqlite3_value* pArgV, throwIfCannotConvert=true)
Requires a C-style array of sqlite3_value*
objects and the number of
entries in that array. Returns a JS array containing the results of
passing each C array entry to
sqlite3_value_to_js()
. The 3rd argument to
this function is passed on as the 2nd argument to that one.