Skip to content

TODO: record empty-string DEFAULT round-trip drift#32

Merged
winebarrel merged 5 commits into
mainfrom
add-empty-default-todo
May 2, 2026
Merged

TODO: record empty-string DEFAULT round-trip drift#32
winebarrel merged 5 commits into
mainfrom
add-empty-default-todo

Conversation

@winebarrel

Copy link
Copy Markdown
Owner

Summary

File the catalog default-normalisation bug surfaced in PR #31's evolution scenario.

A column declared with NOT NULL DEFAULT '' apply-loops:

  • catalog reads COLUMN_DEFAULT as the bareword empty string
  • catalog.normalizeColumnDefault only wraps non-empty barewords for ENUM / SET / CHAR / temporal types
  • parser side stores '' (quoted)

So they never compare equal and every post-apply plan re-emits MODIFY COLUMN … DEFAULT ''.

Filed under "High — correctness bugs" because it produces a permanent drift loop that doesn't self-resolve.

Test plan

  • No code change

🤖 Generated with Claude Code

A column declared with `NOT NULL DEFAULT ''` apply-loops because the
catalog reads it back as a bareword empty string and the default
normaliser doesn't wrap it the way it wraps non-empty barewords for
ENUM / SET / CHAR / temporal types. Parser stores `''` (quoted), so
they never compare equal and every post-apply plan re-emits
`MODIFY COLUMN … DEFAULT ''`.

Surfaced while writing the evolution scenario in PR #31; worked
around there by dropping the explicit DEFAULT. Filed under
"High — correctness bugs" because it produces a permanent drift loop
that doesn't self-resolve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 2, 2026 15:40
@codecov

codecov Bot commented May 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.37%. Comparing base (aa4438f) to head (1096bd2).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #32   +/-   ##
=======================================
  Coverage   73.37%   73.37%           
=======================================
  Files          27       27           
  Lines        2141     2141           
=======================================
  Hits         1571     1571           
  Misses        410      410           
  Partials      160      160           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a high-priority TODO item documenting an empty-string column default round-trip drift (NOT NULL DEFAULT '') that can cause perpetual “MODIFY COLUMN … DEFAULT ''” plans after apply, capturing a catalog vs parser normalization mismatch for future fixing.

Changes:

  • Document the empty-string DEFAULT '' drift loop as a “High — correctness bugs” TODO item.
  • Capture the suspected root cause and where the eventual fix should be applied (catalog default normalization).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TODO.md Outdated
Comment thread TODO.md Outdated
Two Copilot nits on the entry I just added in PR #32:

  - normalizeColumnDefault lives in catalog/tables.go, not
    catalog/catalog.go. (Copilot #1.)
  - The function isn't ENUM/SET/CHAR/temporal-specific — it ignores
    typeName entirely and uses vitess to classify any value as
    bareword-vs-non-bareword. The bug is the `def == ""` short-circuit
    at the top of the function, which returns "" before the bareword
    check runs. The parser side stores `''` (quoted), so they never
    compare equal. (Copilot #2.)

Note also expands the suggested fix: either wrap the empty-string
case for column types where MySQL preserves it, or simply drop the
short-circuit and let vitess classify "".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TODO.md Outdated
Copilot correctly noted the second fix path I'd suggested ("drop the
short-circuit and let vitess classify") doesn't work — vitess can't
parse `SELECT ` and returns a syntax error. The empty-string case
needs an explicit mapping, and since the right behaviour depends on
the column type (varchar/char/text/enum/set preserve `''`; numeric
types don't take a literal empty string at all), the fix has to
start consuming `typeName`, which the current implementation ignores.

Verified with a one-liner go run that `SELECT ''` parses fine but
`SELECT ` (trailing-space empty expression) errors out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TODO.md Outdated
Copilot review: TEXT (and BLOB) cannot take a literal DEFAULT in
MySQL, so listing `text` in the suggested-fix type set documents an
impossible case. Narrow to CHAR / VARCHAR / BINARY / VARBINARY /
ENUM / SET — the types that actually accept `DEFAULT ''` as the
bareword empty string we'd need to round-trip — and explicitly call
out that TEXT / BLOB are excluded because MySQL forbids a literal
default on those.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TODO.md Outdated
Copilot review #4 style nit: the long line with the parenthetical
aside broke the rest of TODO.md's wrapping convention, and inline
`SELECT ` (with trailing space) is brittle in renderers that
collapse trailing whitespace. Rewrapped at the standard width and
turned the parenthetical into its own sentence; the inline code is
now `SELECT` followed by the prose "with an empty expression".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@winebarrel winebarrel merged commit 24da9e6 into main May 2, 2026
7 checks passed
@winebarrel winebarrel deleted the add-empty-default-todo branch May 2, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants