Skip to content

fix: order modified foreign keys after added unique constraints#475

Open
meesvandongen wants to merge 1 commit into
pgplex:mainfrom
meesvandongen:main
Open

fix: order modified foreign keys after added unique constraints#475
meesvandongen wants to merge 1 commit into
pgplex:mainfrom
meesvandongen:main

Conversation

@meesvandongen

Copy link
Copy Markdown

When a migration adds a new UNIQUE/PRIMARY KEY constraint and also modifies an existing foreign key to reference it, the foreign key can be recreated before the referenced constraint exists.

This change updates modified-table dependency ordering so modified foreign keys are applied after newly added referenced UNIQUE/PRIMARY KEY constraints.

Copilot AI review requested due to automatic review settings June 12, 2026 12:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds regression coverage and updates dependency ordering to ensure tables that add UNIQUE/PK constraints are processed before tables whose modified foreign keys reference them.

Changes:

  • Extend topologicallySortModifiedTables to treat modified FKs as dependencies on newly added UNIQUE/PK constraints.
  • Add a unit test covering “modified FK depends on added UNIQUE” ordering.
  • Add new testdata fixtures (old/new schema + diff/plan outputs) for two related dependency scenarios.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/plan.txt Adds expected human-readable plan output fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/plan.sql Adds expected SQL plan fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/plan.json Adds expected JSON plan fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/old.sql Adds “before” schema fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/new.sql Adds “after” schema fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique_reverse_order/diff.sql Adds expected diff SQL fixture for reverse-order scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/plan.txt Adds expected human-readable plan output fixture for non-prefixed tables scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/plan.sql Adds expected SQL plan fixture for non-prefixed tables scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/plan.json Adds expected JSON plan fixture for non-prefixed tables scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/old.sql Adds “before” schema fixture for non-prefixed tables scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/new.sql Adds “after” schema fixture for non-prefixed tables scenario.
testdata/diff/dependency/issue_modified_fk_to_new_unique/diff.sql Adds expected diff SQL fixture for non-prefixed tables scenario.
internal/diff/topological_test.go Adds regression test for ordering modified FK table after referenced table with newly added UNIQUE.
internal/diff/topological.go Updates modified-table topological sort to consider dependencies from modified foreign keys.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +581 to +583
for _, constraintDiff := range tdA.ModifiedConstraints {
processFKDependency(constraintDiff.New)
}
Comment on lines +515 to +517
// topologicallySortModifiedTables sorts modified tables based on constraint dependencies.
// Tables with added UNIQUE/PK constraints that are referenced by other tables' added OR
// modified FKs will come before those tables.
@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown

Greptile Summary

This PR updates modified-table dependency ordering for foreign keys that target newly added keys. The main changes are:

  • Modified foreign keys now participate in table ordering dependencies.
  • Added UNIQUE and PRIMARY KEY constraints are ordered before dependent modified FKs.
  • New regression fixtures cover same-order composite FK updates in normal and reverse table-name order.

Confidence Score: 3/5

This is close, but the ordering fix still misses a valid composite foreign key case.

  • Same-order FK references are now handled.

  • Reverse-order composite references can still skip the dependency edge.

  • That can leave the migration ordering failure in place for valid PostgreSQL schemas.

  • internal/diff/topological.go should match FK referenced columns using the same column-set semantics as the existing FK recreation planner.

Important Files Changed

Filename Overview
internal/diff/topological.go Extends modified-table ordering to inspect modified foreign key definitions.
internal/diff/topological_test.go Adds unit coverage for a modified FK referencing a newly added UNIQUE constraint.

Reviews (1): Last reviewed commit: "fix: order modified foreign keys after a..." | Re-trigger Greptile

Comment on lines 569 to 573
if constraintMatchesFKReference(constraint, fkConstraint) {
// Add edge: tableB (with new UNIQUE/PK) -> tableA (with new FK)
adjList[keyB] = append(adjList[keyB], keyA)
inDegree[keyA]++
break
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Match referenced column sets

This still only adds the dependency edge when the referenced column order exactly matches the new UNIQUE/PK order. PostgreSQL allows a composite FK such as REFERENCES parent (b, a) to use UNIQUE (a, b), and the existing FK recreation planner already treats this as an unordered column set. When a modified FK references the newly added key in the opposite order, constraintMatchesFKReference returns false, so the dependent table can still be ordered before the referenced table and the migration can fail before the unique constraint exists.

Suggested change
if constraintMatchesFKReference(constraint, fkConstraint) {
// Add edge: tableB (with new UNIQUE/PK) -> tableA (with new FK)
adjList[keyB] = append(adjList[keyB], keyA)
inDegree[keyA]++
break
return
}
if fkReferencesAnyConstraint(fkConstraint, []*ir.Constraint{constraint}) {
adjList[keyB] = append(adjList[keyB], keyA)
inDegree[keyA]++
return
}

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.

2 participants