fix: allow GROUPS as identifier by making it a non-reserved keyword (#2473) - #2474
Merged
manticore-projects merged 1 commit intoAug 16, 2026
Merged
Conversation
…SQLParser#2473) Signed-off-by: 付典 <fudianchn@gmail.com>
Contributor
|
Thanks! |
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.
What
GROUPSbecomes a non-reserved keyword again, so it can be used as an identifier (column, table, alias) while theGROUPSwindow frame unit keeps working:Why / Root cause
#2460 (commit d92f407) introduced the PostgreSQL
GROUPSframe unit and declared<K_GROUPS:"GROUPS">in the reserved keyword token section. In PostgreSQL,GROUPSis a non-reserved keyword and stays a legal identifier, so statements like the ones above parsed before #2460 and fail onmasterwithEncountered unexpected token: "groups".The decision in #2460
Making
GROUPSreserved was a deliberate, reviewed trade-off, not an oversight. #2460 initially declaredK_GROUPSinsideNonReservedWord()(24cf1bd); during review the raw<S_IDENTIFIER>productions (CREATE SCHEMA, SET PATH, Oracle KEEP, interval type, COLLATE, the ColDataType lookahead) were called out, and the token was then moved to the reserved set instead of broadening those productions.One point that was not on the table then: the sibling frame units already live in exactly the state this PR restores for
GROUPS.ROWSandRANGEare non-reserved onmaster, and the same raw-identifier productions reject them identically:while quoted forms (
CREATE SCHEMA "groups") work everywhere. "Non-reserved, raw-identifier positions need quoting" is therefore the existing status quo for frame-unit keywords in this grammar, and this PR makesGROUPSconsistent withROWSandRANGE(all three are non-reserved in PostgreSQL) rather than introducing a new inconsistency.If keeping
GROUPSreserved is preferred, closing this PR is fine. If the raw-identifier productions should accept the frame-unit words, that would be a separate change applying toROWS,RANGEandGROUPSalike; I can prepare it on request.How
One symmetric relocation in
JSqlParserCC.jjt: the<K_GROUPS:"GROUPS">declaration moves from the reserved token section into theNonReservedWord()production (betweenGRANTandGROUP_CONCAT).Tokens declared inside
NonReservedWord()fall into theMIN_NON_RESERVED_WORD…MAX_NON_RESERVED_WORDkind range, whichRelObjectName()andisAliasAhead()already accept, and whichKeywordsTestcovers parameterized as identifiers. No other grammar rule changes, and the explicit<K_GROUPS>match inWindowElement()is unaffected (only the token kind numbering moves).Scope
Only the keyword classification changes.
GROUPSframe units (ROWS/RANGE/GROUPS BETWEEN ... EXCLUDE ...) keep parsing exactly as before;GROUPSadditionally works in every identifier position covered by the non-reserved range guards (column, table, schema, alias, function name).Testing
KeywordsTest.testGroupsAsIdentifierreproduces the issue (column, table, explicit and implicit alias,CREATE TABLEcolumn definition): fails onmasterwithJSQLParserException, passes with this change. The parameterizedKeywordsTestidentifier cases pickGROUPSup automatically (732 -> 734 tests).Performance
gradle jmh,JSQLParserBenchmark.parseSQLStatementsonperformance.sql,version=latest, 10 forks x 10 iterations (100 samples) on a 32-core host:master(406a4d4)The
-0.08%delta lies within the 99.9% confidence intervals (the CIs overlap almost entirely): no regression.Verification of the original issue
All statements from #2473 fail on
masterand parse + round-trip with this change.Fixes #2473