Repository navigation
Conversation
CASCADE on DROP COLUMN, DROP CONSTRAINT, or DROP INDEX also drops whatever depends on the target: a view that reads the column, or another table's foreign key on a dropped primary key. Those objects are not in the statement, so the plan cannot show them and the one-table lock does not cover them. The ALTER TABLE forms were classified as plain metadata-only drops and ran natively. The planner now refuses every such drop with the new cascading-drop reason, read from the statement alone, so lint reports it too. The migrate verdict tells the operator to drop each dependent object explicitly and resubmit without CASCADE, which PostgreSQL then refuses while anything still depends on the target. DROP INDEX ... CASCADE no longer gets a DROP INDEX CONCURRENTLY ... CASCADE suggestion, which the server rejects. The plan report moves to format_version 11 and the lint report to 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The demo’s lint assertion still expects version 4 instead of 5, causing the smoke check to fail.
1 open issue
What changed in this PR
Adds planner refusals for cascading drops, preventing implicit removal of dependent objects outside the statement’s scope.
Changes:
- Detects
CASCADEon column, constraint, and index drops and reportscascading-drop. - Adds refusal coverage and operator guidance.
- Bumps plan and lint report versions and updates documentation.
| File | Description |
|---|---|
| pkg/statement/ops.go | Records cascading drop behavior. |
| pkg/statement/ops_test.go | Tests cascade parsing. |
| pkg/planner/planner.go | Adds cascading-drop refusal. |
| pkg/planner/planner_test.go | Tests refusal and unchanged restrictions. |
| pkg/plan/plan.go | Bumps report version to 11. |
| pkg/plan/plan_test.go | Updates contract assertions. |
| pkg/migrate/verdicts.go | Adds refusal guidance. |
| pkg/migrate/dependent_view_integration_test.go | Removes obsolete cascade acceptance case. |
| pkg/migrate/cascading_drop_integration_test.go | Checks refusal preserves dependent objects. |
| pkg/lint/lint.go | Bumps report version to 5. |
| pkg/lint/lint_test.go | Updates contract assertions. |
| pkg/capabilities/capabilities.yaml | Records cascade restrictions. |
| internal/cli/dryrun_text.go | Explains cascading-drop impact. |
| docs/postgres-online-ddl-reference.md | Documents the new refusal. |
| docs/plan-report.md | Updates reason vocabulary and version. |
| docs/optimistic-attempt.md | Marks cascading drops as refused. |
| docs/lint-report.md | Documents lint contract changes. |
| docs/limitations.md | Explains cascade limitations. |
| docs/cli-output-examples.md | Updates report versions. |
| docs/capabilities.md | Updates drop capabilities. |
| demo/tour.sh | Updates plan-version smoke assertions. |
Review effort: Balanced
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
🤖 Copilot's review raised one issue, the demo's lint Addressed by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why
CASCADEon a drop also drops whatever depends on the target: a view that reads a dropped column, or another table's foreign key on a dropped primary key. Those objects are not named in the statement, so the plan cannot show them, and dropping another table's foreign key locks that table, which pg-sprite's one-table lock does not cover.Only
DROP INDEX ... CASCADEwas caught (#189). TheALTER TABLEforms were classified as ordinary metadata-only drops andmigrateran them natively.What
The planner refuses every
DROP COLUMN,DROP CONSTRAINT, orDROP INDEXwithCASCADEunder a newcascading-dropreason. The refusal is read from the statement alone, solintandplanreport it as well asmigrate. Themigrateverdict tells the operator to drop each dependent object explicitly, then resubmit withoutCASCADE; PostgreSQL then refuses the drop while anything still depends on the target.lintused to suggestDROP INDEX CONCURRENTLY i CASCADEforDROP INDEX i CASCADE, which PostgreSQL rejects. That drop is now refused with no suggestion.usershas a primary key thatorders.user_idreferences, and the operator submitsALTER TABLE users DROP CONSTRAINT users_pkey CASCADEthroughmigrate.The plan report moves to
format_version11 and the lint report to 5, since the reason vocabulary is part of both contracts. #223's carve-out that letDROP COLUMN ... CASCADEthrough as a destructive drop is gone: that drop is now refused here instead.Testing
TestRunRefusesACascadingDropruns bothALTER TABLEforms throughmigrateagainst PostgreSQL and checks that the column, the primary key, the view, and the other table's foreign key all survive. With the planner refusal removed, theDROP CONSTRAINTcase executes and drops the foreign key.TestClassifyRefusesACascadingDropcovers every drop form with and without live facts, multi-indexDROP INDEX,IF EXISTS, a multi-commandALTER TABLE, and thatRESTRICTstill classifies as before.Stacked on #223.
🤖 Generated with Claude Code