Skip to content

SPARQL in SQLite playground: sparqlite compiled to WASM - #357

Open
simonw wants to merge 1 commit into
mainfrom
sqlite-sparql-playground
Open

simonw wants to merge 1 commit into
mainfrom
sqlite-sparql-playground

Conversation

@simonw

@simonw simonw commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Look at most recent branches in simonw/research - the rust SQLite extension for SPARQL

Compile that extension to WASM and get it working with WASM SQLite, then build an HTML playground UI for people to try it out with plenty of examples

Adds sqlite-sparql.html, a browser playground for sparqlite, the Rust SQLite extension that implements SPARQL 1.1 (from simonw/research, branch claude/sqlite-sparql-rust, pinned to commit 70cbd8b).

The WASM build (sqlite-sparql/)

  • The extension is built as a static library for wasm32-unknown-emscripten. It is linked into SQLite 3.54.0's official WASM build (the standard sqlite3.mjs with the oo1/capi API) through SQLite's documented sqlite3_wasm_extra_init.c hook, with no makefile patching.
  • It is registered with sqlite3_auto_extension, so every connection gets the sparql_* functions and the sparql_rows / sparql_view virtual tables.
  • Size: sqlite3.wasm is 4.4 MB (1.7 MB gzipped) and sqlite3.mjs is 440 KB (94 KB gzipped).
  • build_wasm.sh rebuilds everything from pinned sources. The committed files are the output of a from-scratch run, which included a fresh Emscripten 6.0.12 install.
  • Problems the build works around (details in sqlite-sparql/README.md):
    • -fwasm-exceptions: Rust's emscripten target unwinds panics with WASM exceptions. sparqlite's panic containment works in the browser: a deliberate panic surfaces as a SQL error and the connection keeps working.
    • A wasm-opt wrapper adding --disable-compact-imports: SQLite's makefile runs wasm-opt --all-features, and the current Binaryen (version 133) then writes imports in an encoding that browsers reject ("unknown import kind 0x7f"). This affects any SQLite WASM build made with current emsdk.
    • wasm-threads.patch: WASM has no threads. RDF inputs over 1 MiB are now parsed inline, and the watchdog for the engine=sql timeout is skipped. The deadline is still checked between row batches.
  • sparqlite's direct B-tree page reader works in WASM. The playground keeps its database as a file in Emscripten's in-memory filesystem rather than :memory:, which made scan-heavy queries 2–3× faster.

The playground (sqlite-sparql.html)

  • SQLite runs in a module Web Worker, so slow queries never freeze the page. It loads with the sparqlite tutorial dataset:
    • 94 real programming languages, with their designers, influences and paradigms;
    • fictional survey and review named graphs;
    • a fictional job_postings SQL table.
  • 68 examples cover:
    • basic queries, joins and filters, OPTIONAL/UNION/MINUS, aggregates and sub-queries;
    • expressions, property paths, named graphs, ASK/CONSTRUCT/DESCRIBE and SPARQL Update;
    • the SQL side: sparql_rows, sparql_view, joins with SQL tables, views, transactions, storage tables, sparql_explain, SPARQL→SQL translation, settings, timeouts and errors.
  • Features:
    • output as a table, SPARQL JSON/XML, CSV/TSV, Turtle, N-Triples or N-Quads;
    • the Explain modes (plan/analyze/logical/algebra/sql/sqlplan);
    • a choice of engine (native or SQL translation);
    • click any IRI to explore it, or turn a query into its SQL equivalent ("As SQL");
    • shareable #sparql= / #sql= links;
    • load RDF in any of the supported formats, download the database file or open one;
    • Stop, which restarts the worker from a snapshot of the database taken after the last change;
    • dark mode and a mobile layout.

Tests

tests/test_sqlite_sparql.py has 17 Playwright tests, all passing locally in headless Chromium. One clicks through all 68 examples and checks that only the two intentional-error examples fail. Others cover each of the playground features above.

Known issue (upstream)

The spargebra 0.4.7 SPARQL parser takes exponential time on nested !( !( … ) ): about 1 s at depth 20, natively too. The worker and the Stop button keep the page usable when it happens.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VY9i6itsA8uV3tGCNf5Ppb


Generated by Claude Code

> Look at most recent branches in simonw/research - the rust SQLite extension for SPARQL
> Compile that extension to WASM and get it working with WASM SQLite, then build an HTML
> playground UI for people to try it out with plenty of examples

sqlite-sparql/ builds sparqlite (simonw/research, branch claude/sqlite-sparql-rust) for
wasm32-unknown-emscripten as a static library and links it into SQLite 3.54.0's official
WASM build (the sqlite3.mjs ES module) through SQLite's sqlite3_wasm_extra_init.c hook,
registered with sqlite3_auto_extension so every connection gets the sparql_* functions.
build_wasm.sh rebuilds it from pinned sources. Needed along the way: -fwasm-exceptions
(Rust unwinds panics with WASM exceptions), a wasm-opt wrapper adding
--disable-compact-imports (current Binaryen otherwise emits an import encoding browsers
reject), and a two-hunk patch so sparqlite never spawns threads.

sqlite-sparql.html runs it in a Web Worker on the sparqlite tutorial dataset (94 real
programming languages plus fictional survey graphs and a job_postings SQL table), with
68 examples across SPARQL queries, property paths, named graphs, CONSTRUCT/DESCRIBE,
updates and the SQL functions and virtual tables, plus explain, output formats, engine
choice, click-to-explore IRIs, RDF loading, database download/upload and a Stop button
that restores the last database snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VY9i6itsA8uV3tGCNf5Ppb

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants