fix: defer new table inline FK when it depends on a new unique constraint (#506)#507
Conversation
…aint (#506) When a new table's inline FK references columns on a pre-existing table that is gaining a UNIQUE or PK constraint (or unique index) in the same migration, the CREATE TABLE was emitted before the constraint it depends on, causing SQLSTATE 42830. Extend planFKRecreationForReplacedConstraints to also detect newly-added UNIQUE/PK constraints and unique indexes on modified tables, suppressing the FK from inline CREATE TABLE and deferring it to after the modify phase. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes an ordering bug in incremental migrations where a new table’s inline foreign key can be emitted before the new UNIQUE/PK constraint or unique index it depends on (triggering SQLSTATE 42830). It extends FK deferral logic so such FKs are suppressed from CREATE TABLE and instead emitted later via deferred constraint creation.
Changes:
- Detect newly-added UNIQUE/PK constraints on modified (pre-existing) tables and defer new-table inline FKs that depend on them.
- Also detect newly-added unique indexes on modified tables and defer dependent new-table inline FKs.
- Add a regression fixture for the table-constraint variant of issue #506.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/diff/table.go | Extends FK deferral planning to consider newly-added unique constraints and unique indexes; adds helper for FK↔unique-index matching. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/plan.txt | New expected human-readable plan output for the regression case. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/plan.sql | New expected SQL plan output for the regression case. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/plan.json | New expected JSON plan output for the regression case. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/old.sql | Old-state fixture: parent table without the needed uniqueness. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/new.sql | Desired-state fixture: parent gains uniqueness; child table references it. |
| testdata/diff/create_table/issue_506_fk_depends_on_new_unique/diff.sql | New expected diff output for the regression case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Re-checked the current head with green CI. Verdict: ready to merge. Greptile's remaining note is about follow-up coverage, not a blocker for this fix:
So from the reviewer side I would merge this as-is, and only add a separate fixture for the unique-index variant later if we want to harden that path further. |
Address Greptile/Copilot review feedback: - Filter out partial indexes (IsPartial) from addedUniqueIndexes - Expand test fixture to cover both variants: UNIQUE constraint and CREATE UNIQUE INDEX Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
CREATE TABLEwas emitted before the constraint it depends on (SQLSTATE 42830)planFKRecreationForReplacedConstraintsto also detect newly-added UNIQUE/PK constraints and unique indexes on modified tables (not just replaced ones)CREATE TABLEand deferred to after the modify phase viafkPostAddsfkReferencesAnyUniqueIndexhelper for variant 2 (unique expressed asCREATE UNIQUE INDEXinstead of table constraint)Test plan
create_table/issue_506_fk_depends_on_new_uniquetest fixture (variant 1: unique as table constraint)Closes #506
🤖 Generated with Claude Code