This document outlines guidance for AI coding agent including project structure, coding style, testing, and contribution practices for the ClickHouse SQL Parser project.
# Build the CLI binary
make
# Run tests
make test
# Update golden fixtures after intentional output changes
make update_testAfter editing code, use goimports and gofmt to maintain code style, and run make lint to check for any issues before committing or requesting a review.
main.gois the CLI entry point (clickhouse-sql-parser) for AST output and SQL formatting.parser/contains core parser code: lexer (lexer.go), AST definitions (ast.go), traversal helpers (walk.go), and grammar-specific parser files (parser_query.go,parser_table.go,parser_alter.go, etc.).- Tests live next to source as
*_test.gofiles, with fixtures underparser/testdata/. - Fixture groups are organized by SQL type (
basic/,query/,dml/,ddl/), with generated expectations inoutput/(AST JSON) andformat/(formatted SQL).
- Use Go 1.21 conventions (
go.mod) and keep codegofmt/goimportsclean (enforced by lint). - Naming is the most important style aspect, try you best to choose a clear and descriptive name for variables, functions, types, and files. For example, use
parseSelectfor a function that parses a SELECT statement, andSelectStatementfor the corresponding AST node type. - Place parsing logic in the matching module by statement family (for example, query parsing in
parser/parser_query.go). - Follow existing parser naming patterns such as
parseXxxhelpers and explicit AST type names. - Keep AST
FormatSQL()output deterministic; formatting changes must be reflected in golden files. - You must go through the repository before adding new code to ensure consistency with existing patterns and styles. If you are unsure about where to place new code or how to format it, please refer to the existing codebase or ask for guidance.
- Reusing existing code and patterns is encouraged to maintain consistency and reduce redundancy. If you find a similar function or pattern in the codebase, consider adapting it for your needs instead of creating something new from scratch.
Before adding support for new syntax or fixing a parsing issue, verify that the SQL is actually valid ClickHouse by checking it against the real engine with clickhouse-local. This prevents the parser from accepting syntax that ClickHouse itself rejects (or rejecting syntax it accepts), which is the single most common source of incorrect grammar changes.
-
Install it once if it is not already available:
- macOS:
brew install clickhouse - Linux/other:
curl https://clickhouse.com/ | sh(produces a./clickhousebinary; invoke as./clickhouse local) - Verify the install with
clickhouse local --version.
- macOS:
-
Validate a statement without executing it against real data by asking ClickHouse to parse it:
# Syntax-check only (does not run the query). Exit code 0 means the SQL parses. clickhouse local --query "EXPLAIN SYNTAX SELECT * FROM system.one WHERE a = 100" # Or check DDL/DML that references no data: clickhouse local --multiquery --query "CREATE TABLE t (id UInt64) ENGINE = Memory; DESCRIBE t;"
-
Workflow:
- Confirm the SQL you intend to support parses (or, for a bug fix, that ClickHouse’s behavior matches your expectation) with
clickhouse-local. - Only then add or change the grammar/AST in this parser.
- Add the same SQL as a fixture under
parser/testdata/<category>/so the behavior is locked in.
- Confirm the SQL you intend to support parses (or, for a bug fix, that ClickHouse’s behavior matches your expectation) with
-
If
clickhouse-localis unavailable in your environment, state that explicitly in the PR description and cite the relevant ClickHouse documentation for the syntax instead, rather than guessing.
- Use Go’s
testingpackage withtestify/requireassertions andgoldiesnapshot comparisons. - Add new SQL cases as
.sqlfiles under the appropriateparser/testdata/<category>/directory. - If expected outputs change, run
make update_testand commit updated files in bothoutput/and/orformat/. - Prefer descriptive test names (
TestParser_*,TestWalk_*) and subtests for per-fixture coverage.
- Match existing commit style: concise, imperative subjects like
Add support for ...orFix parsing failure ..., optionally with issue refs (for example(#235)). - Keep PRs focused; describe grammar/AST impact, include representative SQL examples, and note regenerated fixtures.
- Before requesting review, run
make lintandmake testlocally to mirror CI expectations.
- Always validate the target SQL against
clickhouse-localbefore adding new syntax or fixing a parsing issue (see "Validate SQL withclickhouse-local" above). - You must confirm it's correctly added to
visitor.go,walk.goandformat.gowhen adding a new expression or statement type. This ensures that the new AST node is properly traversed and formatted. - Newly added test cases must be concise and cover the core functionality being tested first.