SQLite WASM with extensions
(1) By anonymous on 2022-12-23 00:10:32 [source]
Hello. I have successfully built SQLite3 from the non-amalgamated sources as well as the WASM bundle.
(2) By Stephan Beal (stephan) on 2022-12-23 09:16:11 in reply to 1 [link] [source]
I am not experienced enough to figure out how to add the bindings. Is it possible to get a short description on how I would add a single function binding, e.g. sqlite3session_create?
Exporting specific features to JS requires an understanding of the build environment and the JS API, so there is no short description which will work for someone unfamiliar with those. i'm hesitant to document those steps in detailed public docs because they are internal implementation details which may change at any time (e.g. the part which performs the symbol exports from C is specific to Emscripten and we won't always be tied to Emscripten). i will look in to exposing the session API to wasm if it's feasible (not all bindings are) and get back to you.
(3) By anonymous on 2022-12-23 09:24:43 in reply to 2 [link] [source]
Thank you Stephan, looking forward to see what can be done with it.
(4) By Stephan Beal (stephan) on 2022-12-23 10:26:50 in reply to 2 [link] [source]
i will look in to exposing the session API to wasm if it's feasible (not all bindings are) and get back to you.
The session extension is huge, adding some 46 new functions and 4 data types to the API, a handful of which are flagged experimental:
This particular addition goes well beyond any of the APIs we've added so far, including virtual tables. It will require not only binding code, but also research into the session API (which i've never used before) to make sure it's done properly. (And then tests have to be written...)
i will commit to taking this on, but it will not be done soon - a cross-country move in early January severely limits my current coding time and for the foreseeable future after that move (into temporary housing) i'll have to prioritize house-hunting and moving (again) over coding.
The good news is that a cursory glance reveals nothing in the API which sticks out as being problematic for binding purposes, other than its sheer width and depth, which leads us to the most glaring caveat...
We currently have a "soft limit" of 1mb for the resulting wasm file and are currently a tick over 800kb. If this extension pushes the wasm file over that limit, we may instead opt to create a separate build for this feature so that those who don't use it don't have to pay that cost. We really don't want to do that, though, because every such extra build increases our maintenance burden significantly. Ergo, it's possible that we'll instead decide to forego the extension altogether if it adds too much weight. First we'll need to add it and see how big it is, though.
(5) By Stephan Beal (stephan) on 2022-12-23 14:33:10 in reply to 2 [link] [source]
Exporting specific features to JS requires an understanding of the build environment and the JS API, so there is no short description which will work for someone unfamiliar with those.
For the curious, here's the code and build changes needed to integrate the session extension in its lowest-level form:
Noting that binding most APIs requires far less effort than that.
We currently have a "soft limit" of 1mb for the resulting wasm file and are currently a tick over 800kb.
The size won't be an issue - this only adds about 30 or 40kb to the wasm file.
With that (in the wasm-session-api branch), the APIs are now bound to JS but...
They're completely untested and won't be moved to the trunk until they are. Writing tests will be a much larger effort, as the session API is completely foreign to me, and it's unlikely that i'll get to that any time soon.
These bindings reveal a small shortcoming in how we handle bindings of C functions which take JS functions in place of function-pointer arguments. This is best demonstrated with an example:
int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ const char *zTab /* Table name */ ), int(*xConflict)( void *pCtx, /* Copy of sixth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ );
xFilter argument is a function pointer which expects a C-string as its second argument. Our framework can handle a variety of type conversions from JS to WASM and back for WASM-exported functions, but cannot yet do so for "injected" WASM functions. When we pass a JS function to the JS binding of
sqlite3changeset_apply(), we must internally convert that to a WASM function in order to get a C-level function pointer for it. When the sqlite3 internals call it via that "injected" pointer, we don't yet have an automated way to perform type conversions on the arguments.
That particular shortcoming only affects string-type arguments. Pointers and numbers are passed through as-is with no translation (noting that C-strings are just pointers and are passed along as such). We can (and in some cases do) create hand-written bindings for such things, but the session API is large enough that automating it seems like the better idea.
On the other hand, there may be valid reasons to not automate that specific type of conversion and require that folks perform them on their own (it's just one line of code).
(6) By anonymous on 2022-12-25 01:34:21 in reply to 5 [link] [source]
Thanks for all that effort Stephan. I did not expect something so quickly. I'll start playing around with this soon.
(7) By Stephan Beal (stephan) on 2022-12-25 20:35:25 in reply to 1 [link] [source]
Merry Christmas 🎁: it's now in trunk along with very basic unit tests. It seems to work but the tests need to be expanded greatly as time and energy allow for (which seems unlikely before mid-January, but stranger things have happened).
There's a prerelease snapshot build with this feature over at wasm:/uv/snapshot.html.
The relevant JS-specific docs are at wasm:/doc/trunk/api-c-style.md#session-api.