feat(engines): the sqlite kv engine — the default engine, first SQL-backed (wave 3)

Implements the sqlite kv-tier engine per ADR-003/007/010 §1 behind
feature `sqlite` (default-on): the B5 row shape (key BLOB PK / value
BLOB / size INTEGER NOT NULL), INSERT OR IGNORE CAS first-writer-wins
on both put forms, the EXISTS has probe, the materializing cursor body
with len() from the size column, the degenerate in-memory stage with
both hygiene forms, the indexed-column size probe (plan-tested), the
no-tables-yet virgin-store read tolerance (tested against a tableless
database file), WAL + synchronous=NORMAL verified at open, prepare_cached
discipline, and every rusqlite operation in spawn_blocking under the
recorded single-connection posture.

Task: tasks/engine-sqlite.md (status: completed). The engine-state
window family and store construction remain in their own tasks.

Verification:
- cargo test — 58 pass (11 new sqlite in-module tests)
- cargo clippy --all-targets -- -D warnings — clean
- cargo fmt --check — clean
- cargo check --no-default-features — green
This commit is contained in:
glm-5.3-flash committed 2026-10-12 04:31:24 +00:00
1 parent 758ccfb359
commit 908fb5d2dd
2 files changed
+939 -5

No files matched your search

+49 -3
View File
@@ -1,7 +1,7 @@
---
id: engine-sqlite
name: sqlite kv engine — the default engine
status: pending
status: completed
depends_on: []
scope: narrow
risk: medium
@@ -111,8 +111,54 @@ in-module unit tests only.
## Notes
> To be filled by implementation agent
Recorded design points landed in the module doc (`src/sqlite.rs`):
- **Schema-creation timing:** the constructor runs `CREATE TABLE IF
NOT EXISTS` at open. The virgin-store tolerance itself is an
engine-level read-path property independent of that timing —
unit-tested against a genuinely tableless database file via a
`#[cfg(test)]` `new_tableless` constructor. The tolerance is
deliberately read-only: a write against a tableless database surfaces
the engine error rather than silently creating schema (tested).
- **WAL engagement is verified at open, not assumed:** the constructor
probes `PRAGMA journal_mode = WAL` and errors when WAL cannot be
engaged (in-memory databases included — tested). The pragma posture
(WAL persistent + synchronous NORMAL per-connection) is asserted in
the pragma test on the backend's own single connection.
- **Error mapping:** the no-tables-yet discriminant is a stringly check
on rusqlite's Display ("no such table") — stringly by nature, the
stable surface sqlite itself guarantees. `delete` maps it to
`Error::Missing` (rows-affected discipline holds for the virgin
form); `put` propagates it as `Error::Io`.
- **size metadata-only proof:** exactness is asserted for large/absent
keys and `EXPLAIN QUERY PLAN` asserts the probe searches the key's
index (`USING INDEX`) — never a scan or value load.
- Connection posture: one connection behind a short-held
`parking_lot::Mutex`, shared with staging handouts via `Arc` (a
staging commit must see the same table); the engine `Clone`s. All
rusqlite I/O in `spawn_blocking` via a local `blocking` helper (the
local.rs pattern); cursor/staging read bodies are in-memory after
materialization and need no blocking.
- `EXPLAIN QUERY PLAN` calls must bind the `?1` parameter even though
they do not execute — sqlite enforces the bind count at step time.
## Summary
> To be filled on completion
The `sqlite` kv engine shipped complete behind feature `sqlite`
(default-on): the row shape `blobs (key BLOB PRIMARY KEY, value BLOB,
size INTEGER NOT NULL)` (POC #5 B5 adapted), `INSERT OR IGNORE` CAS
first-writer-wins on both put forms, the EXISTS `has` probe, the
materializing cursor body with `len()` from the size column, the
degenerate in-memory stage committed through the whole-value row write
with both hygiene forms, the indexed-column `size` probe, complete
`list`, and the no-tables-yet read tolerance. WAL + synchronous=NORMAL
set and verified at open; `prepare_cached` discipline throughout; every
rusqlite operation in `spawn_blocking`; single-writer posture recorded
in the module doc. Eleven in-module tests green (method contract, list
completeness, cursor contract, empty entry, staged round-trip incl.
both dedup forms, both hygiene forms, pragma posture, WAL-engagement
rejection, size/index plan, tableless virgin store). `cargo test` 58
pass, `cargo clippy --all-targets -- -D warnings` clean, `cargo fmt
--check` clean, `cargo check --no-default-features` green. Engine-state
window family and store construction remain in their own tasks
(`engine-sqlite-window`, `store-sqlite-construction`).