feat: compound-PK foreign-key references — grammar + tests (ADR-0043)
Multi-column FK parsing on both surfaces: DSL from P.(a, b) to C.(x, y) (parenthesized endpoint; single bare form unchanged) and SQL FOREIGN KEY (a, b) REFERENCES P(x, y) incl. bare-reference auto-expand. consume_fk_reference + the table-level/ALTER FK parsers collect column lists; the from P. completion now offers ( (snapshots updated). 12 integration tests in tests/it/compound_fk.rs cover parse (both surfaces), engine-enforced FK, arity + partial-PK + per-pair-type-mismatch refusal, --create-fk per-column, save->rebuild round-trip, undo (one step), and single-column preservation. Mark T3 [x]; ADR-0043 implemented.
This commit is contained in:
+21
-23
@@ -399,30 +399,28 @@ since ADR-0027.)
|
||||
*(Implemented per ADR-0014; auto-fills omitted shortid
|
||||
columns and validates user-supplied values against the same
|
||||
alphabet and length range.)*
|
||||
- [/] **T3** Compound primary keys handled end-to-end (DSL,
|
||||
- [x] **T3** Compound primary keys handled end-to-end (DSL,
|
||||
storage, display, FK reference).
|
||||
*(Partial, verified 2026-06-07: compound-PK **declaration**
|
||||
(`with pk a(int),b(int)`), **storage** (`primary_key:
|
||||
Vec<String>`), and **display** are present and tested.
|
||||
**Missing: a FK that *references* a compound PK** —
|
||||
`db.rs` resolve/alter FK paths enforce a single
|
||||
`parent_column: String`; a bare `REFERENCES parent` on a
|
||||
compound-PK table is refused as ambiguous, and multi-column FK
|
||||
target syntax is not in the grammar. This is the one open
|
||||
end-to-end leg of T3 — but a **codebase audit (2026-06-09)
|
||||
found it is not a small finish**: single-column FK is woven
|
||||
through ~15–20 sites across 6+ files — the
|
||||
`__rdbms_playground_relationships` table schema, the
|
||||
`RelationshipSchema` struct, the **`project.yaml` relationship
|
||||
format** (`RawEndpoint { column }`), both grammar surfaces
|
||||
(`add 1:n relationship` + SQL `FOREIGN KEY`), the executor's FK
|
||||
DDL emission, and the per-column type-compat check. It needs a
|
||||
**migration** (the metadata-table + yaml-format change, F3) and
|
||||
an **ADR** to settle the design forks: compound-PK matching
|
||||
policy (must an FK reference *all* PK columns, or a subset?),
|
||||
per-pair type-compat semantics, the yaml multi-column shape, and
|
||||
back-compat for existing single-column projects. So this leg is
|
||||
ADR-first, not a sweep item.)*
|
||||
*(Done 2026-06-09 via **ADR-0043**: the FK-reference leg now
|
||||
works on both surfaces — DSL `add 1:n relationship from
|
||||
P.(a, b) to C.(x, y)` and SQL `FOREIGN KEY (a, b) REFERENCES
|
||||
P(x, y)` (bare `REFERENCES P` auto-expands to the full PK).
|
||||
References the parent's full compound PK matched positionally,
|
||||
per-pair type-compat (ADR-0011); the FK is engine-enforced,
|
||||
persisted (`columns: [a, b]` in `project.yaml`, comma-joined in
|
||||
metadata), shown symmetrically by `describe`, and `--create-fk`
|
||||
creates one child column per parent PK column. The relationship
|
||||
model went list-based through all six layers, single-column
|
||||
behaviour preserved (commit `b14f019`); 12 integration tests in
|
||||
`tests/it/compound_fk.rs` plus the existing single-column suite
|
||||
as the regression net. The earlier-noted (2026-06-07) breakdown:*
|
||||
*compound-PK **declaration** (`with pk a(int),b(int)`),
|
||||
**storage** (`primary_key: Vec<String>`), and **display** were
|
||||
already present and tested. The FK-reference leg — once an
|
||||
ADR-first ~15–20-site change across the relationship model — is
|
||||
what ADR-0043 delivered (back-compat dropped by user decision, so
|
||||
no migration was needed). Subset / non-PK (UNIQUE-target) FK
|
||||
references stay out of scope.)*
|
||||
|
||||
## Visualizations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user