Repository navigation
statement: refuse accepted-blocking DROP INDEX ... CASCADE - #189
Conversation
CASCADE drops dependents on tables the acknowledgement never named.
…blocking-cascade * origin/main: planner: let the server prove whether adding a column rewrites the table (#181) migrate: run a copy-and-swap routed statement to one verdict (#183) docs: record the moved-image completion loss in CO-4's open window (#194) preflight, executor: name the routing class on every typed cause (#192) schemachange, checkpoint: fail a pinned-key test without a hang (#190) schemachange: type the shadow-gone resume refusal and say whether a swap proof was made (#174) schemadiff: adopt a live unique index for a new key constraint (#180) schemadiff: plan against the target schema's own types and functions (#179) planner: refuse dropping what the replica identity index keys on (#178) schemadiff: model column-owned sequence declarations (#177) schemadiff: model table storage parameters and refuse a mismatch (#176) refusal: name the routing class of the copier and shadow-operation refusal causes (#173) schemachange: run a table under writes through the Runner (#171) migrate: test that an apply leaves the table as a fresh build of the file would (#175) # Conflicts: # docs/capabilities.md # pkg/capabilities/capabilities.yaml
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
🤖 Review 1/2 (adversarial correctness) of 9b60ce2: 0 blocking, 2 non-blocking. I read the whole diff against Invariants. AB-3 is extended (the scope rule is added and its Enforced: line now names Non-blocking1.
|
| Mutant | Caught by |
|---|---|
ParseOne ignores cascade (len(objects) == 1 only) |
TestParseOneKinds, TestAcceptedRefusal, TestGate, TestAcceptedBlockingAdmission, TestMigrateAcceptBlockingLeavesIneligibleRefusalsAlone, and the end-to-end TestMigrateAcceptBlockingRefusesCascadeAndKeepsDependentForeignKey (the cascade then ran) |
cascades never set |
TestParseOneKinds, TestAcceptedRefusal, TestGate, TestAcceptedBlockingAdmission, CLI ineligible-refusal test |
acceptedBlockingShape admits every drop and reindex |
TestAcceptedBlockingAdmission (cascade, multi-index and REINDEX SCHEMA rows), TestExecuteAcceptedBlockingRefusesCascadeDrop (the cascade ran and the foreign key was dropped) |
gateRefusal ignores the target (always the eligible site) |
TestAcceptedRefusal, TestGate, TestAcceptedBlockingEligibleRowsArePinned, TestIndexStatementAcceptedBlockingEligibility, TestGateVerdictAcceptedBlockingEligibility, CLI ineligible-refusal test |
cascade branch removed from indexAdvice |
TestGate (the concurrent safer idiom is suggested) |
Every production change in the diff has at least one killing test, and both layers (gate and executor shape check) are independently pinned.
- Reach:
Gateruns beforeForcein bothmigrate.Run(migrate.go#L219) and the CLI front door, and I found no other route from an operator-supplied statement to execution.ParseOps(thediff/planner classifier) does not read the drop behavior, so a library caller that classifies a cascading drop there and rewrites it concurrently gets a server error (the statement in item 1), not an execution. - Docs: README, capabilities (
.mdand.yaml), plan-report, refusal-classes, the passthrough design doc, the--accept-blockinghelp text, and AB-3/AB-4 all say the same thing as the code.
This review was generated by Claude Code (claude-sonnet-5-5).
|
🤖 Review 2/2 (OSS adoption, integration ease for importers) of 9b60ce2: 0 blocking, 3 non-blocking. Lens check for Non-blocking1.
|
aparajon
left a comment
There was a problem hiding this comment.
🤖 Stamping with comments: 0 blocking, 5 non-blocking (2 in review 1/2, 3 in review 2/2; see the two review comments above).
This stamp was left by Claude Code (claude-sonnet-5-5).
Review fixes: a DROP INDEX CONCURRENTLY that PostgreSQL rejects (CASCADE or several indexes) is refused by-design, not sent to a direct run; the cascade refusal names the retry without CASCADE; executor shape refusals say why; plain and RESTRICT drops of a referenced index are pinned as server-refused.
|
🤖 Review response — created by Kiran's code review agent (Amp, Claude Opus 4.6) — pull/189, follow-up commit Verdict: all 5 non-blocking findings fixed in a follow-up commit that also merges
The concurrent-form detail also drops "yet", since these rows are T3 with no roadmap item (raised on #188). Source: block/pg-sprite#189, review comments 6230051382 and 6230051890 and review 5556373128 at head |
…blocking-cascade * origin/main: capabilities: mark rows migrate refuses as refused (#188) fix(migrate): report a desired-state run executed only when a fresh plan is empty (#217) feat(migrate): refresh column statistics after a native type change (#198) planner: carry every attribute of a primary key or unique constraint into its online sequence (#197) # Conflicts: # docs/capabilities.md # pkg/capabilities/capabilities.yaml
migrate --accept-blockingnow refusesDROP INDEX ... CASCADE, so the one table the operator acknowledges is the only table the statement touches.Why
--accept-blocking <table>acknowledges one table's lock, butDROP INDEX ... CASCADEalso drops whatever depends on the index — a foreign key on another table, for instance — locking and changing a table the operator never named (AB-3, AB-4). Neither the gate nor the executor's shape check looked at the drop behaviour, so the cascading form was admitted.What
DROP INDEXas a scope wider than one relation (IndexTargetOther), and recordsCascades(). The gate then files it at the existing ineligibleindex-statement-othersite, and the executor's shape check, which already requires a single relation, refuses it too.RESTRICTdrops stay eligible.DROP INDEX CONCURRENTLY, which PostgreSQL rejects withCASCADE; it says to drop the dependents explicitly first.--accept-blockinghelp updated (upholds AB-3, AB-4).Before / after
ordershas a foreign key on the unique indexusers_email_keyofusers, and the operator acknowledges onlyusers. Before, the drop ran and took the foreign key onorderswith it; after, it is refused and nothing changes.