{"id":22054114,"url":"https://github.com/llimllib/wasm_sqlite_with_stats","last_synced_at":"2025-05-12T03:20:03.566Z","repository":{"id":58515906,"uuid":"532127343","full_name":"llimllib/wasm_sqlite_with_stats","owner":"llimllib","description":"Documentation and demonstration of how to build WASM versions of SQLite with extensions embedded","archived":false,"fork":false,"pushed_at":"2025-04-03T13:48:37.000Z","size":6447,"stargazers_count":26,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-05T21:08:25.455Z","etag":null,"topics":["sqlite","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://llimllib.github.io/wasm_sqlite_with_stats/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/llimllib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-03T01:47:02.000Z","updated_at":"2025-04-03T13:48:41.000Z","dependencies_parsed_at":"2023-01-17T20:31:00.385Z","dependency_job_id":null,"html_url":"https://github.com/llimllib/wasm_sqlite_with_stats","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llimllib%2Fwasm_sqlite_with_stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llimllib%2Fwasm_sqlite_with_stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llimllib%2Fwasm_sqlite_with_stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llimllib%2Fwasm_sqlite_with_stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/llimllib","download_url":"https://codeload.github.com/llimllib/wasm_sqlite_with_stats/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253666281,"owners_count":21944645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sqlite","wasm","webassembly"],"created_at":"2024-11-30T15:19:41.838Z","updated_at":"2025-05-12T03:20:03.557Z","avatar_url":"https://github.com/llimllib.png","language":"C","readme":"# Building a WASM sqlite with an embedded extension\n\nI wanted to build a wasm version of sqlite, but I also wanted to include [an\nextension](https://github.com/nalgeon/sqlean/blob/main/docs/stats.md) in it.\n\nAs far as I know, you can't dynamically load extensions into the wasm version\nof sqlite, so I wanted to build a version that had it statically linked in.\n\nAs I don't know C very well, this seemed pretty hopeless - but thankfully I\nfound [sqlite-lines](https://github.com/asg017/sqlite-lines/) by @asg017 (who\nalso kindly [helped me on\ntwitter](https://twitter.com/agarcia_me/status/1565775569664430080)), which\n[demonstrated](https://observablehq.com/@asg017/introducing-sqlite-lines) that\nit was possible.\n\n- [The pieces](#the-pieces)\n- [The idea](#the-idea)\n- [The steps](#the-steps)\n- [Build it yourself](#build-it-yourself)\n- [SQLite fiddle with extension](#sqlite-fiddle-with-extension)\n\n**update** (Nov 11 2024): there are [official instructions](https://sqlite.org/wasm/doc/trunk/building.md#:~:text=see.md%20for%20details.-,adding%20client-custom%20init%20code,-The%20WASM%20build) for adding an extension to the official WASM build (this uses sql.js instead, as the official wasm build did not exist at the time of its writing). I have not yet tried them out\n\n**update 2** (Apr 3 2025): Timothy Lin has [a very nice article](https://www.timlrx.com/blog/sqlite-wasm-with-custom-extensions) Giving a thorough example and demonstrating the `sqlite3_wasm_extra_init` function which simplifies the process and didn't exist when I wrote this piece.\n\n## The pieces\n\nTo build it, I followed in Alex's footsteps and used these pieces:\n\n- [Emscripten](https://emscripten.org/)\n- The [sqlite amalgamation file](https://www.sqlite.org/amalgamation.html) and\n  [extension header\n  file](https://github.com/sqlite/sqlite/blob/master/src/sqlite3ext.h)\n  - I just copied the versions Alex used\n- The [stats\n  file](https://github.com/nalgeon/sqlean/blob/main/src/sqlite3-stats.c) from\n  sqlean\n- The [sqlite wasm API](https://github.com/sql-js/sql.js/) from sql.js\n- The [Makefile](https://github.com/asg017/sqlite-lines/blob/main/Makefile) and\n  [core-init.c](https://github.com/asg017/sqlite-lines/blob/main/core_init.c)\n  file from [sqlite-lines](https://github.com/asg017/sqlite-lines)\n\n## The idea\n\nThe basic idea of building a sqlite that has an extension statically linked is\nthat you can use an undocumented C preprocessor macro called\n`SQLITE_EXTRA_INIT` which will, if defined, load extra code into sqlite after\nfinishing up its own initialization. If you point `SQLITE_EXTRA_INIT` at a\nfunction that calls\n[`sqlite3_auto_extension`](https://www.sqlite.org/c3ref/auto_extension.html)\nwith a pointer to your extension's init function, it will load right after\nsqlite loads itself and the functions defined within will be available to\nsqlite.\n\n## The steps\n\nTo make the idea happen, this code:\n\n- sets `SQLITE_EXTRA_INIT` [here](https://github.com/llimllib/wasm_sqlite_with_stats/blob/83bdf9e1bf6808590a281d8f2d32cafafa750b33/Makefile#L13), pointing to the `core_init` function\n- defines the `core_init` function [here](https://github.com/llimllib/wasm_sqlite_with_stats/blob/83bdf9e1bf6808590a281d8f2d32cafafa750b33/core_init.c)\n- makes `core_init` available to sqlite by [appending it](https://github.com/llimllib/wasm_sqlite_with_stats/blob/83bdf9e1bf6808590a281d8f2d32cafafa750b33/Makefile#L52) to the end of the amalgamation file as the first step of our build process\n- uses emscripten [to build](https://github.com/llimllib/wasm_sqlite_with_stats/blob/83bdf9e1bf6808590a281d8f2d32cafafa750b33/Makefile#L38) sqlite3-stats.c and the amalgamation file (with the appended `SQLITE_EXTRA_INIT` bit) together into a wasm output\n\nFinally, I made an [HTML page](https://github.com/llimllib/wasm_sqlite_with_stats/blob/e057459ef636de80091bbc781751055b9bf5395d/index.html) that makes the most basic possible use of the sqlite binary to make sure that the stats extension has been loaded.\n\n## Build it yourself\n\n`make clean wasm`\n\nTo visit the web page that demonstrates how to use the file, serve the `dist`\ndirectory with a web server that serves proper mime types. I like to use\n[`devd`](https://github.com/cortesi/devd), so I run `devd -ol dist`\n\n## SQLite fiddle with extension\n\nI used the knowledge I gained in this effort to a [SQLite fiddle with an embedded extension](https://llimllib.github.io/wasm_sqlite_with_stats/). Instructions for building the fiddle can be found in the [build-fiddle](https://github.com/llimllib/wasm_sqlite_with_stats/tree/build-fiddle) branch.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllimllib%2Fwasm_sqlite_with_stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fllimllib%2Fwasm_sqlite_with_stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllimllib%2Fwasm_sqlite_with_stats/lists"}