Skip to content

Check foreign keys once per build and per watch batch - #1543

Merged
thekevinbot merged 7 commits into
mainfrom
bot/1541-defer-fk-1019
Oct 20, 2026
Merged

thekevinbot merged 7 commits into
mainfrom
bot/1541-defer-fk-1019

Conversation

@thekevinbot

@thekevinbot thekevinbot commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1541

Declared foreign keys are checked once per unit of work instead of per row.

  • Build: the build transaction sets PRAGMA defer_foreign_keys = ON, so tables can fill in any order. An orphan at commit fails the build with a message naming the table, the producing file and the unmatched values (from pragma_foreign_key_check), not a bare FOREIGN KEY constraint failed.
  • Watch: each batch's refreshes across all tables run in one deferred-FK transaction (per-operation transactions became savepoints). A batch that leaves an orphan is rolled back and reported as one error event; the database stays at its previous state.
  • No wedge: a rejected batch's events are held and replayed, restated as each path stands now, with every later batch, so it lands with the batch that resolves the orphan. If held plus new still fails, the new batch is tried alone so unrelated changes land.
  • Docs: docs/reference/config.md "Foreign keys".

Not deferred, and out of scope: ON DELETE/ON UPDATE actions. A changed file is applied as delete plus insert, so ON DELETE CASCADE deletes the children of an edited parent. This is documented.

E2E Verification

  • Ran e2e suites locally for every affected SDK
  • Python SDK e2e: pass (affected subset, 20 passed)
  • TypeScript SDK e2e: pass (18 passed)
  • Rust core e2e (if applicable): pass (cargo test --workspace --features cli)
  • packages/python/e2e-attestations/<branch>.json receipt written if packages/python changed (just e2e-attest-python)
  • packages/ts/e2e-attestations/<branch>.json receipt written if packages/ts changed (just e2e-attest-ts)
  • Command(s) run: uv run maturin develop --release; cargo build --release -p dirsql --features cli; cd packages/python && testing-conventions e2e attest 'uv run python -m pytest tests/e2e/on_file_query_test.py tests/e2e/use_case_join_test.py tests/e2e/fanout_test.py tests/e2e/query_contract_test.py tests/e2e/declared_table_name_test.py tests/e2e/watch_speed_test.py tests/e2e/server_speed_test.py -x -q'; cd packages/ts && testing-conventions e2e attest 'pnpm test:e2e'; cargo test --workspace --features cli
  • Result summary: all pass. By hand: an FK repro config built 20/20 times (it failed at random before). In dirsql --watch, editing a referenced parent now applies; deleting a referenced parent gives a named error and keeps the previous state; the held deletion landed once the orphaned children were removed.

Changelog / Migrations

  • Changelog fragment added under packages/rust/changelog.d/ for each changed package
  • Migration fragment with the same slug added under packages/rust/migrations.d/ for each changed package

@thekevinbot
thekevinbot marked this pull request as ready for review October 19, 2026 11:36
@thekevinbot
thekevinbot merged commit e3b363d into main Oct 20, 2026
90 checks passed
@thekevinbot
thekevinbot deleted the bot/1541-defer-fk-1019 branch October 20, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Declared foreign keys fail builds at random and wedge watch mode

1 participant