fix: order function recreation after dependent view recreation (#480)#488
Conversation
When a function's RETURNS/parameter type references a view that must be recreated (DROP + CREATE) and the function's signature also changes, the function was being recreated in the create phase — before the view's DROP in the modify phase. The freshly-created function re-pinned the old view, so the subsequent DROP VIEW ... RESTRICT failed with SQLSTATE 2BP01. The function's DROP already runs in the drop phase, so deferring its CREATE to the modify phase (after generateModifyViewsSQL recreates the view) leaves the view free of dependents during its RESTRICT drop. Added functions whose type references a view with RequiresRecreate are pulled out of the create phase into functionsAwaitingRecreatedViews and emitted after view recreation. Fixes #480 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes an apply dependency-ordering failure when a function’s return/parameter type references a view that must be recreated (DROP+CREATE), by deferring creation of such functions until after the view recreation step in the modify phase.
Changes:
- Track views being recreated (
RequiresRecreate) and defer added functions whose signature references those view composite types. - Emit these deferred functions after
generateModifyViewsSQLrecreates the views (issue #480). - Add a regression test case under
testdata/diff/dependency/issue_480_view_function_recreate/asserting correct DDL order across plan outputs.
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/diff.go | Defers function creation until after recreated views are dropped/recreated; adds recreated-view lookup helper. |
| testdata/diff/dependency/issue_480_view_function_recreate/plan.txt | Golden plan text showing corrected DDL ordering. |
| testdata/diff/dependency/issue_480_view_function_recreate/plan.sql | Golden plan SQL showing corrected DDL ordering. |
| testdata/diff/dependency/issue_480_view_function_recreate/plan.json | Golden plan JSON capturing the corrected step ordering. |
| testdata/diff/dependency/issue_480_view_function_recreate/old.sql | Repro old-state schema (table → view → function). |
| testdata/diff/dependency/issue_480_view_function_recreate/new.sql | Repro new-state schema that forces view recreation and function signature change. |
| testdata/diff/dependency/issue_480_view_function_recreate/diff.sql | Golden diff SQL reflecting the intended execution order. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Greptile SummaryThis PR fixes a dependency-ordering bug (#480) where
Confidence Score: 5/5Safe to merge. The change is a targeted fix to function-deferral ordering that follows the existing pattern exactly, and the test case directly reproduces the previously-failing scenario end-to-end. The new No files require special attention. Important Files Changed
Reviews (1): Last reviewed commit: "fix: order function recreation after dep..." | Re-trigger Greptile |
Address review feedback: the functionsAwaitingRecreatedViews bucket can also hold genuinely new functions (no old definition), so qualify the "old definition dropped in the drop phase" reasoning to signature-changed functions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Fixes a dependency-ordering bug where
applyfails withcannot drop view ... because other objects depend on it (SQLSTATE 2BP01).When a function's
RETURNS/parameter type references a view, the function depends on that view's composite rowtype. If both the view must be recreated (DROP+CREATE, e.g. a column added mid-list) and the function's signature changes (so it's a drop+add rather than an in-placeCREATE OR REPLACE), pgschema emitted the operations in this order:The function's
DROPalready runs in the drop phase, but itsCREATEran in the create phase — before the view'sDROP— re-pinning the old view and blocking theRESTRICTdrop.Fix
The existing function-deferral logic only considered newly added views (
buildViewLookup(d.addedViews)). This adds the same handling for views being recreated (modifiedViewswithRequiresRecreate): added functions whose type references such a view are pulled out of the create phase intofunctionsAwaitingRecreatedViewsand emitted in the modify phase, aftergenerateModifyViewsSQLrecreates the view.Resulting order (now applies cleanly):
Test plan
Added
testdata/diff/dependency/issue_480_view_function_recreate/(the issue's exact reproduction:table <- view <- function, adding arolecolumn).internal/diffTestDiffFromFiles— asserts the corrected DDL ordering.cmdTestPlanAndApply— applies the migration end-to-end against embedded PostgreSQL, proving the new order is valid (previously failed with 2BP01).Both green; full suite runs in CI.
🤖 Generated with Claude Code