docs: document CHECK-on-renamed-column limitation, drop from TODO#98
Conversation
The TODO entry framed this as a fixable bug, but probing MySQL's actual behaviour revealed that: - `RENAME COLUMN` with an active CHECK constraint that references the column always errors with `Error 3959`. - There is no MySQL-side bypass — `SET foreign_key_checks=0` doesn't apply (CHECK and FK are unrelated), and even a `DROP CHECK → RENAME COLUMN → ADD CHECK (old_name …)` sequence is rejected with `Error 1054 Unknown column` on the re-add. MySQL itself does not auto-rewrite CHECK bodies on rename. So the user always has to spell out the new column name in the new CHECK body regardless of what myschema does. The remaining question was whether myschema should also drop the CHECK before emitting the RENAME, and whether to auto-rewrite the catalog side's CHECK body so the diff doesn't even fire DROP+ADD. Decision: do neither. The expression-rewrite path would require parsing every CHECK body through vitess and walking the AST, which isn't justified by how rare the column-rename-with-CHECK case is in practice. The user's manual `DROP CHECK` step (or a `-- myschema:execute` block) is a minute of work. CAVEATS.md gets a new "Renaming a column referenced by a CHECK constraint" section explaining the rule, the workaround, and the rationale. The TODO entry is removed since the limitation is now part of the documented contract, not a deferred fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #98 +/- ##
=======================================
Coverage 86.96% 86.96%
=======================================
Files 30 30
Lines 3321 3321
=======================================
Hits 2888 2888
Misses 266 266
Partials 167 167 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR updates project documentation to reflect a MySQL limitation around renaming columns referenced by CHECK constraints, and removes a corresponding “TODO” item now considered an accepted limitation/contract.
Changes:
- Document MySQL’s behavior/error when renaming a column referenced by an active CHECK constraint, plus rationale for not auto-fixing in myschema.
- Add a documented workaround section for users.
- Remove the related TODO entry now that the limitation is documented.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
CAVEATS.md |
Adds a new caveat section explaining CHECK+RENAME behavior and a proposed workaround. |
TODO.md |
Removes the TODO item related to CHECK constraints blocking column renames. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Three valid corrections on the new CAVEATS section: - Execute groups run AFTER all other DDL buckets, not before (verified: diff_all.go:97 — "blocks run after every other DDL bucket"). My example told users to wrap the DROP CHECK in `-- myschema:execute`, which would actually fire AFTER the failing RENAME COLUMN — exactly backwards. - The check-SQL semantics in the example were also inverted: myschema treats 1+ rows as "already applied, skip" and 0 rows as "not applied yet, run." For a DROP, my example returned rows when the CHECK existed (so the DROP would skip when it should run, and try to drop again after the CHECK is gone). Both errors disappear by recommending a genuinely out-of-band pre-step instead. Rewrite the workaround to: run the DROP CHECK by hand against the live database, then run `myschema apply`. The diff then sees catalog has no CHECK and emits a clean RENAME + ADD CHECK pair, both of which succeed. Add an explicit "don't reach for `-- myschema:execute` here" paragraph that spells out why the directive can't help. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Use the full `ADD CONSTRAINT chk_x CHECK (old_name …)` form in the inline narrative for consistency with the actual MySQL DDL syntax used elsewhere (the previous shorthand `ADD CHECK (...)` looked like literal DDL but isn't valid). - PR description still recommended the `-- myschema:execute` workaround that the doc had since reverted; updated the PR body so the recommendation matches what CAVEATS now says (out-of-band manual `DROP CHECK` against the live database). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Four valid catches: - CAVEATS plan example always showed `DROP CHECK`, but diffConstraints suppresses CHECK drops unless `--allow-drop=constraint` (or `=all`) is set. Document both shapes: with allow-drop the user sees the three-statement plan; without it, only the failing RENAME COLUMN plus a `-- skipped:` line. The MySQL Error 3959 is the same either way. - Replace the Unicode circled `①` annotation in the SQL example with a plain ASCII `-- fails here`. The fancy character hurts copy/paste into terminals and grep over logs. - Spelling: "dropped-then-readded" → "dropped-then-re-added" to match the "re-add" usage earlier in the same section. - testdata/apply/inline_rename_all_kinds.yml's caveat comment still pointed at the deleted TODO entry. Update the pointer to "CAVEATS.md 'Renaming a column referenced by a CHECK constraint'" so the cross-reference doesn't go stale. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The previous round added an inaccurate "without allow-drop the DROP gets suppressed" branch to the CAVEATS section. Verified against the actual implementation: - diffConstraints suppresses a DROP only on the `!ok` branch — i.e. when the constraint is being removed entirely from desired. - For the bug scenario (same name `chk_x`, different body because it references the renamed column) the constraint is present on both sides, so `ok=true`, the suppression logic doesn't apply, and DROP+ADD fires regardless of allow-drop. Probed: `myschema plan` with and without --allow-drop=constraint produced byte-identical output for the rename-with-CHECK case. Drop the two-shape narrative and replace it with a single correct description: the three-statement plan above is what every user sees, and apply fails at line 1 with Error 3959. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
The "CHECK constraint referencing a renamed column blocks the rename" TODO was framed as a fixable diff-layer bug. Probing MySQL's actual behaviour shows the constraint is harder than it looked:
So the user always has to spell out the new column name in the new CHECK body, regardless of what myschema does. The only remaining question was whether myschema should auto-rewrite the catalog-side CHECK definition (so the diff doesn't fire DROP+ADD at all) and reorder the buckets so DROP CHECK runs before RENAME COLUMN.
Decision: don't fix in code. The auto-rewrite would parse every CHECK body through vitess and walk the AST — significant code that isn't justified by how rare the case is. The user's manual `DROP CHECK` step is a minute of work.
Changes
Test plan
🤖 Generated with Claude Code