Repository navigation
Conversation
6d0d61e to
34beb13
Compare
|
Thank you for your work and effort, but I am not a big fan of it:
|
|
Thanks for looking at it @manticore-projects. To clarify the problem this addresses: Recent PRs added dialect-specific keywords to the reserved block for every dialect: ClickHouse's So this isn't about accepting non-portable SQL, but about one dialect's keywords not leaking into the others. If the per-dialect model is too much, a smaller fix would be to make those dialect-only words non-reserved again, behind lookaheads where their clause starts, as #2781 did for |
Reserved keywords are global: a keyword reserved for one dialect's syntax (ClickHouse's PREWHERE and SETTINGS, Exasol's FILE and SCRIPT, MySQL's XOR, ...) is rejected as a name in every dialect, and words a dialect reserves (DuckDB's CASE, TABLE, DESC, ...) are accepted as names whatever the dialect. - `KeywordPolicy`: a dialect's own rules, whether a word is an unquoted name in a `NamePosition` (an object name, a function name, a label after AS or ".", a bare alias). `Dialect#getKeywordPolicy()` is null for the default rules. - `Dialect.DUCKDB` (dollar-quoted string tags, adjacent string literals on a new line) uses `DuckDbKeywordPolicy`: DuckDB 1.5.5's 489 keywords with their categories, from `duckdb_keywords()`, and PostgreSQL's rules for them. Function names only reject reserved keywords, as DuckDB special-cases COALESCE, NULLIF, IF, ... - The grammar consults the policy in both directions: `RelObjectName()` rejects the names it rejects and `DialectUnreservedWord()` accepts the reserved-by-default keywords it accepts; `DialectLabel()` accepts any keyword after AS or "."; a select item's bare alias follows the bare-alias rule; the XOR operator, INCLUDES/EXCLUDES, EXISTS, CONNECT_BY_ROOT, PRIOR, XMLSERIALIZE and the window-frame BETWEEN/UNBOUNDED step aside when the word is a name, with explicit lookaheads (no new choice conflict). - Without a policy nothing changes. - `DuckDbKeywordPolicyTest` checks each DuckDB keyword in 7 name positions against what DuckDB 1.5.5 parses (`duckdb-keyword-names.csv`), except 32 documented cells where JSqlParser parses the word as dedicated syntax (MAP, STRUCT, TRY_CAST, COLUMNS, WITH RECURSIVE, ...) or as a date unit (`SELECT 1 day`). - `TaggedDollarStringTest` treats every dialect enabling dollar-quoted string tags, now including DuckDB, like PostgreSQL.
34beb13 to
41a5a26
Compare
I would not object that at all: exotic and scarcely used features like this Exasol stuff can take longer to parse -- as long as it does not affect the performance of the regular Oracle/Postgres/MSQL/MariaDB queries. |
|
To make the point concrete, on current master:
The Exasol That's the inconsistency I'd like to fix: keywords introduced for a dialect-gated syntax should only be reserved when that dialect is on. |
Well understood, I only object separate keyword lists (because it will be a nightmare to maintain). |
|
Opened #2793 with the smaller fix you suggested: the Exasol/ClickHouse clause words become non-reserved, with no separate keyword lists, and parse performance stays the same. |
Purpose
Implements #2786: a dialect owns its reserved keywords, in both directions, starting with DuckDB.
Model
KeywordPolicy#isName(word, NamePosition): whether a word is an unquoted name at a position:NAME(column, table, CTE, ...),FUNCTION,LABEL(afterASor.),BARE_ALIAS.Dialect#getKeywordPolicy():nullfor the default rules (nothing changes without a policy).Dialect.DUCKDB(dollar-quoted string tags, adjacent string literals on a new line) usesDuckDbKeywordPolicy: DuckDB 1.5.5's 489 keywords with their categories, fromduckdb_keywords(), and the PostgreSQL rules DuckDB applies to them. Function names only reject reserved keywords: DuckDB's grammar special-cases functions named by other keywords (COALESCE,NULLIF,IF, ...).Grammar
RelObjectName()rejects the names the policy rejects at that position (position from the previous token:AS/., or a following().DialectUnreservedWord()accepts the keywords reserved by default that the policy accepts as names;DialectLabel()accepts any keyword afterASor..ASfollows theBARE_ALIASrule; other aliases followNAME.XORoperator (grammar and Pratt loop),INCLUDES/EXCLUDES,EXISTS,CONNECT_BY_ROOT,PRIOR,XMLSERIALIZE, window-frameBETWEEN/UNBOUNDED,CONNECT BY [NOCYCLE], with explicit lookaheads:checkGrammarAmbiguitypasses.Validation
check: 13,489 tests, zero failures/errors; Spotless, Checkstyle, PMD, SpotBugs andcheckGrammarAmbiguitypass. All existing tests are unchanged, apart fromTaggedDollarStringTest, which now treats every dialect enabling dollar-quoted string tags (PostgreSQL and DuckDB) alike.DuckDbKeywordPolicyTestcompares, for each of DuckDB's 489 keywords, 7 name positions (column, qualified column,ASalias, bare alias, table, table alias, CTE) against what DuckDB 1.5.5 itself parses (duckdb-keyword-names.csv, generated withjson_serialize_sql()): 3,391 cells agree. 32 cells are exempted, each documented: JSqlParser parses the word as dedicated syntax at that position (MAP {...},STRUCT(...),TRY_CAST(...),COLUMNS(...),DEFAULT,WITH RECURSIVE,UPDATE ... SET, ...) orSELECT 1 dayas a date unit.Dialect.DUCKDB.Limits
DISTINCTROW,STRAIGHT_JOIN,SQL_CACHE, ...) cannot be names under a policy:Select()'sLOOKAHEAD(3)intoPlainSelect()takes them as modifiers first.