Skip to content

D1: auto-migrate referenced-table rebuilds via FK cascade (follow-up to #226) #241

Description

@dmealing

Follow-up to #226. That issue is being fixed by detect-and-refuse: meta migrate --dialect d1 now throws a clear generation-time error instead of silently emitting a migration that fails against production when it would rebuild a foreign-key-referenced table (design: docs/superpowers/specs/2026-07-27-d1-referenced-table-rebuild-refuse-design.md).

This issue tracks the deferred auto-fix: instead of refusing, generate a cascade that actually applies on remote D1.

What was prototyped (Appendix A of the #226 design)

A cascade works, validated against libSQL modelling remote D1 (batch in one implicit transaction, foreign_keys=ON):

  • rebuild each referencing child without its FK -> rebuild the parent -> restore the children's FKs, all in one pass;
  • defer_foreign_keys=ON as a belt; temp tables reference each other's temp names (SQLite resolves FK targets lazily) and RENAME rewrites them to final names;
  • two load-bearing ordering rules: referrers-first DROP, parents-first RENAME.

Validated for single-parent, transitive (g→c→p), multi-child, and self-referential graphs — data intact, FKs re-enforced.

Why it was deferred

Disproportionate for a niche dialect's edge case: needs a reverse FK-graph + topological sort + self-ref special-casing, and multi-table cycles (A↔B) have no reliable atomic sequence and would still need refusing. Detect-and-refuse removes the dangerous (silent, production) behavior at ~10% of the cost.

If picked up

  • Build the reverse FK-graph + topological order over the affected set (recreate set ∪ transitive referrers).
  • Emit the validated cascade; keep refusing genuine multi-table cycles.
  • Gate the migrate-doctrine way: emit → apply to a real engine (libSQL, batch-in-one-transaction to model remote D1) → re-diff EMPTY, per topology.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions