🤖 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:
- 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.
- 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.
🤖 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
Root cause
MySQL changed how a boolean keyword default is resolved on
ENUM/SETbetween 8.4 and 9.7. Reproduced locally against the official images:enum('0','1') NOT NULL DEFAULT TRUEDEFAULT '0'DEFAULT '1'enum('0','1') NOT NULL DEFAULT FALSEDEFAULT '0'enum('a','1') NOT NULL DEFAULT TRUEDEFAULT '1'enum('x','y') NOT NULL DEFAULT TRUEset('0','1') NOT NULL DEFAULT TRUEDEFAULT '0'DEFAULT '1'TRUE→ 1 → member index 1 ('0'inenum('0','1')), andFALSE→ 0, which is not a valid index, hence 1067.SETbehaves as a bitmask, so bit 0 selects the first member.'1'/'0'and matches it against the member list, soenum('a','1') DEFAULT TRUEis now accepted where 8.4 rejected it, andenum('0','1') DEFAULT TRUEnow yields the second member.The test hardcodes the 8.4 reading (
DEFAULT '0') with no version gate, so 9.7 fails on therequire.Containsof the liveSHOW 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 aMODIFY COLUMNthat 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:
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.(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,
SEThas the same split and should not be added without a gate.Not to be confused with the other failure on #1225 (
TestMoveReverseWindowNMResumesAfterKillon the 8.0.45 job), which is #1239.