Rust · WebAssembly · SIMD128 · no server

Orrery

A query engine in the browser

A SQL engine written from scratch — lexer, parser, binder, cost-based optimizer, vectorized operators, and a Parquet reader — compiled to WebAssembly. It runs in this tab, over seven million rows, with nothing behind it.

Databases answer questions and never show their working. This one shows all of it: the tokens, the parse tree, the plan as bound, every rewrite the optimizer makes, the operators it chose and why, and the rows moving through them as the query runs.

7,433,139
rows in one Parquet file, queried here
972
queries answered by SQLite and compared
0
dependencies in the engine crate
12,252
SIMD instructions in the shipped module

BEFORE AFTER Project Filter Join Scan Scan predicate pushdown the join now builds from the rows that survive Project Join Filter Scan Scan
Frontispiece One rewrite, of eleven. Every stage below is the engine's own output on whatever you type — nothing here is a mock-up.
I

The tables

loading…
II

The query

⌘ / Ctrl + Enter to run

III

The pipeline

one stage per figure
IV

How it is known to be right

the part that took longest

Answered twice

All 972 queries in a 1,066-record corpus are put to this engine and to SQLite, and the answers compared. A semantic bug — three-valued NULL logic, NOT IN over a nullable subquery, an outer join's padding — shows up as a disagreement rather than as something nobody noticed.

Every fast path has a slow one

The same corpus runs eight ways: vectorized against scalar, hash join against merge, pruning on against off, index scan against full scan, optimizer on against off. All eight must agree. A rewrite that changes an answer fails the build — which is the definition of semantics-preserving, made checkable.

Random tables, not just random queries

Property tests generate the data as well as the SQL: small tables, a fifth of the cells NULL, joins and subqueries over them, run with the optimizer on and off. Four hundred thousand cases. The shrinking is the point — a failure arrives as the smallest table and query that still reproduce it.