3a0c03d781
Captures up-front design decisions for RDBMS Playground: stack (Rust + Ratatui + SQLite), input modes, project file format, type vocabulary, undo snapshots and replay log, sharing/export, and testing approach. ADR-0000 establishes the ADR practice itself and mandates index upkeep alongside any ADR change.
2.0 KiB
2.0 KiB
ADR-0002: Database engine
Status
Accepted
Context
The application teaches relational database concepts. Requirements on the engine:
- File-based, with a single binary file that can live in the project folder.
- Real RDBMS feature set: typed columns, primary keys, foreign keys with referential integrity, indexes, query planner output we can expose to learners.
- Industry adoption — students should leave with a skill that maps to something they will encounter again.
- Embeddable from Rust without arcane build steps.
Candidates considered:
- SQLite — file-based, near-universal adoption, supports FK
enforcement, has
EXPLAIN QUERY PLAN, and since 3.37 supportsSTRICTtables which give proper type enforcement instead of SQLite's traditional loose type affinity. - DuckDB — file-based, modern, but analytical/columnar by design; would teach analytical instincts that mislead in transactional contexts.
- Embedded Postgres (pglite, pg_embed) — closest to a "real" RDBMS, but adds friction and complicates packaging.
Decision
Use SQLite via the rusqlite crate. All tables are created as
STRICT tables. Foreign-key enforcement is enabled per-connection
(PRAGMA foreign_keys = ON).
Simplified user-facing column types (see ADR-0005) are mapped to the underlying SQLite STRICT types at parse time.
Consequences
- Tight, low-friction packaging —
rusqlitebundles SQLite. EXPLAIN QUERY PLANoutput is directly usable for the query analysis feature (ADR pending).- SQLite's
ALTER TABLEis limited (e.g. type changes, some drops). Schema evolution will use the rebuild-table technique internally; this is hidden from users in simple mode and exposed honestly in advanced mode. - STRICT tables forbid the historical permissive typing students might encounter elsewhere — this is intentional and matches the pedagogical goal.
- Booleans are stored as
INTEGER(0/1) per SQLite's STRICT type set; thebooluser-facing type maps to this and is rendered astrue/falsein result views.