docs: ADR-0035 4a.2 plan + split table-level CHECK to 4a.3

Survey of the constraint persistence machinery revealed that
table-level/multi-column CHECK needs a NEW __rdbms_* metadata table
(SQLite exposes no PRAGMA for CHECK), unlike per-column CHECK/DEFAULT
(reuse __rdbms_playground_columns.check_expr + PRAGMA dflt_value) and
composite UNIQUE (PRAGMA index_list origin 'u' + a TableSchema field).

User-confirmed split: 4a.2 = per-column CHECK/DEFAULT (raw sql_expr
text) + composite UNIQUE(a,b), no new internal table; 4a.3 = table-level
CHECK + the new metadata table. ADR §13 and README updated in lockstep;
4a.2 plan doc added.
This commit is contained in:
claude@clouddev1
2026-05-25 10:34:04 +00:00
parent 631074ff9c
commit 1c50133438
3 changed files with 212 additions and 11 deletions
+19 -10
View File
@@ -319,16 +319,25 @@ ADR-0033's structure:
autoincrement is independent of inline-vs-table-level PK (the insert
path computes the next value), verified by round-trip tests. **No
FK** (4b); **no `DEFAULT`/`CHECK`/table-level `UNIQUE`** (4a.2).
- **4a.2 — The constraint slice.** Split out (2026-05-24,
user-confirmed) for the constraints that are *not* a clean reuse:
(1) **`CHECK`/`DEFAULT`** via the full `sql_expr` surface stored as
**raw SQL text** — needed because `sql_expr` is validate-only and
yields no `Expr` AST for `compile_check_sql`/`ColumnSpec`, so it is a
separate execution path; (2) **composite `UNIQUE(a,b)` and
multi-column table `CHECK`** — the first structures `TableSchema`
cannot already represent, needing a model + YAML round-trip +
`read_schema` detection + `do_create_table` emission extension, with
save/load/rebuild tests. Until then 4a rejects all of these
- **4a.2 — Per-column `CHECK`/`DEFAULT` + composite `UNIQUE(a,b)`.**
Split out (2026-05-24) and re-scoped (2026-05-25, user-confirmed) to
the constraints that need **no new internal table**: (1)
**`CHECK`/`DEFAULT`** via the full `sql_expr` surface stored as **raw
SQL text** — `sql_expr` is validate-only (no `Expr` AST for
`compile_check_sql`/`ColumnSpec`), so a separate execution path
captures the raw expression text; per-column `CHECK` reuses the
existing `__rdbms_playground_columns.check_expr` column, `DEFAULT`
round-trips via the engine's native `PRAGMA table_info`; (2)
**composite `UNIQUE(a,b)`** — a new `TableSchema.unique_constraints`
field, detected on read via the UNIQUE-constraint index
(`PRAGMA index_list` origin `u`), round-tripped through YAML, with
save/load/rebuild tests.
- **4a.3 — Table-level / multi-column `CHECK(…)`.** Split from 4a.2
(2026-05-25, user-confirmed) because SQLite exposes **no PRAGMA for
CHECK constraints**, so a table-level CHECK cannot be read back from
the engine and needs a **new `__rdbms_*` metadata table** as its
source of truth (the ADR-0012/0013 pattern) — a distinct
architectural step. Until 4a.2/4a.3 land, 4a rejects these forms
"not yet supported". (The general rule: a DDL feature needs new
model/execution work only when it introduces a structure simple mode
could never produce, or an expression the structural helper cannot