Repository navigation
Conversation
minleejae
force-pushed
the
feat/mysql-column-attributes-20261014
branch
from
October 14, 2026 07:50
fc52164 to
eee3991
Compare
MySQL column attributes without a typed alternative were split into one opaque option per token: AFTER id became OTHER[AFTER] and OTHER[id], SRID 4326 became OTHER[SRID] and OTHER[4326], and inline UNIQUE KEY was a UNIQUE constraint followed by an opaque KEY. Store the FIRST/AFTER position of ALTER ADD, CHANGE and MODIFY column definitions as a ColumnPosition on AlterExpression.ColumnDataType, parsed after the attributes as in MySQL. Add SRID, COLUMN_FORMAT, ENGINE_ATTRIBUTE and SECONDARY_ENGINE_ATTRIBUTE column option kinds with typed factories, read inline UNIQUE KEY as one key constraint, and read bare KEY as a primary key that keeps its spelling. Legacy column specs keep their previous tokens, and the validator checks the AFTER column. Signed-off-by: minleejae <mmj9808@gmail.com>
minleejae
force-pushed
the
feat/mysql-column-attributes-20261014
branch
from
October 14, 2026 08:36
eee3991 to
de2c5ca
Compare
This branch has not been 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.
Purpose
Model the MySQL column position and column attributes that are currently split into one opaque option per token. For example,
ALTER TABLE t ADD COLUMN c INT AFTER idexposesOTHER[AFTER]andOTHER[id],SRID 4326exposesOTHER[SRID]andOTHER[4326], and the inlineKEYprimary key is only an opaqueKEYtoken, soCreateTable.getConstraints()misses it.Current design (As-is)
ColumnDefinitionOption()has typed alternatives for the common attributes. Anything else falls back toColumnDefinitionParameter(), which reads one token at a time.Kind.OTHERoptions:FIRST/AFTER colposition of ALTER ADD, CHANGE and MODIFY;SRID n,COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT};ENGINE_ATTRIBUTE [=] '…'andSECONDARY_ENGINE_ATTRIBUTE [=] '…'.UNIQUE KEYis a UNIQUE constraint followed by an opaqueKEY. A bare inlineKEY, MySQL's column-level synonym for PRIMARY KEY, is opaque.Target design (To-be)
ColumnPosition(FIRSTorAFTER column) and store it onAlterExpression.ColumnDataType(getPosition(),setPosition(),withPosition()).ColumnPosition()production reads it after the column attributes, as MySQL does.ColumnDataType.appendTorenders it last, so toString andAlterDeParseragree.AlterValidatorchecks the column named byAFTERwith metadata validation.ColumnOptionkinds with typed factories and accessors, following the Unify column option storage and mutation contracts #2769/Make column option token access consistent and explicit #2777 contracts:SRID:srid(long),getSrid();COLUMN_FORMAT:columnFormat(ColumnFormat),getColumnFormat();ENGINE_ATTRIBUTE/SECONDARY_ENGINE_ATTRIBUTE:engineAttribute(StringValue),secondaryEngineAttribute(StringValue),getEngineAttribute(),isUseEquals(). The literal is visited and rendered through the expression printer, like a COMMENT literal.COLUMN_FORMAT COMPRESSED. No new tokens or reserved words.ColumnKeyConstraint()readsUNIQUE [KEY]and bareKEYinto oneKeyConstraint.KEYkeeps its spelling and reportsConstraintKind.PRIMARY_KEY, so it also appears ingetConstraints().FOREIGN KEY REFERENCES …prefix stays one rawFOREIGN KEYoption, so itsKEYis not read as a primary key.CHAR(n) BINARYstays an opaque option.BINARYbelongs to the data type's character set clause, together withASCII,UNICODEandCHARACTER SET. It is not a column attribute, and it also appears inCAST(… AS CHAR(n) BINARY), so a column option kind would model it at the wrong level.ColDataType, next toCharacterSetSyntax. That changes the type grammar shared with CAST/CONVERT/JSON_VALUE, and it needs order-preserving state for forms such asBINARY CHARACTER SET xandCHARACTER SET x BINARY. This is left for a separate change.getColumnSpecs()andColumnOption.getTokens()keep the previous token split, for example[SRID, 4326],[UNIQUE, KEY]and[NOT, NULL, AFTER, id]. OnColumnDataType,setColumnSpecs()replaces the options and the position, so a spec snapshot round-trips.getColumnOptions()no longer contains the opaque nodes for these attributes or for the position.AFTER id NOT NULL. This now fails to parse instead of becoming raw tokens.Validation
Dialect.MYSQLand without a dialect;UNIQUE KEY, bareKEYand SQL Server's inlineFOREIGN KEY;setColumnSpecs, builders, rejected placements, and AFTER-column validation.COLUMN_FORMAT DYNAMICas an example of a raw option; they now useCOLUMN_FORMAT COMPRESSED, which stays raw.ColumnAttributeTestnow expects the typedCOLUMN_FORMATand keeps a raw extension (NOT SECONDARY).spotlessApply check: 10,400 tests, 10,375 passed, 25 skipped, zero failures/errors. The grammar choice conflict check, Checkstyle, PMD, SpotBugs and coverage checks pass.master(bdf8ac31) on a corpus of 635 MySQL 8.4 and PostgreSQL 18 DDL/DCL statements, each accepted by the server, plus variants, with and without a dialect:master(bdf8ac31), with zero regressions.Dialect.MYSQL, opaque column options drop from 29 to 1; the one left isCHAR(10) BINARY. Without a dialect it is the same, 29 to 1.ColumnPositionvalues on 7 ALTER statements.toString()on a second, identical server, in the same order. All 205 MySQL and 328 PostgreSQL statements give the same result (success, or the same error).Integration validation
Applied #2806–#2819 together on
master(bdf8ac31), with the stacked PRs on top of their bases (#2806 → #2807 → #2808, #2806 → #2809 → #2810 and #2811 → #2812).master. Between the branches, conflicts are limited to adjacent additions (README/index rows, usage sections, imports, visitor and feature lists, one enum line and one alias guard).spotlessApply check: 11,494 tests, 11,469 passed, 25 skipped, zero failures/errors. The grammar choice conflict check passes.master: 206) and 363 of 364 PostgreSQL statements (master: 328). Every MySQL 8.4 non-reserved word and PostgreSQL 18 unreserved or column-name keyword parses as a column and table name.