Repository navigation
migrate: refuse a destructive statement unless --allow-destructive names the table - #253
Conversation
…mes the table migrate --alter ran DROP COLUMN, DROP CONSTRAINT and DROP NOT NULL as written, with only a warning, so a standalone CLI user could discard data by accident. They are now refused with destructive-change on every route and in a dry run until a typed acknowledgement names the table, and a drop that re-adds the same column gets guidance to retype it in place. RF-10 records the rule.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
🤖 Adversarial correctness review performed by Jash's AI agent. Reviewed the PR delta at head Verdict: no correctness defect found in the reviewed delta; full verification remains incomplete. The destructive gate precedes the extracted dispatch, so native, forced, and copy-and-swap routes share it. A matching acknowledgement lifts only this gate; planner refusals and the other route policies remain separate. Findings1. (Optional coverage) Exercise schema resolution through the real front doors. The unqualified-name case in Action items
VerifiedThe changed code checks a supplied acknowledgement before routing, derives destructiveness from routed decisions, audits before dispatch, and attaches Exact-head surrounding-source and inline-comment API reads failed with connection errors; I obtained no checkout and ran no local build/tests. I therefore could not independently inspect the resolver, planner's existing destructive classification, complete dispatch, or inline discussions. These limits prevent an unconditional verification claim. This review was generated by Codex (GPT-6.1 Sol). |
|
🤖 Product review at OSS adoption ease: The default now protects standalone CLI users from accidental drops, and the refusal provides the exact table acknowledgement. Drop/re-add guidance offers a useful safer path. The README, exit-code examples, and demo distinguish the refused verdict from an acknowledged dry-run plan, which matters for scripts consuming JSON. SchemaBot integration: This is a behavior change for existing This review was generated by Codex (GPT-6.1 Sol). |
#248 merged first with plan format 13 and suggest format 4 for coordinated-constraint-rename, so alter-column-type-in-place moves to plan 14 and suggest 5. Both guidance codes are kept.
Two schemas hold the same table: the acknowledgement must name the one the session's search_path resolves, for the dry run and the apply alike.
|
🤖 Adversarial review response — created by Kiran's code review agent (Amp, Claude Opus 4.6) — pull/253, follow-up commit The optional coverage finding is fixed with a front-door regression test; the product review's release note is updated for the version clash with #248, and its SchemaBot adapter step is tracked as an internal follow-up.
Source: block/pg-sprite#253, review comments 6391751905 and 6391753175 and review 5640880653 at head |
#259 added RF-11 beside this branch's RF-10; both invariants are kept in order.
Keeps both verdict text lines where they met: this branch's blocked: line and main's allowed: line (#253), in the CLI renderer and in verdict.String.
migrate --alternow refuses any statement that drops a column, a constraint or aNOT NULLunless--allow-destructive SCHEMA.TABLEnames the table, so data can no longer be discarded by accident.Why
pg-sprite should make it very hard to make, by accident, a change that loses data or leaves a table unreadable or unwritable. The declarative path already refuses destructive plans, and lock risk already needs
--forceor--accept-blocking. The imperative path did not:migrate --alter "ALTER TABLE orders DROP COLUMN note"ran as written, with adestructive: truewarning and exit 0. That protects SchemaBot users, whose--allow-unsafegates the flag, but not anyone running the CLI on its own. A drop followed by a re-add of the same column was the sharpest case: most people who write it want to change the column's type, and instead lose every value in it.What
migrate.Runrefuses a statement whose plan contains a destructive operation (DROP COLUMN,DROP CONSTRAINT,DROP NOT NULL). The refusal isdestructive-change, classby-design, the same contract the declarative path uses.--dry-run. Nothing executes.replica-identity,dependent-vieworcascading-dropkeeps its own reason.DROP INDEXstays with the statement-kind gate and--accept-blocking.--allow-destructive SCHEMA.TABLE(Options.AllowDestructive) must name the resolved table, like--force; a mismatch isErrAllowDestructiveMismatchand nothing executes.--force,--dry-runand--restart. It is refused with--accept-blockingand byRunDesired.allowed_destructive: true.alter-column-type-in-place, which points toALTER COLUMN ... TYPE ... USING ...as the way to keep the values. The new code bumpsplan.FormatVersionfrom 13 to 14 andsuggest.FormatVersionfrom 4 to 5.design-principles.mdnow covers the imperative path.schemabot-integration.mdnow says to map SchemaBot's unsafe acknowledgement toOptions.AllowDestructive.Before / after
The same statement,
ALTER TABLE orders DROP COLUMN qty, ADD COLUMN qty bigint, run by a CLI user who meant to widenqty:Upgrade note
This changes behaviour for existing callers. An imperative
DROP COLUMN,DROP CONSTRAINTorDROP NOT NULLthat used to execute is now refused, with exit code 2, until the acknowledgement is passed. An adapter should passOptions.AllowDestructiveonly for a change the operator approved.References
plan.FormatVersion13 andsuggest.FormatVersion4 forcoordinated-constraint-rename, so this PR now carries 14 and 5. diff: report an index left invalid by an unfinished build as an advisory #249 bumps the plan version too; whichever of the two merges second takes the next number.🤖 Generated with Amp (Claude Opus 4.6)