Repository navigation
fix(tokenizer,ast): lex literals per dialect; keep operator meaning across dialects - #874
Conversation
…ct; keep operator meaning across dialects - Numeric literals follow each dialect: PostgreSQL 16 1_000/0x/0o/0b, SQLite and ClickHouse digit separators, Oracle 1d/1f and storage sizes (100M), MySQL digit-leading names; trailing junk such as 1x is an error where the dialect rejects it instead of becoming an alias. - PostgreSQL U&'...' strings and U&"..." identifiers with UESCAPE. - Quoted type names keep their quotes through SQL(), FormatAST and Transpile. - JSON operators bind looser than ^ in PostgreSQL, as PostgreSQL parses. - Formatting or transpiling to another dialect rewrites ^, #, ~, <<, >>, &, |, || and PostgreSQL-only operators to the target's form or returns an error; FormatASTChecked/FormatStatementChecked/FormatExpressionChecked report it, and every in-repo caller uses them. - SQL() adds the parentheses a hand-built tree needs; parsed trees render as before. - Bare digit-leading MySQL names render with backticks everywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
# Conflicts: # CHANGELOG.md # pkg/formatter/render.go
|
Claude finished @ajitpratap0's task in 28s —— View job Review of PR #874I read the diff selectively, mainly Overall: The design looks sound. The operator-meaning checks fail loudly instead of emitting text whose meaning changes, and the Code quality and potential issues
Performance
Security
Tests
Summary: No blocking issues found. The main risk is the duplicated traversal in |
Summary
Follow-ups from the post-merge audit of #866–#868, about literal lexing and operator meaning:
Numeric literals per dialect. Each dialect gets its real rules:
1_000,0x1F,0o17,0b1011d/1fBINARY_DOUBLE/FLOAT and storage sizes (RESIZE 100M,BLOCKSIZE 8K)1col,t.1col, rendered with backticks)0xhex as on mainTrailing junk such as
1xis now an error where the dialect rejects it. Before, it silently became1 AS x.PostgreSQL Unicode escapes:
U&'d\0061t'andU&"d\0061t"withUESCAPE, with comments allowed beforeUESCAPE. Before, these printed asU & '…'. Identifiers are written back decoded.Quoted type names keep their quotes, e.g.
CAST(x AS "MyType")and PostgreSQLx::"char", throughSQL(),FormatASTandTranspile.Precedence: PostgreSQL JSON operators now bind looser than
^, as PostgreSQL does.Operator meaning across dialects: formatting or transpiling into another dialect rewrites operators to the target's form or returns an error. It never emits text whose meaning changes. Covered:
^(power vs XOR),#,~,<<,>>,&,|,||(CONCAT in MySQL) and PostgreSQL-only operators. For example, PostgreSQLa # bused to reach MySQL asa # b, where#starts a comment. NewFormatASTChecked/FormatStatementChecked/FormatExpressionChecked. Every in-repo caller uses them:gosqlx.FormatWithDialect, Transpile, transform, fingerprint, CLI, LSP, MCP and cbinding.SQL()on hand-built trees adds the parentheses they need, e.g.(a OR b) AND c, including a hand-built child inside a parsed tree. Parsed trees render byte-identically to main.Test Plan
gofmt,go vet,golangci-lint run(0 issues),task test:race,task test:cbinding;TestRealWorldCorpusgreenSQL()over all testdata (251 files, 3,011 statements): identical to main apart from the intended changesFormatWithDialectover the corpus is +2.5% ns/op and +1 alloc/op versus main.Breaking Changes
Behaviour changes, listed per dialect in the CHANGELOG:
1x,10Moutside Oracle/generic) are errors where the dialect rejects them.FormatWithDialect. The legacy string-returningFormatAST/FormatStatement/FormatExpressionreturn""in that case, as their doc comments say.🤖 Generated with Claude Code
https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2