Repository navigation
Conversation
ABSENT, CURRENT, FORCE, IMPORT, PRIOR, SQL_NO_CACHE, UNBOUNDED, UNKNOWN and XMLSERIALIZE become non-reserved words; BETWEEN, FULL, ONLY and RETURNING join the reserved words that are names in name positions. A word after TABLE or COLUMN is always a name, so CREATE TABLE value (...) no longer falls back to an UnsupportedStatement. EXCLUDE names a column unless an exclusion constraint follows, and PATH is accepted as a column type. NonReservedWord is split over two productions: the lookahead routine generated for all words would exceed the JVM's 8000 byte limit for JIT compilation. Signed-off-by: minleejae <mmj9808@gmail.com>
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
Allow keywords that MySQL 8.4 and PostgreSQL 18 accept as unquoted column and table names. A sweep of MySQL's non-reserved words and PostgreSQL's unreserved and column-name keywords, each used as a column in
CREATE TABLE, inALTER TABLE ... ADD COLUMNand as a table name, found 38 statements that fail and 26CREATE TABLE <keyword> (...)statements that silently become anUnsupportedStatement. Each server accepts the words of its own list, for example:Current design (As-is)
ABSENT,CURRENT,FORCE,IMPORT,PRIOR,SQL_NO_CACHE,UNBOUNDED,UNKNOWNandXMLSERIALIZEare reserved, although each one only starts a clause in a few places.BETWEEN,FULL,ONLYandRETURNINGare reserved and are not in the list of reserved words thatRelObjectName()accepts in name positions (likeLEFT,ORDER,SET,VALUE).TABLEorCOLUMN,CREATE TABLE value (a INT)andADD COLUMN offset INTfail; forCREATE TABLEthe statement falls back to anUnsupportedStatement.CREATE TABLEelement that starts withEXCLUDEis always read as an exclusion constraint, so a column namedexcludefails.ColDataType()does not accept thePATHtoken, so PostgreSQL's geometric typepathfails.keywords.rststill listsEXISTS,EXTEND,SAMPLEandSTATEMENT, which fix: allow STATEMENT as an unquoted identifier #2706, fix: allow exists as an unquoted identifier #2773 and fix: allow sample and extend as unquoted identifiers #2774 made non-reserved.Target design (To-be)
NonReservedWord()(as in Make dialect-specific clause words non-reserved #2793). Each keeps its keyword use through these guards:PRIORis Oracle's operator only when an operand follows (PRIOR id,PRIOR (a),PRIOR 2), not inprior = 1,prior IS NULLorORDER BY prior DESC.SQL_NO_CACHEis a MySQL select modifier only before a select item.FORCE INDEX|KEY (...)is an index hint, never an implicit alias.UNBOUNDED PRECEDING|FOLLOWING,XMLSERIALIZE (andABSENT ON NULLkeep their meaning.current.xis a qualified column.CURRENTalone stays aTimeKeyExpressionas before.BETWEEN,FULL,ONLYandRETURNINGare added to that list inRelObjectName(). They start clauses after an expression or a table, so they stay reserved:FULLfollows theLEFT/RIGHTrule. It is an implicit alias unless a join follows, soFROM t fullworks andFROM a FULL JOIN bis unchanged.BETWEEN,ONLYandRETURNINGare never implicit aliases (ASstill works).ONLYbefore a relation name afterFROM,JOIN,UPDATE,INTO,USINGor,is PostgreSQL's inheritance prefix. Forms that are still unsupported, such asDELETE FROM ONLY torJOIN ONLY t, fail as before instead of naming a tableonly.JSON_ARRAY(RETURNING JSON)andJSON_OBJECT(ABSENT ON NULL)keep their clauses.TABLEorCOLUMNis always a name.IF [NOT] EXISTSandONLYare matched before the name, as before.EXCLUDEstarts an exclusion constraint only beforeUSING,(orWHERE.PATHis accepted as a column type, but not as the type of aJSON_TABLEcolumn, where it introduces the path.NonReservedWord()is split into two productions:-XX:HugeMethodLimit), so it would always run interpreted. Measured, that cost about 5% on the benchmark below.MIN_NON_RESERVED_WORD/MAX_NON_RESERVED_WORDsentinels.PRIORbefore a condition and theSQL_NO_CACHEmodifier). JavaCC does not evaluate a semantic lookahead on[...]or(...)*while it scans an enclosing syntactic lookahead, and a choice keeps that guard.keywords.rstis regenerated withupdateKeywords. 88 words are reserved (was 100) and 434 non-reserved (was 425).Not changed
ALTER TABLE t ADD offset INTwithoutCOLUMNstill fails for the listed reserved words. Clause keywords, such asIF NOT EXISTS, also followADD.DROP COLUMNandRENAME COLUMNread the column withKeywordOrIdentifier(), which accepts only a short fixed list of words. That is left to the ALTER column work.ONLYfollowed by an unquoted identifier is read as the relation prefix. SoCREATE TABLE t (a INT, only serial)still fails, and(only serial)or(a INT, only INT)parse.Validation
KeywordsTest: 1,015 cases.CREATE TABLEand inADD COLUMN;CREATE TABLEname;WHEREandORDER BY;FROM,UPDATE ... SETand anINSERTcolumn list.spotlessApply check: 10,442 tests, 10,417 passed, 25 skipped, zero failures/errors. The grammar choice conflict check reports no warnings.RETURNING, JSON functions, window frames, OracleCONNECT BY, PostgreSQLONLY,EXCLUDEconstraints,IF [NOT] EXISTS) and the identifier uses. The statement type and the rendered SQL match master, except for the identifier uses that now parse.CreateTable/Alter, with noUnsupportedStatementleft. Thepathcolumn type statements also parse. The other corpus statements are unchanged..sqltest resources parsed in the calling thread, thread CPU time, 40 rounds per JVM, 10 alternating JVM pairs against master.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.