Repository navigation
Conversation
…curity actions Rendered SQL had stray spaces in several ALTER TABLE actions: SET INVISIBLE, ALTER INDEX i INVISIBLE, a trailing space after FORCE and [NO] FORCE/ENABLE/DISABLE ROW LEVEL SECURITY, MODIFY ( c INT ), and ADD CONSTRAINT UNIQUE KEY uk (a). An index without a declaration printed a leading space, and argument-less JSON_ARRAY()/JSON_OBJECT() rendered as JSON_ARRAY( ) and JSON_OBJECT( ) with a trailing space. Separate these words with exactly one space and add no leading or trailing space. toString() and StatementDeParser stay identical. Signed-off-by: minleejae <mmj9808@gmail.com>
This was referenced Oct 14, 2026
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
Follow-up to #2792. More renderers emit stray spaces. Today:
ALTER TABLE t ALTER COLUMN c SET INVISIBLErendersSET INVISIBLE(alsoSET VISIBLE, and the form withoutCOLUMN).ALTER TABLE t ALTER INDEX i INVISIBLErendersALTER INDEX i INVISIBLE.ALTER TABLE t FORCEends with a space, andFORCE, ALGORITHM = INPLACErendersFORCE , ALGORITHM = INPLACE.ALTER TABLE t {ENABLE | DISABLE | FORCE | NO FORCE} ROW LEVEL SECURITYends with a space.ALTER TABLE t MODIFY (c INT)rendersMODIFY ( c INT ).ADD CONSTRAINT UNIQUE KEY uk (a)rendersuk (a).IndexofCREATE INDEX ON t (a)renders(a)when printed on its own.DEFAULT (JSON_ARRAY())rendersDEFAULT (JSON_ARRAY( ) ), andJSON_OBJECT()rendersJSON_OBJECT( ).The SQL still reparses, but the extra spaces differ from the input.
Current design (As-is)
ColumnSetVisibilityappends" SET "and then" VISIBLE"or" INVISIBLE".Indexputs two spaces before its trailing index spec when it has no columns. It also puts a space before the column list even when nothing precedes it.AlterExpressionbody appends a space after the operation keyword even when no payload follows. The row level security keywords add the same space." ( "and" ) ". TheADD CONSTRAINT <type> <name>header ends with a space before the column list's own separator.JSON_ARRAYandJSON_OBJECTalways open with"( "and close with") "or" ) ", even with no arguments.Target design (To-be)
ALTER COLUMN c SET INVISIBLE,ALTER INDEX i INVISIBLE,FORCEand... ROW LEVEL SECURITY;MODIFY (c INT),ADD CONSTRAINT UNIQUE KEY uk (a);Indexwith no declaration renders(a).JSON_ARRAY()andJSON_OBJECT()render without inner spaces. No space follows the closing parenthesis. Calls with arguments keep their current inner spacing.EXCHANGE PARTITION ... WITH VALIDATIONrendering of a plainAlterExpressiondrops its trailing space.StatementDeParserproduce the same text. The grammar is unchanged.Validation
DeparseWhitespaceTest(added in Render single spaces in DROP PRIMARY KEY, RENAME TABLE and indexes #2792) now also:toString()andStatementDeParseroutput exactly for the forms above in MySQL, PostgreSQL and default mode;JSON_ARRAY/JSON_OBJECTwith arguments orON NULLclauses render no double space;ColumnSetVisibility, a constructedIndexand a constructedEXCHANGE PARTITIONaction directly.spotlessApply check: 10,382 tests, 10,357 passed, 25 skipped, zero failures/errors.master(bdf8ac31) on a corpus of 635 MySQL 8.4 and PostgreSQL 18 DDL/DCL statements, each accepted by the server, with and without a dialect: no regressions. Only 6 MySQL and 3 PostgreSQL statements of the forms above change theirtoString(), in both dialect and default mode. InCREATE INDEX ON ..., the contained index renders(name)instead of(name).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.