fix(plugin-mysql): read a nullable column's DEFAULT NULL back as NULL on MySQL and MariaDB - #3067
Merged
Merged
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
This was referenced Sep 23, 2026
… on MySQL and MariaDB
datlechin
force-pushed
the
fix/mysql-null-column-default
branch
from
September 23, 2026 15:35
5520511 to
9f1c9ad
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3058
Root cause
The MySQL plugin decoded a catalog default without looking at the column's nullability. MySQL and MariaDB both report SQL NULL for a nullable column's default, whether it was declared
DEFAULT NULLor declared with no default at all. MySQL's manual says those are the same thing: an omitted default on a nullable column is an explicitDEFAULT NULL. The decoder mapped every SQL NULL to "no default", which the Default cell paints as the italic Empty. Saving NULL worked. The read threw it away.The same function carried a second shipped defect (0.73.0, #2690). On MariaDB 10.2.7 and later,
fetchColumnsreadSHOW FULL COLUMNSbut appliedINFORMATION_SCHEMA's quoting rules to it.SHOW FULL COLUMNSquotes nothing, soDEFAULT 'abc'was read as the SQLabc. The next edit of that column then failed or changed the default:ERROR 1054, or withERROR 1064for''and dates'NULL'silently became SQL NULLFix
Read side (
MySQLCatalogDefault.swift,MySQLPluginDriver+Schema.swift).bare(SHOW COLUMNS everywhere,INFORMATION_SCHEMAon MySQL) or.quoted(INFORMATION_SCHEMAon MariaDB 10.2.7+). The oldquotesLiteralsflag described one read and was applied to another.mysqlColumnDefaultreads SQL NULL asNULLon a nullable column and as no default on a NOT NULL one. A generated or AUTO_INCREMENT column has no default.INFORMATION_SCHEMAread that already ran for generation expressions.SHOW FULL COLUMNSstays the primary read, because proxies answer it truthfully and answer the catalog with nothing.SHOW CREATE TABLEsupplies the defaults nothing else states exactly:uuid()and'uuid()'read alikeSHOW CREATE TABLEonly for tables that hold such a default.SHOW CREATE TABLEcolumn parser moved fromOceanBaseColumnDefaultstoMySQLCreateTableScanner. It still reads one definition per line, because OceanBase printsSETandENUMmembers with unbalanced quotes. A line that opens a quoted column name without closing it now runs on into the next, so a line break inside a name cannot hand the rest of it to another column as a default.Write side (
MySQLColumnDefinitionSQL.swift)TEXT,BLOB,JSONandGEOMETRYit was writtenDEFAULT (NULL), which MySQL 8 stores as an expression default and MySQL 5.7 rejects.App
EditableColumnDefinition.setNullable(_:)clears a NULL default when a column becomes NOT NULL. Otherwise, now that nullable columns read as NULL, turning Nullable off would fail almost everywhere withERROR 1067. Setting Primary Key and the Create Table auto-increment promotion go through it too.TableRows.serverAssignsValuedoes not count a NULL default. Add Row keeps sending NULL rather than leaving nullable MySQL columns to the server.DEFAULT NULLagainst PostgreSQL's nothing is not a difference.Probe script
scripts/check-mysql-column-defaults.sh [host] [port] [user]asserts, against a live server, every catalog shape the decoder hard-codes. It gates each fixture on the server version.Measured
SHOW FULL COLUMNSDEFAULT NULL,SHOW FULL COLUMNSDEFAULT NULL,INFORMATION_SCHEMANULLDEFAULT 'abc',SHOW FULL COLUMNSabcabc(unquoted)DEFAULT 'abc',INFORMATION_SCHEMAabc'abc'DEFAULT (concat('日','x')), catalog日asæ\u{97}¥NOT NULL DEFAULT NULLBefore and after, from a harness that runs the plugin's real
fetchColumnsandgenerateModifyColumnSQLagainst live servers. It re-runs aMODIFYfor every column with the default exactly as read, then reads the table again:origin/mainNameafterMODIFY … NULL DEFAULT NULLnil(Empty)NULLMODIFYof an expression default holdingit'sERROR 1064日andéMODIFYof'abc','','2020-01-01'defaultsERROR 1054,1064,1064'NULL'SHOW CREATE TABLEagainstINFORMATION_SCHEMAdecodingTests
MySQLColumnDefinitionSQLTests:SHOW FULL COLUMNSfallbackSHOW CREATE TABLEexpression defaults, non-ASCII includedSHOW CREATE TABLEfallbackStructureNullDefaultTests:CreateTableDraftBuilderTests,RowOperationsManagerTests,StructureDiffEngineTestsandCrossEngineStructureTranslatorTestsfor the app-side changes.ColumnDefaultRoundTripTests.mysqlTextColumnParenthesisesOnceasserted that the menu's NULL is writtenDEFAULT (NULL)on a TEXT column. That was the defect, measured above, so the assertion now expects bareNULL.There is no UI test. The flow needs a live MySQL or MariaDB server, and the UI test runner has none.
Before / After
No screenshots. Two other sessions were running
TableProUITestson this machine, and a second TablePro process fails their XCUITest host. The reporter's recording shows the before. After: the sameNamecolumn reads NULL in the Default cell and keeps it after Cmd+S and Cmd+R.Known limits
ALTER COLUMN … DROP DEFAULTreads as NULL. The catalog reports it exactly likeDEFAULT NULL, and forTEXTso doesSHOW CREATE TABLE. TablePro cannot create that state: aMODIFYwithout aDEFAULTclause givesDEFAULT NULL.