Skip to content

Split keywords into reserved and non-reserved sets#282

Merged
git-hulk merged 2 commits into
masterfrom
fix/reserved-keyword-split
Jul 5, 2026
Merged

Split keywords into reserved and non-reserved sets#282
git-hulk merged 2 commits into
masterfrom
fix/reserved-keyword-split

Conversation

@git-hulk

@git-hulk git-hulk commented Jul 5, 2026

Copy link
Copy Markdown
Member

Summary

Revives #275, rebased onto current master (the #276/#277 accessor renames caused the old branch to no longer apply), with both review regressions fixed.

matchTokenKind previously coerced every keyword token to match TokenKindIdent, so any keyword could silently fill an identifier slot:

Input Before After
SELECT a FROM WHERE b = 1 parsed as SELECT a AS FROM WHERE b = 1 error at WHERE: expected table name
SELECT NOT NOT a NOT (column \"NOT\") AS a works with the precedence fix in #279; errors cleanly here
SELECT 1 AS interval, SELECT a, from, b FROM t works still works (non-reserved / disambiguated)

Review fixes from #275

Both regressions flagged in the review are addressed, with regression tests:

  1. Callable operator keywords (parser/keyword.go review thread): and(a, b), or(a, b), in(1, [1]), like(s, p), ilike(s, p) all parse again — parseIdentOrFunction accepts a keyword name when the next token is (. Keywords with dedicated syntax (CAST, CASE, EXTRACT, INTERVAL...) keep their own paths, which run first. SELECT FROM (SELECT 1) behaves identically to master (verified against a master build).
  2. Reserved-keyword aliases after AS (three review threads): expression lists (SELECT (1 AS from), sum(x AS from)), ORDER BY x AS from, and non-parenthesized CTEs (WITH 1 AS from SELECT from) all use parseAnyKeyword now, exactly as suggested.

Design

  • reservedKeywords: statement/clause starters and expression operators — these no longer match identifier positions, so a missing name fails fast instead of swallowing the clause keyword. Everything else (DATE, KEY, FIRST, ID, ...) stays usable as a bare identifier.
  • parseAnyKeyword: for positions where context has proven the token is a name (after AS, after a dot, disambiguated select items) — accepts reserved keywords too.
  • matchTokenKind is variadic: matchTokenKind(TokenKindIdent, TokenKindKeyword) where any keyword is acceptable.

No golden fixture changed; make test passes.

Closes the follow-up promised in #275.

🤖 Generated with Claude Code

Revives #275 rebased onto current master (post-#276/#277 renames) and
addresses both review regressions.

matchTokenKind previously coerced every keyword token to match
TokenKindIdent, so any keyword could silently fill an identifier slot:
`SELECT a FROM WHERE b = 1` parsed as `SELECT a AS FROM WHERE b = 1`.

- New reservedKeywords set: statement/clause starters and expression
  operators no longer match identifier positions, so a missing name
  fails fast at the clause keyword. All other keywords stay usable as
  bare identifiers.
- parseAnyKeyword accepts any keyword - reserved or not - in positions
  where context has already proven the token is a name: after AS, after
  a dot in a qualified name, or a lookahead-disambiguated select item.

Review fixes on top of the original branch:
- Operator keywords stay callable as ClickHouse functions when followed
  by '(': and(a, b), or(a, b), in(1, [1]), like(s, p), ilike(s, p).
  parseIdentOrFunction now accepts a keyword name in that case.
- Reserved keywords are accepted as aliases after AS in expression
  lists (`SELECT (1 AS from)`, `sum(x AS from)`), ORDER BY
  (`ORDER BY x AS from`) and non-parenthesized CTEs
  (`WITH 1 AS from SELECT from`), per review suggestions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread parser/parser_table.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f08bae41f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread parser/parser_common.go
Comment thread parser/parser_column.go Outdated
Comment thread parser/parser_column.go Outdated
Comment thread parser/parser_common.go Outdated
@git-hulk git-hulk merged commit 38158f9 into master Jul 5, 2026
4 checks passed
@git-hulk git-hulk deleted the fix/reserved-keyword-split branch July 5, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant