Allow reserved keywords as bare column names in SELECT list#269
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
There was a problem hiding this comment.
Pull request overview
This PR updates the SELECT-list parsing logic to accept clause-starter keywords (e.g., LIMIT) as bare column names in projections when they’re clearly not starting a real clause, aligning behavior with ClickHouse for queries like SELECT ..., limit, ... FROM t.
Changes:
- Adds lookahead-based disambiguation in
isSelectItemTerminatorKeywordto avoid prematurely endingparseSelectItemswhen encountering keywords likeLIMITused as identifiers. - Introduces a new query fixture and corresponding golden/format/beautify outputs covering
limitas an unquoted column name.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| parser/parser_column.go | Adds keyword lookahead logic to disambiguate SELECT item terminators vs identifier-like keywords. |
| parser/testdata/query/select_limit_as_column.sql | New repro fixture for limit used as a column in SELECT list. |
| parser/testdata/query/output/select_limit_as_column.sql.golden.json | Golden AST output for the new fixture. |
| parser/testdata/query/format/select_limit_as_column.sql | Formatter expected output for the new fixture. |
| parser/testdata/query/format/beautify/select_limit_as_column.sql | Beautifier expected output for the new fixture. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
28d0efc to
5a5bcf3
Compare
Extend keyword-as-identifier handling to recognize end-of-statement (EOF or `;`) as a disambiguator in expression position, so projections like `SELECT case`, `SELECT case;`, or `SELECT limit` parse as bare column refs — matching ClickHouse server (verified against 25.10.7.6, which returns UNKNOWN_IDENTIFIER, i.e. syntactic accept). The eos check is applied inline in parseColumnExpr rather than added to keywordIsSelectItemIdentifier, because the latter is shared with the terminator/alias-position check, where a trailing clause-starter keyword at EOF (e.g. `SELECT * FROM`) must still be treated as a terminator. Verified `SELECT * FROM` still errors as before. Fixtures: - select_keyword_as_only_column.sql (`SELECT interval`) - select_keyword_as_only_column_semicolon (`SELECT case;`) - select_clause_keyword_as_only_column (`SELECT limit`) - select_keyword_as_alias (`SELECT 1 AS interval, 2 AS from, 3 AS limit`) The AS-alias fixture documents that `SELECT 1 AS <reserved-kw>` already works for every reserved keyword without special handling, because matchTokenKind(TokenKindIdent) coerces TokenKindKeyword and so parseIdent accepts keyword tokens as alias names; added a comment at the AS branch of parseSelectItem to make that intentional.
|
@git-hulk this should be good to review now |
@erezrokah Thank you! |
…p#269) Extend keyword-as-identifier handling to recognize end-of-statement (EOF or `;`) as a disambiguator in expression position, so projections like `SELECT case`, `SELECT case;`, or `SELECT limit` parse as bare column refs — matching ClickHouse server (verified against 25.10.7.6, which returns UNKNOWN_IDENTIFIER, i.e. syntactic accept). The eos check is applied inline in parseColumnExpr rather than added to keywordIsSelectItemIdentifier, because the latter is shared with the terminator/alias-position check, where a trailing clause-starter keyword at EOF (e.g. `SELECT * FROM`) must still be treated as a terminator. Verified `SELECT * FROM` still errors as before. Fixtures: - select_keyword_as_only_column.sql (`SELECT interval`) - select_keyword_as_only_column_semicolon (`SELECT case;`) - select_clause_keyword_as_only_column (`SELECT limit`) - select_keyword_as_alias (`SELECT 1 AS interval, 2 AS from, 3 AS limit`) The AS-alias fixture documents that `SELECT 1 AS <reserved-kw>` already works for every reserved keyword without special handling, because matchTokenKind(TokenKindIdent) coerces TokenKindKeyword and so parseIdent accepts keyword tokens as alias names; added a comment at the AS branch of parseSelectItem to make that intentional.
ClickHouse server accepts essentially every reserved keyword as a bare column reference in a SELECT projection; the parser previously rejected most of them. This widens
isSelectItemTerminatorKeywordandparseColumnExprto parse a keyword as an identifier when the next token is,,AS, or another clause-starter keyword — none of which can legally follow a real clause/expression starter.Validated against ClickHouse 25.10.7.6: 255/256 reserved keywords now parse as bare column refs (only
NOTrejected — a unary operator, also rejected by CH).Backticked identifiers tokenize as
TokenKindIdent, so PR #268's trailing-comma handling is preserved (regression fixtureselect_trailing_comma_before_from_keyword_table.sql).ch-demo.mp4
Test plan