Skip to content

MySQL 9.7 changed ENUM/SET boolean-keyword default resolution; TestDiffIntegrationBooleanKeywordDefaultOnExcludedTypes fails on 9.7 #1264

Description

@morgo

🤖 Filed by Morgan's AI agent.

TestDiffIntegrationBooleanKeywordDefaultOnExcludedTypes (added in #1225, pkg/statement/diff_integration_test.go) fails deterministically on the MySQL 9.7 job and passes on 8.0.28 / 8.0.42 / 8.0.45 / 8.4. It has failed on every push to that branch (2026-09-09 and 2026-09-22), so it is not flaky.

Failing job: https://github.com/block/spirit/actions/runs/35728483085/job/106747878570

--- FAIL: TestDiffIntegrationBooleanKeywordDefaultOnExcludedTypes (0.07s)
    diff_integration_test.go:748:
        Error: "... `choice` enum('0','1') NOT NULL DEFAULT '1' ..."
               does not contain "`choice` enum('0','1') NOT NULL DEFAULT '0'"

Root cause

MySQL changed how a boolean keyword default is resolved on ENUM/SET between 8.4 and 9.7. Reproduced locally against the official images:

declaration 8.4.9 9.7.0
enum('0','1') NOT NULL DEFAULT TRUE DEFAULT '0' DEFAULT '1'
enum('0','1') NOT NULL DEFAULT FALSE error 1067 DEFAULT '0'
enum('a','1') NOT NULL DEFAULT TRUE error 1067 DEFAULT '1'
enum('x','y') NOT NULL DEFAULT TRUE error 1067 error 1067
set('0','1') NOT NULL DEFAULT TRUE DEFAULT '0' DEFAULT '1'
  • 8.4 and earlier resolve the keyword numerically: TRUE → 1 → member index 1 ('0' in enum('0','1')), and FALSE → 0, which is not a valid index, hence 1067. SET behaves as a bitmask, so bit 0 selects the first member.
  • 9.7 resolves the keyword as the string value '1' / '0' and matches it against the member list, so enum('a','1') DEFAULT TRUE is now accepted where 8.4 rejected it, and enum('0','1') DEFAULT TRUE now yields the second member.

The test hardcodes the 8.4 reading (DEFAULT '0') with no version gate, so 9.7 fails on the require.Contains of the live SHOW CREATE TABLE, before it reaches the diff assertions.

Scope

This is a test-expectation defect only, as far as I can tell. The boolean-keyword folding normalizer added in #1225 already excludes ENUM, so no fold is attempted on either version; the diff emits a MODIFY COLUMN that re-states the declared default, which converges on both. Nothing in the production path depends on the 8.4 numeric reading. I have not audited whether other statement-layer tests carry ENUM/SET boolean-default expectations.

Suggested fix

Handle it in #1225, one of:

  1. Drop the choice enum(...) column from the fixture. The exclusion it documents (the keyword names a member rather than a value) is version-dependent and is now only true pre-9.7, so the reading it is meant to record no longer generalizes.
  2. Keep the column but branch the expected live default on the server version, and say in the comment that 9.7 switched from index to value resolution.

(1) is the smaller change and keeps the test's stated purpose — recording the readings that justify each exclusion — honest, since the enum reading is no longer a stable one. Whichever way it goes, SET has the same split and should not be added without a gate.

Not to be confused with the other failure on #1225 (TestMoveReverseWindowNMResumesAfterKill on the 8.0.45 job), which is #1239.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions