Skip to content

Reject incomplete SQL and preserve lexical errors - #322

Merged
git-hulk merged 6 commits into
masterfrom
codex/fix-parser-token-errors
Sep 10, 2026
Merged

Reject incomplete SQL and preserve lexical errors#322
git-hulk merged 6 commits into
masterfrom
codex/fix-parser-token-errors

Conversation

@git-hulk

@git-hulk git-hulk commented Sep 10, 2026

Copy link
Copy Markdown
Member

Problem

ParseStmts checks the byte offset before consuming the final token, and
SELECT permits an empty projection at EOF. Ignored token errors and failed
lookahead can also discard lexical failures or replace them with a later
grammar error. The shared sign branch incorrectly recognizes +> as ->.

Reproduction

parser.NewParser("SELECT").ParseStmts()           // succeeds with no statements
parser.NewParser("SELECT 1; SELECT").ParseStmts() // loses the final SELECT
parser.NewParser("SELECT 1 /*").ParseStmts()      // accepts an unclosed comment
parser.NewParser("SELECT 1 +> 2").ParseStmts()     // formats +> as ->

Fix

Retain the first lexical failure in a private lexerError that wraps its
cause and byte position outside cursor checkpoints. Restore lookahead on
every outcome and return the original failure through ParseError. Return
errors from tryConsumeTokenKind and propagate them through expectTokenKind
and every optional-token caller. Preserve no-match and normal EOF behavior.
Test token exhaustion, require a SELECT expression, and recognize an arrow
only when it starts with a minus.
Public APIs and existing golden output are unchanged.

Test

Add regressions for final-token boundaries, lexical failures across
lookahead/backtracking, original error locations, and cursor restoration.
Check direct error propagation through required tokens, optional tokens,
and list separators without relying on wrapError. The focused tests failed
before the fix. Add AST and formatting fixtures
for valid arrow syntax and a final statement without a semicolon.

Validate the reproductions with ClickHouse 26.7.1.1315. A separate probe
also rejects malformed suffixes in 684 variations of the existing SQL
fixtures. make, make test, and make lint pass with Go 1.21.13 and
the CI-pinned golangci-lint v1.53.3. Local macOS verification uses the
external linker and an ad-hoc signature for the temporary linter binary.

## Problem

ParseStmts checks the byte offset before consuming the final token, and
SELECT permits an empty projection at EOF. Ignored token errors and failed
lookahead can also discard lexical failures or replace them with a later
grammar error. The shared sign branch incorrectly recognizes +> as ->.

## Reproduction

```go
parser.NewParser("SELECT").ParseStmts()           // succeeds with no statements
parser.NewParser("SELECT 1; SELECT").ParseStmts() // loses the final SELECT
parser.NewParser("SELECT 1 /*").ParseStmts()      // accepts an unclosed comment
parser.NewParser("SELECT 1 +> 2").ParseStmts()     // formats +> as ->
```

## Fix

Retain the first lexical error and its byte position outside cursor
checkpoints, restore lookahead on every outcome, and return the original
failure from ParseStmts. Test token exhaustion, require a SELECT
expression, and recognize an arrow only when it starts with a minus.
Public APIs and existing golden output are unchanged.

## Test

Add regressions for final-token boundaries, lexical failures across
lookahead/backtracking, original error locations, and cursor restoration.
The focused tests failed before the fix. Add AST and formatting fixtures
for valid arrow syntax and a final statement without a semicolon.

Validate the reproductions with ClickHouse 26.7.1.1315. A separate probe
also rejects malformed suffixes in 684 variations of the existing SQL
fixtures. `make`, `make test`, and `make lint` pass with Go 1.21.13 and
the CI-pinned golangci-lint v1.53.3. Local macOS verification uses the
external linker and an ad-hoc signature for the temporary linter binary.
@git-hulk git-hulk changed the title codex/fix parser token errors Reject incomplete SQL and preserve lexical errors Sep 10, 2026
Replace the separate lexer error and position fields with a private
lexerError wrapper. Capture comment positions at the error source and
preserve already-positioned failures when token consumption returns.

Extend the lookahead regression to inspect the returned error position.
Build, lint, and the full race/compatibility suite pass with Go 1.21.13.
Remove the duplicate lexer error check after parseStmt. The next loop
iteration always calls consumeToken before checking EOF, so retained
lexical failures already return through that path. wrapError preserves
the lexical cause when the grammar returns a secondary error first.
Return (*Token, error) from tryConsumeTokenKind and check the error in
expectTokenKind and every optional-token caller. Preserve non-matching
and EOF behavior while returning lexical failures at consumption.

Add regressions for direct error propagation, original error positions,
non-matching tokens, and final-token consumption. make test, make lint,
and make pass with Go 1.21.13 and the CI-pinned linter.
Remove Lexer.err and propagate consumption and lookahead failures through
parser helpers. Keep error positions in returned lexerError values and
retry only grammar errors during backtracking.

Preserve keyword mismatch rollback and normal EOF. Cover direct keyword,
lookahead, and backtracking errors, plus scanning valid input after a
failed scan is rewound. make test, make lint, and make pass with Go 1.21.13
and the CI-pinned linter; 684 malformed fixture suffixes are rejected.
@git-hulk
git-hulk marked this pull request as ready for review September 10, 2026 05:51
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T05:57:42.272212Z bf4d562 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@git-hulk
git-hulk merged commit f2ac5af into master Sep 10, 2026
4 checks passed
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