v1.15.0
v1.15.0 — Tree API, ClickHouse 100%, Oracle Gaps, Correctness Sweep
Covers everything merged between v1.14.0 and the October 2026 performance
audit: the high-level Tree API, ClickHouse at 83/83 of the QA corpus, Oracle
gaps, and two architect-review correctness sprints (#517, #518). Exported
signatures are unchanged apart from additions; read Behavior changes
before upgrading.
Behavior changes
- Linter rules inspect nested queries: 14 built-in rules moved to
ast.Walkand 6 more were reinforced, so violations inside subqueries and CTEs are now reported. Expect more findings on nested SQL. (#517) - Structured parser errors: 37
fmt.Errorfsites in the parser now return structured*errors.Errorvalues with position and code, and context cancellation returnsctx.Err()directly soerrors.Is(err, context.Canceled)works.*errors.Error.WithXmethods now copy instead of mutating the receiver. LegacyParse-family functions wrap theErrSyntax/ErrTokenize/ErrTimeout/ErrUnsupportedDialectsentinels. (#517, #518) parser.ValidateBytes("")returns an error, matchinggosqlx.Validate(""). Snowflake stub statements (USE,COPY INTO,PUT,GET,LIST,REMOVE,CREATE STAGE/STREAM/TASK/PIPE/...) are now*ast.UnsupportedStatementinstead of*ast.DescribeStatement. (#511)
Added
- High-level
TreeAPI inpkg/gosqlx:ParseTree(ctx, sql, opts...)returns an opaque*Treewith typed walkers (WalkSelects,WalkInserts,WalkUpdates,WalkDeletes,WalkCreateTables,WalkJoins,WalkCTEs,WalkFunctionCalls,WalkIdentifiers,WalkBinaryExpressions, genericWalkBy[T]),Tree.RewriteandTree.Clone.FormatTree/FormatASTformat without re-parsing. Functional optionsWithDialect,WithStrict,WithTimeout,WithRecoveryandWithMaxBytesreplace the combinatorialParseWith*helpers, which remain.ParseReader/ParseReaderMultipleread from anio.Reader, bounded byWithMaxBytes;errors.Is(err, gosqlx.ErrTooLarge)matches when the limit is exceeded. (#517, #518) - Dialect-aware
gosqlx.SplitStatements(sql, dialect): splits a script on top-level;, honouring PostgreSQL dollar quoting and E-strings, nested block comments, MySQL backticks and SQL Server brackets. (#518) - One-call
gosqlx.Lint,gosqlx.Analyzeand error helpers:Lint(sql)runs all 30 built-in rules,Analyze(sql)reports basic optimization hints and query complexity, andErrorCode,ErrorLocationandErrorHintunwrap structured error details throughfmt.Errorfwrapping. (#512) pkg/sql/dialect: typedDialectand aCapabilitiesstruct with feature flags, exposed throughParser.DialectTyped(),Parser.Capabilities()andParser.Is<Dialect>()helpers. (#517, #518).gosqlx.ymllinter configuration (pkg/linter/config): YAML loader with rule enable/disable, severity overrides and ignore globs. (#517)keywords.Conflicts(): reports keyword registrations that collide across dialects; 11 silent conflicts were resolved. (#517)ast.UnsupportedStatementandAST.HasUnsupportedStatements(): parse-only Snowflake stubs are now their own node type, and the formatter emits-- UNSUPPORTED: <raw SQL>for them instead of corrupt SQL. (#511)EXTRACT(field FROM expr)parses. (#511)- ClickHouse at 83/83 of the QA corpus:
ARRAY JOIN/LEFT ARRAY JOIN(newArrayJoinClause), scalar CTEs (WITH <expr> AS <name>),CREATE MATERIALIZED VIEWwithENGINE/TO,CREATE TABLE ... AS <source> ENGINE = ..., numericSAMPLEarguments withOFFSET, andLIMIT offset, count. (#513) - Named
WINDOWclause (SQL:2003):WINDOW w AS (PARTITION BY a ORDER BY b). (#513) - Oracle compatibility:
ROWNUM/ROWID/LEVEL/SYSDATEpseudo-columns with implicit aliases,PIVOT/UNPIVOTINlists withASaliases, and backslashes treated literally in string literals outside MySQL/PostgreSQL. (#513) SQL()forPragmaStatement,ShowStatement,DescribeStatementandReplaceStatement. (#513)ast.PoolLeakCount(): counts work-queue entries dropped while releasing expressions. (#517)
Changed
- Deprecations:
pkg/sql/monitoris deprecated in favour ofpkg/metrics. The legacy parser APIsParse([]token.Token),ParseFromModelTokensWithPositionsandConversionResult.PositionMappingare scheduled for removal in v2.0. (#511) pkg/sql/astsource split:ast.goandpool.gowere split into statement, expression, clause and release files. No declarations changed. (#518)
Fixed
- Pool leaks:
PutSelectStatementreleased only some pooled fields, largeINlists overflowed thePutExpressionwork queue, and subqueries insideIN/EXISTS/ANY/ALL/array constructors were never released. (#517, #518) Children()coverage: 14 AST node types returned no children despite holding nodes, soWalk/Inspectskipped them. (#517)- LSP: statement dispatch uses a type switch instead of
%Tstring matching, anddocumentSymbolreturns real ranges instead of line 0 to EOF. (#517) - Oracle and ClickHouse parsing:
CONNECT BY/IS NULLis no longer misread as a CTE,SETTINGSand numericSAMPLEare no longer consumed as table aliases, and the SQL ServerOUTPUTclause on INSERT parses in every dialect. (#513) gosqlx.ParseBytespasses bytes straight to the tokenizer, and seven previously skipped extraction cases (CASE, CAST, IN, BETWEEN, EXTRACT, recursive CTEs) are fixed. (#511)
Security
- Metrics error counters are bounded: error statistics were keyed by
err.Error(), an unbounded map that could exhaust memory. They are now counted per error code. (#517) - Trivy findings:
golang.org/x/cryptoraised to v0.54.0 andbrace-expansionpinned to^5.0.8in the VS Code extension. (#528)
Internal
- CI: performance-regression and fuzz-regression jobs,
codecov.ymlthresholds, and thebodyclose/noctxlinters (#512); a CI gate against newp.dialect ==comparisons (#518); race tests run throughtask test:racewith a separate CGOtask test:cbindingjob (#513, #517). - Website: site revamp, light-mode fixes and animations (#514, #515, #516).
- Docs: version and rule-count sweep (#510); integrations bumped to v1.14.0 (#509).