feat(schema): foreign keys for every table reference, with orphan quarantine #11

Merged
KofTwentyTwo merged 4 commits from feature/foreign-keys into develop 2026-10-14 23:00:28 +00:00
4 Commits
Author SHA1 Message Date
james.maesandClaude Opus 5.5 588ae52cd9 test(reports): give the old retention report a real run
The foreign key on lab_report.run_id rejects develop's placeholder run 999999,
so the 40-day-old report now belongs to an inserted FAILED run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:51:18 -05:00
james.maesandClaude Opus 5.5 cad99545b2 Merge origin/develop into feature/foreign-keys
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:49:47 -05:00
james.maesandClaude Opus 5.5 fb856fdb39 test(schema): take a join's referencing side from its key field
A join's child column is on the side whose field is not the primary key,
so a many-to-one join (child -> parent) is checked on the child too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:35:13 -05:00
james.maesandClaude Opus 5.5 7ed9d0b81e feat(schema): foreign keys for every table reference, with orphan quarantine
Changesets 12-26 add a foreign key for each possible-value reference between
the QBit's tables, named fk_<child table>_<column>:

- lab_finding.run_id, lab_report.run_id -> lab_run: CASCADE (owned detail)
- comparison.change_event_id -> change_event: CASCADE (computed for the change)
- regression.cause_change_event_id, lab_run.change_event_id -> change_event,
  regression.first_run_id / checkpoint_run_id -> lab_run: SET NULL (pointers)
- lab_run / lab_finding / regression / comparison .target_id -> target and
  regression.budget_id -> budget: RESTRICT (history is kept, D8; pages and
  budgets are disabled, not deleted; the QBit never deletes either)

Each changeset first records parent-less rows in qqq_fk_quarantine and nulls
them (or, for the NOT NULL run_id columns, copies the row as JSON and deletes
it, PostgreSQL only), and is marked ran when the constraint already exists.
Changeset 12 indexes the foreign key columns that had no leading index.

WebPerfForeignKeyTest runs the changelog with Liquibase on PostgreSQL
(Testcontainers), checks the orphan path and re-run idempotency, and fails
when a table reference in the meta-data has no constraint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:16:35 -05:00