Skip to content

Commit a35ff2f

Browse files
joaoh82claude
andauthored
feat(web): launch sqlrite.dev — landing, /docs, benchmarks viz, doc sweep (SQLR-1) (#117)
* docs(roadmap): Phase 9 + Phase 10 — sync v0.2.0 → v0.9.1 wave The roadmap, supported-SQL reference, and the docs index had drifted behind nine minor releases of actual SQL-surface work. Each item below was independently shipped under its own SQLR-* / PR but had been languishing under "Possible extras" or in the "Not yet supported" list — confusing for anyone reading the docs to figure out what the engine actually does today. Phase 9 (v0.2.0 → v0.9.1) — promoted from "extras" to a real phase: 9a · v0.3.0 · DEFAULT clause + DROP TABLE/INDEX + ALTER TABLE 9b · v0.4.0 · free-list + manual VACUUM (SQLR-6) 9c · v0.5.0 · auto-VACUUM trigger past 25% (SQLR-10) 9d · v0.5.1 · IS NULL / IS NOT NULL + Option<Value> INSERT (SQLR-7) 9e · v0.6.0 · GROUP BY + aggregates + DISTINCT + LIKE + IN (SQLR-3) 9f · v0.7.0 · JOINs — INNER, LEFT, RIGHT, FULL OUTER (SQLR-5) 9g · v0.9.0 · prepared statements + ? param binding (SQLR-23) 9h · v0.9.0 · HNSW probe widened to cosine + dot (SQLR-28) 9i · v0.9.1 · PRAGMA dispatcher + auto_vacuum knob (SQLR-13) Phase 10 — benchmarks vs SQLite + DuckDB (SQLR-4 / SQLR-16, twelve workloads, pinned-host runs published). Also fixed: - docs/supported-sql.md "Not yet supported" was self-contradicting: body documented LIKE / IN / GROUP BY / aggregates / DISTINCT / ALTER TABLE / DROP / VACUUM in detail, then claimed they weren't supported. Pruned the now-stale entries; left HAVING, BETWEEN, GLOB / REGEXP, GROUP_CONCAT, named placeholders, MVCC, etc. - docs/_index.md "Project state" gained Phase 9 + Phase 10 lines. - The "Active frontier" callout at the top of roadmap.md no longer points at the v0.2.0 milestone (already shipped six minor releases ago). - The "Possible extras" tail block now lists only what's actually open (subqueries, CTEs, HAVING, CASE, BETWEEN, OFFSET, multi-col ORDER BY, MVCC, savepoints, more pragmas, etc.). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(web): launch project website — landing, /docs, benchmarks viz A new Next.js 15 + Tailwind v4 site under web/, intentionally self-contained (own package.json, no Cargo coupling) so it can be extracted into its own repo later without rewrites. Deploys to Vercel out of the box — point Vercel at web/ as the Root Directory and the framework preset handles the rest. Two pages, eleven sections, no client-side chart library. Landing (/) 01 Hero · animated SQL REPL + cargo-install bar, hero-meta calls out "Phases 0–10 shipped · v0.9.1 on crates.io / PyPI / npm" 02 Features · 12-card grid covering pager, B-tree, WAL, transactions, JOINs + aggregates, prepared statements, HNSW, FTS, free-list + auto-VACUUM, six SDKs, Tauri + MCP, "built to be read" 03 Architecture · 7-layer diagram from input → storage 04 Roadmap · timeline with done / active / next states; Phase 9 sub-phases (v0.2.0 → v0.9.1) and Phase 10 (benchmarks) match the repo's docs/roadmap.md 1:1 05 SDK switcher · tabbed Rust/Python/Node/Go/C/WASM with per-SDK install command, version, registry, and a copy-pasteable example 06 SQL surface · statement table including JOINs, aggregates, ALTER TABLE, DROP TABLE/INDEX, VACUUM, PRAGMA, prepared statements; plus an honest "not yet supported" pill list 07 Benchmarks · pure-CSS proportional bars (no chart library) sized per-row so "shorter = faster" lines up with "lower is better". Three headline stats (~50× HNSW, 1.6–1.9× read-path gap, 608 µs hybrid), four chart groups (the HNSW win, OLTP read paths, FTS + hybrid, DuckDB analytical lead), four SQLR-tagged engineering debts, and links to the canonical doc + raw JSON envelope 08 Desktop · Tauri 2.0 + Svelte 5 mockup with download buttons 09 Blog · four-card grid pointing at the Medium series CTA strip + footer with author socials (GitHub, LinkedIn, X) Docs (/docs) Sticky sidebar nav + on-page TOC. New sections for JOINs, GROUP BY & aggregates, ALTER / DROP / VACUUM, prepared statements, PRAGMA, vector search, full-text search, the MCP server. The "Supported SQL" summary lists JOINs, aggregates, predicates, prepared statements, pragmas as their own bullets. Stack - Next.js 15.5.18 (App Router) + React 19 + TypeScript (strict) - Tailwind v4 (CSS-first @theme config in src/app/globals.css) - shadcn/ui infrastructure (components.json + cn helper) — bespoke components on top, no premature abstraction - lucide-react for icons; next/font for Inter + JetBrains Mono - "use client" only where state lives (terminal, install-bar, sdk-showcase). Everything else is a Server Component. - SQL highlighter is a tokenizer that returns React nodes — no dangerouslySetInnerHTML anywhere in the tree. Verified: - npm run typecheck ✓ - npm run lint ✓ (no warnings) - npm run build ✓ — 5 static pages, 3.9 kB / 110 kB First Load JS landing - render-test on dev server: every nav anchor resolves; per-row benchmark bar widths come out at the right proportions (HNSW 1.99% next to brute-force 100%, DuckDB clamped to 1.5% min so label is still readable) CLAUDE.md + README.md gain a one-line pointer to web/ so a first-time reader of the repo finds the site without grepping. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9221f49 commit a35ff2f

36 files changed

Lines changed: 10933 additions & 16 deletions

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SQLRite is a from-scratch SQLite-style embedded database written in Rust. It's p
1616
- `sqlrite-ffi/` — C ABI cdylib + generated `sqlrite.h` header. Backs the Go SDK and any C consumer.
1717
- `desktop/` — Tauri 2 + Svelte 5 GUI. Embeds the engine directly (no FFI hop).
1818
- `benchmarks/` — SQLR-4 / SQLR-16 bench harness. `Driver` trait + SQLRite + SQLite (rusqlite-bundled) drivers + criterion-driven workloads. Excluded from the default CI build/test/clippy/doc commands; run locally with `make bench` (or `make bench-duckdb`). See [docs/benchmarks-plan.md](docs/benchmarks-plan.md).
19+
- `web/` — marketing + docs site (Next.js 15 + Tailwind v4). Independent of the Cargo workspace; lives in-repo for now but is structured to lift into its own repository later. See [web/README.md](web/README.md).
1920

2021
Architecture deep-dive: [docs/architecture.md](docs/architecture.md). The full doc index is [docs/_index.md](docs/_index.md).
2122

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Rust-SQLite (SQLRite)
1111
> What I cannot create, I do not understand.
1212
> — Richard Feynman
1313
14+
📖 **Project website + docs:** the marketing + getting-started site is in [`web/`](web/) (Next.js 15 + Tailwind v4). Run `cd web && npm install && npm run dev` to preview locally; deploys to Vercel out of the box.
15+
1416

1517
<table style="width:100%">
1618
<tr>

docs/_index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ As of May 2026, SQLRite has:
5252
- A Tauri 2.0 + Svelte desktop app (Phase 2.5 complete)
5353
- AI-era extensions across the product surface (Phase 7 complete): VECTOR columns + HNSW indexes (7a-7d), JSON columns (7e), the `ask()` natural-language → SQL family across the REPL / desktop / Rust / Python / Node / Go / WASM (7g.1-7g.7), and the [`sqlrite-mcp`](mcp.md) Model Context Protocol server (7h + 7g.8)
5454
- Full-text search + hybrid retrieval (Phase 8 complete): FTS5-style inverted index with BM25 ranking + `fts_match` / `bm25_score` scalar functions + `try_fts_probe` optimizer hook + on-disk persistence with on-demand v4 → v5 file-format bump (8a-8c), a worked hybrid-retrieval example combining BM25 with vector cosine via raw arithmetic (8d), and a `bm25_search` MCP tool symmetric with `vector_search` (8e). See [`docs/fts.md`](fts.md).
55+
- SQL surface + DX follow-ups (Phase 9 complete, v0.2.0 → v0.9.1): DDL completeness — `DEFAULT`, `DROP TABLE` / `DROP INDEX`, `ALTER TABLE` (9a); free-list + manual `VACUUM` (9b) + auto-VACUUM (9c); `IS NULL` / `IS NOT NULL` (9d); `GROUP BY` + aggregates + `DISTINCT` + `LIKE` + `IN` (9e); four flavors of `JOIN` — INNER, LEFT, RIGHT, FULL OUTER (9f); prepared statements + `?` parameter binding with a per-connection LRU plan cache (9g); HNSW probe widened to cosine + dot via `WITH (metric = …)` (9h); `PRAGMA` dispatcher with the `auto_vacuum` knob (9i)
56+
- Benchmarks against SQLite + DuckDB (Phase 10 complete, SQLR-4 / SQLR-16): twelve-workload bench harness with a pluggable `Driver` trait, criterion-driven, pinned-host runs published. See [`docs/benchmarks.md`](benchmarks.md).
5557
- A fully-automated release pipeline that ships every product to its registry on every release with one human action — Rust engine + `sqlrite-ask` + `sqlrite-mcp` to crates.io, Python wheels to PyPI (`sqlrite`), Node.js + WASM to npm (`@joaoh82/sqlrite` + `@joaoh82/sqlrite-wasm`), Go module via `sdk/go/v*` git tag, plus C FFI tarballs, MCP binary tarballs, and unsigned desktop installers as GitHub Release assets (Phase 6 complete)
5658

5759
See the [Roadmap](roadmap.md) for the full phase plan.

docs/roadmap.md

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
The project is staged in phases. Each phase is shippable on its own, ends with a working build + full test suite + a commit on `main`, and can be paused between. The README's roadmap section is a summary of this doc.
44

5-
> **Active frontier (May 2026):** Phase 8 shipped end-to-end (8a–8f). All six sub-phases — standalone algorithms, SQL surface, cell-encoded persistence with on-demand v4→v5 file-format bump, hybrid-retrieval worked example, `bm25_search` MCP tool, and the docs sweep — landed across PRs #78#83. The next milestone is the **v0.2.0 release** (file-format change + new SQL surface). After v0.2.0 the roadmap loops back to "possible extras" and the 5a.2 cursor refactor.
5+
> **Active frontier (May 2026):** Phases 0–10 shipped end-to-end. After Phase 8 closed the v0.1.x cycle, the v0.2.0 → v0.9.1 wave (Phase 9, sub-phases 9a–9i) landed the SQL surface that had been parked under "possible extras": DDL completeness (DEFAULT, DROP TABLE/INDEX, ALTER TABLE), free-list + auto-VACUUM, IS NULL, GROUP BY + aggregates + DISTINCT + LIKE + IN, four flavors of JOIN, prepared statements with parameter binding, HNSW metric extension, and the PRAGMA dispatcher. Phase 10 published the SQLR-4 / SQLR-16 benchmarks against SQLite + DuckDB. **Current head: v0.9.1.** The roadmap from here is the smaller "possible extras" list at the bottom of this doc plus the 5a.2 cursor refactor.
66
77
## ✅ Phase 0 — Modernization
88

@@ -517,12 +517,87 @@ Adds the `bm25_search` MCP tool, symmetric with `vector_search` (Phase 7h). Wrap
517517

518518
Final docs pass — canonical [`fts.md`](fts.md) reference (mirrors `ask.md`'s shape); FTS sections added to [`supported-sql.md`](supported-sql.md), [`architecture.md`](architecture.md) (module map + storage section), [`file-format.md`](file-format.md) (`KIND_FTS_POSTING` layout, v4→v5 bump in version history), [`sql-engine.md`](sql-engine.md) (`try_fts_probe` optimizer hook), [`mcp.md`](mcp.md) (`bm25_search` tool entry + count bump 7→8); FTS step added to [`smoke-test.md`](smoke-test.md); [`_index.md`](_index.md) re-organized to give Phase 8 its own top-level section.
519519

520+
## ✅ Phase 9 — SQL surface + DX follow-ups *(0.2.0 → 0.9.1)*
521+
522+
After Phase 8 closed out the v0.1.x cycle and the v0.2.0 file-format bump shipped, the next wave landed the SQL features that had been parked under "possible extras," plus the storage hygiene + DX work that had accumulated alongside them. Each sub-phase shipped as its own minor release, so consumers got each capability the moment it was stable on `main`.
523+
524+
### ✅ Phase 9a — DDL completeness *(v0.3.0)*
525+
526+
`feat(ddl): DEFAULT clause, DROP TABLE/INDEX, ALTER TABLE` (PR #86).
527+
528+
- **`DEFAULT <literal>`** column constraint — accepted on CREATE TABLE and ADD COLUMN; literal-only (function defaults like `CURRENT_TIMESTAMP` rejected at parse time so we don't silently accept misleading SQL).
529+
- **`DROP TABLE [IF EXISTS]`** + **`DROP INDEX [IF EXISTS]`** — single-target; refuses to drop `sqlrite_autoindex_*` (constraint-bound). All attached indexes (auto, explicit, HNSW, FTS) ride along when a table goes away.
530+
- **`ALTER TABLE`**`RENAME TO` / `RENAME COLUMN` / `ADD COLUMN` / `DROP COLUMN`. One operation per statement (SQLite parity). Auto-index names follow renames; index deps cascade through column drops; `ADD COLUMN` with `DEFAULT` backfills existing rows.
531+
532+
### ✅ Phase 9b — Free-list + manual VACUUM *(v0.4.0, SQLR-6)*
533+
534+
Pages released by `DROP TABLE` / `DROP INDEX` / `ALTER TABLE DROP COLUMN` go onto a persisted free-page list rather than being silently leaked. `CREATE TABLE` and INSERT consult the freelist before extending the file. Bare `VACUUM;` rewrites every live B-Tree contiguously from page 1 and clears the freelist; modifiers (`VACUUM FULL`, table targets, etc.) are parsed but rejected at execution. No-op on in-memory databases. Refused inside an open transaction.
535+
536+
### ✅ Phase 9c — Auto-VACUUM *(v0.5.0, SQLR-10)*
537+
538+
Every page-releasing DDL checks the freelist after committing and runs `vacuum_database` automatically when the freelist exceeds **25%** of `page_count` (SQLite parity). Skips databases under 16 pages, skips inside transactions, skips on in-memory and read-only DBs. Threshold tunable per-`Connection` via `set_auto_vacuum_threshold(Option<f64>)`.
539+
540+
### ✅ Phase 9d — `IS NULL` / `IS NOT NULL` + typed `Option<Value>` INSERT pipeline *(v0.5.1, SQLR-7)*
541+
542+
Explicit null tests across `WHERE` / `UPDATE SET` / `DELETE WHERE`. The INSERT pipeline started carrying `Option<Value>` end-to-end so `NULL` and a missing-column DEFAULT can be distinguished without a sentinel.
543+
544+
### ✅ Phase 9e — `GROUP BY`, aggregates, `DISTINCT`, `LIKE`, `IN` *(v0.6.0, SQLR-3)*
545+
546+
The biggest single SQL-surface jump in the project's history.
547+
548+
- **`GROUP BY <col>[, <col>, …]`** — bare column names only. Every non-aggregate projection item must appear in the `GROUP BY` list (parser-checked).
549+
- **Aggregates**`COUNT(*)`, `COUNT(col)`, `COUNT(DISTINCT col)`, `SUM`, `AVG`, `MIN`, `MAX`. Integer `SUM` stays integer until a `REAL` arrives or `i64` overflows (one-time promotion). `AVG` returns `REAL` (or `NULL` on empty groups). `MIN` / `MAX` skip NULLs and use the same total order as `ORDER BY`. Empty-group results are `0` for counts, `NULL` for the rest.
550+
- **`DISTINCT`** — applies after projection (and after aggregation when both are present); `LIMIT` counts unique rows; `NULL = NULL` for dedupe.
551+
- **`LIKE` / `NOT LIKE` / `ILIKE`**`%`, `_`, `\`-escape. ASCII case folding on by default (SQLite parity). `NULL LIKE 'pattern'` evaluates to `NULL` (excluded by `WHERE`).
552+
- **`IN (literal-list)`** + **`NOT IN (literal-list)`** — three-valued logic per SQL standard.
553+
554+
### ✅ Phase 9f — JOINs *(v0.7.0, SQLR-5)*
555+
556+
`INNER`, `LEFT OUTER`, `RIGHT OUTER`, `FULL OUTER JOIN ... ON …` with explicit `ON`. Why all four when SQLite ships only INNER + LEFT: the per-flavor differences are NULL-padding policies on top of one nested-loop driver — `RIGHT` / `FULL` were free once the executor had a multi-table scope. See [`docs/design-decisions.md`](design-decisions.md) for the rationale.
557+
558+
- Aliases (`FROM customers AS c JOIN orders AS o ON c.id = o.customer_id`); when an alias is supplied the original name leaves scope (SQL standard).
559+
- Qualified column references (`<table>.<col>` / `<alias>.<col>`); ambiguous bare references error with a "qualify it" hint.
560+
- Multi-join chains left-fold: `A ⨝ B ⨝ C` evaluates as `(A ⨝ B) ⨝ C`.
561+
- Self-joins require an alias on at least one side.
562+
- `WHERE` runs after joins (the standard `LEFT JOIN ... WHERE right.col IS NULL` anti-join idiom works).
563+
564+
Not yet supported: `CROSS JOIN`, comma-separated FROMs, `NATURAL JOIN`, `JOIN ... USING (col)`, aggregates / `GROUP BY` / `DISTINCT` *over* a join, `fts_match` / `bm25_score` inside a join expression. Algorithm: plain nested-loop, O(N×M) per level — hash / merge joins are a future optimization.
565+
566+
### ✅ Phase 9g — Prepared statements + parameter binding *(v0.9.0, SQLR-23)*
567+
568+
Every executable statement accepts `?` placeholders anywhere a value literal is allowed. Public Rust API: `Connection::prepare` / `prepare_cached`, `Statement::execute_with_params(&[Value])` / `query_with_params(&[Value])`. Strict positional binding, strict arity. `Value::Vector(Vec<f32>)` binds where a bracket-array literal would normally appear — including the second arg of `vec_distance_*` inside an HNSW-eligible `ORDER BY`, so the graph shortcut still fires for prepared KNN queries.
569+
570+
`prepare_cached` keeps a per-connection LRU plan cache (default cap 16, tunable via `set_prepared_cache_capacity`) — a hot SQL string parses exactly once across the connection's lifetime. Named placeholders (`:foo`, `$1`) deferred.
571+
572+
### ✅ Phase 9h — HNSW probe widened to cosine + dot *(v0.9.0, SQLR-28)*
573+
574+
`CREATE INDEX … USING hnsw (col) WITH (metric = '<l2|cosine|dot>')` — the metric travels with the index and the optimizer only takes the graph shortcut when the query's `vec_distance_*` function matches the index's metric. Mismatches fall through to brute force rather than returning a wrong answer. Pre-SQLR-28 catalogs round-trip unchanged (no `WITH` is equivalent to `metric = 'l2'`).
575+
576+
### ✅ Phase 9i — `PRAGMA` dispatcher + `auto_vacuum` knob *(v0.9.1, SQLR-13)*
577+
578+
`PRAGMA <name>;` (read) / `PRAGMA <name> = <value>;` (write) is now a real executor arm. The first wired pragma is `auto_vacuum`, which exposes the SQLR-10 threshold to SDK / FFI / MCP consumers that can't call the Rust setter. Out-of-range values, NaN, ±∞, and unknown identifiers are rejected with typed errors — the trigger never silently saturates. Adding a new pragma is a single arm in `execute_pragma`; future ones (`journal_mode`, `synchronous`, `cache_size`, `page_size`, …) will land as they earn their keep.
579+
580+
## ✅ Phase 10 — Benchmarks vs SQLite *(SQLR-4 / SQLR-16)*
581+
582+
End-to-end SQLR-4 / SQLR-16 bench harness with twelve workloads across three groups (read-by-PK, transactional CRUD, analytical slices, vector / FTS retrieval). Pluggable `Driver` trait + bundled SQLite + DuckDB drivers; criterion-based; pinned-host runs published at [`docs/benchmarks.md`](benchmarks.md). Excluded from CI (criterion is too noisy on shared runners; `rusqlite-bundled` is heavy). See [`docs/benchmarks-plan.md`](benchmarks-plan.md) for the design and PRs #102#114 for the staged rollout.
583+
520584
## "Possible extras" not pinned to a phase
521585

522-
- Joins (`INNER`, `LEFT OUTER`, `CROSS`)
523-
- `GROUP BY`, aggregates (`COUNT`, `SUM`, `AVG`, ...), `DISTINCT`, `LIKE`, `IN`
524-
- Composite and expression indexes
586+
The remaining items — actually open, not retroactively rewritten:
587+
588+
- Subqueries (scalar, `IN (SELECT ...)`, correlated) and CTEs (`WITH`, recursive)
589+
- `HAVING` (post-aggregation filter)
590+
- `CASE WHEN … THEN … END`, `BETWEEN`, `GLOB`, `REGEXP`, `LIKE … ESCAPE '<char>'`
591+
- Aggregates / `GROUP BY` / `DISTINCT` *over* joins (needs a single executor pass that knows about multiple input streams)
592+
- Multi-column / expression `ORDER BY`, `OFFSET`, `NULLS FIRST/LAST`
593+
- `UNION` / `INTERSECT` / `EXCEPT`, `INSERT ... SELECT`
594+
- Composite + expression indexes
595+
- Concurrent writes via MVCC + `BEGIN CONCURRENT` — design sketch in [`docs/concurrent-writes-plan.md`](concurrent-writes-plan.md)
596+
- `CREATE VIEW`, `CREATE TRIGGER`, `FOREIGN KEY`, `CHECK`, table-level / composite constraints
597+
- Savepoints + isolation-level control (`BEGIN IMMEDIATE` / `BEGIN EXCLUSIVE`)
598+
- Built-in scalar functions (`LENGTH`, `UPPER`, `LOWER`, `COALESCE`, `IFNULL`, date/time, `printf`, …)
599+
- More pragmas (`journal_mode`, `synchronous`, `cache_size`, `page_size`, …)
525600
- Alternate storage engines (LSM/SSTable for write-heavy workloads)
526-
- Benchmarks against SQLite — design proposal in [`benchmarks-plan.md`](benchmarks-plan.md) (SQLR-4). Confirmed comparison targets: SQLite (mandatory baseline), DuckDB on analytical-slice workloads (optional). libSQL deferred; Cloudflare D1 + rqlite explicitly out-of-scope (network-resident, not embedded).
601+
- Code signing for desktop installers (Phase 6.1)
527602

528-
These will slot in where they make sense — many are natural side effects of Phase 3 storage work or Phase 5's library API.
603+
These slot in where they make sense — many are natural side effects of the existing executor / pager / parser surfaces.

docs/supported-sql.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -589,23 +589,26 @@ A REPL launched with `sqlrite --readonly foo.sqlrite` (or `sqlrite::open_databas
589589
For context when you hit `NotImplemented`. See [Roadmap](roadmap.md) for when these land:
590590

591591
### Joins & composition
592-
- `INNER` / `LEFT OUTER` / `RIGHT OUTER` / `FULL OUTER JOIN ... ON ...`**supported** (SQLR-5)
593-
- `CROSS JOIN`, comma joins, `NATURAL JOIN`, `JOIN ... USING` — not yet
592+
- `CROSS JOIN`, comma joins, `NATURAL JOIN`, `JOIN ... USING` — explicit `INNER` / `LEFT` / `RIGHT` / `FULL OUTER JOIN ... ON ...` works (SQLR-5); the others don't
593+
- Aggregates / `GROUP BY` / `DISTINCT` *over* a JOIN — pipe through a subquery once subqueries land
594+
- `fts_match` / `bm25_score` inside a JOIN expression — single-table-bound today
594595
- Subqueries (scalar, `IN (SELECT ...)`, correlated)
595596
- CTEs (`WITH`), recursive CTEs
596597
- Views (`CREATE VIEW`)
597598

598599
### Aggregation & grouping
599-
- `GROUP BY`, `HAVING`
600-
- Aggregate functions (`COUNT`, `SUM`, `AVG`, `MIN`, `MAX`, `GROUP_CONCAT`)
601-
- `DISTINCT`
600+
- `HAVING` — pre-aggregation `WHERE` works; post-aggregation filtering doesn't yet
601+
- `DISTINCT` on `SUM` / `AVG` / `MIN` / `MAX` (only `COUNT(DISTINCT col)` is supported)
602+
- `GROUP BY` on expressions — bare column names only
603+
- Other aggregate functions (`GROUP_CONCAT`, `STRING_AGG`, …) — only `COUNT` / `SUM` / `AVG` / `MIN` / `MAX` are wired
602604

603605
### Predicate & expression
604-
- `LIKE`, `GLOB`, `REGEXP`
605-
- `IN (...)`, `NOT IN`, `BETWEEN`
606+
- `GLOB`, `REGEXP`
607+
- `BETWEEN`
608+
- `LIKE … ESCAPE '<char>'` — bare `LIKE` / `NOT LIKE` / `ILIKE` work; the explicit-escape form doesn't
609+
- `IN (subquery)`, `IN UNNEST(...)` — only literal lists are supported
606610
- `CASE WHEN ... THEN ... END`
607-
- Expressions in the `SELECT` projection list
608-
- Column aliases (`AS`)
611+
- Expressions in the `SELECT` projection list — aggregate calls are the one allowed expression form (`SELECT age + 1 FROM users` is rejected)
609612
- Built-in functions (`LENGTH`, `UPPER`, `LOWER`, `COALESCE`, `IFNULL`, date/time, `printf`, …)
610613

611614
### DDL
@@ -620,13 +623,18 @@ For context when you hit `NotImplemented`. See [Roadmap](roadmap.md) for when th
620623
### Transactions
621624
- Savepoints (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`)
622625
- Isolation-level control (`BEGIN IMMEDIATE`, `BEGIN EXCLUSIVE`)
626+
- Concurrent writes / MVCC (`BEGIN CONCURRENT`) — proposal sketched in [`docs/concurrent-writes-plan.md`](concurrent-writes-plan.md)
623627

624628
### Query shape
625629
- `OFFSET`
626-
- Multi-column `ORDER BY`
630+
- Multi-column `ORDER BY`, `NULLS FIRST/LAST`
627631
- `UNION`, `INTERSECT`, `EXCEPT`
628632
- `INSERT ... SELECT`
629633
- `UPDATE ... FROM`, `DELETE ... USING`
634+
- Window functions (`OVER (...)`, `FILTER (WHERE ...)`, `WITHIN GROUP`)
635+
636+
### Parameter binding
637+
- Named placeholders (`:foo`, `$1`, `@x`) — only positional `?` is supported (SQLR-23)
630638

631639
### Session / schema
632640
- Multiple attached databases (`ATTACH DATABASE`, `DETACH DATABASE`)

web/.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# dependencies
2+
/node_modules
3+
/.pnp
4+
.pnp.*
5+
.yarn/*
6+
!.yarn/patches
7+
!.yarn/plugins
8+
!.yarn/releases
9+
!.yarn/versions
10+
11+
# testing
12+
/coverage
13+
14+
# next.js
15+
/.next/
16+
/out/
17+
18+
# production
19+
/build
20+
21+
# misc
22+
.DS_Store
23+
*.pem
24+
25+
# debug
26+
npm-debug.log*
27+
yarn-debug.log*
28+
yarn-error.log*
29+
.pnpm-debug.log*
30+
31+
# env files
32+
.env*
33+
!.env.example
34+
35+
# vercel
36+
.vercel
37+
38+
# typescript
39+
*.tsbuildinfo
40+
next-env.d.ts

0 commit comments

Comments
 (0)