Highlights
This minor release focuses on performance, clearer diagnostics and new layout options, alongside a large wave of Databricks and SparkSQL support and a broad set of dialect improvements and bug fixes.
- Linting is faster across the board. A series of performance changes removes quadratic work in the layout rules and
LT09, reuses whole-file reflow sequences across rules, and skips parse subtrees that can't match. It also cuts fixed costs every linted file pays and sends less data to and from worker processes. The Rust engine also gets lower allocation overhead and a per-process regex cache. - Parse errors are easier to act on. Unparsable-section messages now name the unexpected token and show the grammar the parser expected. Diagnostics on templated code now carry full source positions.
- New layout and convention options.
LT05gains alist_wrapping = filloption that puts as many list elements on each line as fit, rather than one per line.- The new
indented_using_on_newlineoption indentsON/USINGbelow a join target on its own line. CV03adds arequire_multiline_forbid_single_linetrailing-comma policy.fixed_suffixcan now be set in config, not just on the CLI.
- Databricks and SparkSQL support grows a lot, including:
- SQL scripting and stored procedures
- Unity Catalog
SHOW/DESCRIBE, privileges and tags GEOGRAPHY/GEOMETRYtypesEXECUTE IMMEDIATEand named parameter markers- SQL-bodied
CREATE FUNCTION - a Databricks parameter style for the placeholder templater
- The Jinja templater supports more dbt behaviour. It adds dbt materialization blocks and the
fromjson/tojsonhelpers, and fixesreturnhandling in nested macros defined in the same file.
Beyond that, this release expands parsing support across DuckDB, Snowflake, T-SQL, MySQL/MariaDB, PostgreSQL, ClickHouse, SQLite, Trino, Oracle, Redshift, BigQuery, Flink, Db2, StarRocks, Doris and other dialects. Rule fixes stop several autofixes from changing query meaning: ST02, ST06, ST08, ST09 and CV06 now preserve precedence, parentheses, operators and statement boundaries. Other fixes reduce false positives in AL05, AM01, AM07, RF01, RF03 and LT09. SQLFluff also now supports Click 8.5.
This release also includes first-time contributions from fifty-five new contributors. Thank you all for your contributions. π
Whatβs Changed
- Trino: parse CREATE/DROP MATERIALIZED VIEW (#8940) @adhavan18
- Fix LT02 blank-line growth after empty inline templates (#8944) @zhangxinyao88
- SparkSQL: Support multi-column TABLE() arguments (#8761) @WittierDinosaur, @claude
- T-SQL: Parse $PARTITION.() calls (#8917) @pujitha24
- Snowflake: Support aggregation and projection policies (#8936) @sai-sakalam
- Postgres: support GROUP BY DISTINCT / ALL (#8925) @YashG1836
- Fix pre-commit end-of-file-fixer failure on main (vertica fixture) (#8929) @YashG1836
- Include source positions for templated diagnostics (#8697) @dheeraj-juvvadi, @claude
- linter: surface the expected grammar in unparsable messages (#8558) @taslater, @claude
- fix(RF03): only skip templated refs for the placeholder templater (#8561) @udsy19
- Preserve expression precedence when ST02 negates a CASE (#8867) @Jackmeson1, @claude
- ClickHouse: Support multiple comma-separated actions in ALTER TABLE (#8914) @manjirisharma
- fix(vertica): support integer literals and DEFAULT in ALTER TABLE SET MERGEOUT (#8894) @pranaysb
- MySQL: support DESCRIBE, DESC and full EXPLAIN syntax (#8923) @YashG1836
- fix(doris): remove unsupported FlushStatementSegment from StatementSegment (#8901) @Pyhroff
- fix(starrocks): remove unsupported FlushStatementSegment from StatementSegment (#8902) @Pyhroff
- Fix pre-commit end-of-file-fixer failure on main (#8927) @keraion
- fix(doris): use CommaSegment for fixed range partition grammar (#8896) @pranaysb
- Test rule-filter options in the diff-quality integration (#8898) @zhangxinyao88
- fix(LT09): do not rejoin single select target when line length exceeds limit (#8624) (#8863) @askarshabdanov1-collab
- SQLite: allow MATCH, VIRTUAL and LAST as identifiers (#8905) @kennywu411-dev
- perf: skip subtrees that cannot match and trim redundant rule work (#8910) @joshmarkovic
- fix(postgres): resolve COLUMN keyword ref in AlterForeignTableActionSegment (#8888) @pranaysb
- Add show statement to MySQL (#8812) @bigbuger
- fix(mysql, mariadb): resolve TableReference typo and optional validation in ALTER TABLE EXCHANGE PARTITION (#8878) @askarshabdanov1-collab
- fix(db2): register INVALID keyword for XML index definitions (#8892) @pranaysb
- fix(redshift): replace postgres-only statements with Redshift grammar (#8856) @Duo-ee, adenyoung
- fix(trino): support CREATE FUNCTION with RETURN and register missing keywords (#8881) @askarshabdanov1-collab
- fix(flink): add missing BUCKETS and BUCKET unreserved keywords (#8879) @askarshabdanov1-collab
- T-SQL: Fix RuntimeError from keywords missing in the dialect (#8872) @555aaditya
- Databricks: support Unity Catalog SHOW, DESCRIBE, privileges and tags (#8862) @taslater, @claude
- fix(databricks): register NOVALIDATE keyword and support constraint option (#8890) @pranaysb
- feat(db2): support all COMMENT ON object types (#8908) @bekoenig
- feat(flink): support common Flink 1.20 SQL constructs (#8912) @kalanyuz
- RF02: list ignore_words and ignore_words_regex in config_keywords (#8907) @rawsun007
- Clarify CV06 diagnostics for misplaced semicolons (#8911) @sugarzzzcccsss
- perf(core): cut three fixed costs that every linted file pays (#8909) @joshmarkovic
- AM01: Don't flag DISTINCT ON used with GROUP BY (#8919) @555aaditya
- Add indented_using_on_newline to indent ON/USING below a join target on its own line (#8864) @pjpscriv, @cubic-dev-ai[bot]
- Snowflake: Support data metric functions on tables and views (#8885) @sai-sakalam
- SQLite: stop parsing bare functions and literals as column references (#8903) @kennywu411-dev
- Bracketed: drop the redundant trailing gap match (#8848) @WittierDinosaur, @claude, Danny Jones
- fix(sqlite): add PARTIAL and SIMPLE unreserved keywords for foreign key MATCH clause (#8880) @askarshabdanov1-collab
- T-SQL: Accept signed values and bare CACHE in CREATE SEQUENCE (#8875) @555aaditya
- SparkSQL: Support named parameter markers (#8765) @WittierDinosaur, @claude
- perf(reflow): find alignment siblings in a single walk (#8869) @Duo-ee, adenyoung
- T-SQL: Support ENABLE TRIGGER statement (#8865) @555aaditya
- fix(redshift): parse SHOW statements (#8857) @Duo-ee, adenyoung
- fix(trino): parse TRUNCATE TABLE statements (#8858) @Duo-ee, adenyoung
- Add dbt JSON conversion helpers to the Jinja templater (#8853) @hector2394
- fix(clickhouse): preserve case-sensitive function names (#8852) @hector2394
- Databricks: support SQL scripting and stored procedures (#8847) @taslater, @claude
- SparkSQL/Databricks: accept keywords used as identifiers, JSON path wildcards and bracketed set operands (#8846) @taslater, @claude
- Databricks: support GEOGRAPHY and GEOMETRY types (#8851) @taslater, @claude
- fix(bigquery): parse date parts by argument position (#8703) @normaltank
- fix: support Click 8.5.0 (#8648) @Sameera-14, @WittierDinosaur
- CV06: preserve line-comment boundaries when moving newline semicolons (#8819) @sunxiuguo
- fix(snowflake): support DCM stream, procedure and task definitions (#8838) @hector2394
- fix(jinja): support dbt materialization blocks in the Jinja templater (#8704) @ozenyunus35
- Fix line-range noqa directive matching with disable_noqa_except (#8834) (#8837) @manjirisharma
- Placeholder templater: add a Databricks parameter style (#8544) @taslater, @claude
- Databricks: support SHOW GRANTS (#8516) @taslater, @claude
- Databricks: parse inline FLOW clauses on streaming tables (#8520) @taslater, @claude
- parser: name the unexpected token in leftover unparsable messages (#8559) @taslater
- Databricks: allow %-prefixed body lines in a magic cell (#8545) @taslater, @claude
- Postgres: Support CREATE, ALTER and DROP TABLESPACE (#8830) @ozenyunus35
- Enable fixed_suffix in config (#8796) @victorwon2001
- Snowflake: allow indentation for CREATE and ALTER FILE FORMAT (#8641) @ryanakml
- Fix table-name extraction in the basic API example (#8774) @Insecshin
- Keep following statements executable when CV06 moves a semicolon (#8811) @Jackmeson1, @claude
- Drop trailing commas before FROM in CV02, AL06 and AL07 doc examples (#8842) @rawsun007
- Fix silent miss on repeated CTE wildcards in set expressions (AM07) (#8542) (#8827) @XTZDevTEch, Tobias Richter
- fix(mysql): add lexer support for DELIMITER and SOURCE, plus related fixes in Rust and Python (#8797) @rfanth, @claude
- Preserve select order for positional column bindings in ST06 (#8795) @Jackmeson1, @claude
- fix(RF01): allow ClickHouse JSON, Tuple and Nested dot access (#8805) @Cayan
- Redshift: support dynamic data masking policies (#8818) @Duo-ee
- Databricks: preserve magic-cell newlines for LT01 (#8841) @Duo-ee
- Support underscores in SQLite numeric literals (#8844) @yagruda
- DuckDB: parse multi-file COPY TO options (#8826) @student-shivamm
- build(deps): bump source-map-js from 1.2.1 to 1.2.2 in /docsv (#8845) @dependabot[bot]
- perf: reuse whole-file reflow sequences and speed up type checks (#8804) @joshmarkovic
- build(deps): bump follow-redirects from 1.16.0 to 1.16.1 in /docsv (#8806) @dependabot[bot]
- Snowflake: Support GIT REPOSITORY statements (#8803) @sai-sakalam
- docs: clarify error-category ignore configuration (#8807) @dsilvadeepal
- Postgres: Support ALTER COLUMN SET EXPRESSION AS (#8705) (#8809) Elena Rostova
- T-SQL: Support HASH indexes and BUCKET_COUNT on memory-optimized tables (#8737) (#8786) @TerraEnginner-dev
- SparkSQL: Support CREATE FUNCTION with a SQL body (#8764) @WittierDinosaur, @claude
- T-SQL: Support $action inside expressions in MERGE OUTPUT clause (#8739) (#8748) @paneendrakumar0
- BigQuery: parse WITH expressions (#8620) @devYRPauli, @claude
- Keep aliases used in WINDOW and other SELECT clauses (AL05) (#8793) @Jackmeson1, @claude
- fix(snowflake): parse date parts by function argument position (#8718) @sunxiuguo
- fix(snowflake): balance indentation for scripting CASE statement (#8690) (#8790) @Dev-Engineer24
- Snowflake: Support bind variables in CREATE/ALTER SECRET options (#8802) @michal-swiatowy, @claude
- T-SQL: Support empty OVER () clause for PERCENTILE_CONT and PERCENTILE_DISC (#8740) (#8788) @XTZDevTEch, Tobias Richter
- Fix dbt return handling in same-file nested Jinja macros (#8789) @Uddoo
- fix(RF04/RF05/CP02): scope column_aliases/table_aliases to the SELECT an alias belongs to (#8524) @udsy19
- Postgres: reject col_name_keywords (e.g. BETWEEN) as bare data types (#6430) (#8588) @mishra-prince
- fix(RF01): extend struct field resolution to six dialects (#8598) @dennisimoo
- fix(mysql): stop silent misparses from the catch-all typed-literal rule (#8610) @rfanth, @claude
- fix(AL05): keep ClickHouse table function aliases in joins, comma lists (#8613) @Cayan
- RF03: don't unqualify correlated references in APPLY / LATERAL subqueries (#8627) @FrankTub, @claude, Frank Tubbing
- T-SQL: parse GROUPING SETS, CUBE and ROLLUP in GROUP BY (#8738) (#8773) @cyber-atharv
- Keep the token text before a Jinja tag inside the token (#8615) @devYRPauli, @claude
- [MRG] Fix LT05 long ORDER BY lines ending with semicolons (#8687) @itzzdev09
- Honor inline dialect directives when loading SQL files (#8664) @Lingikaushikreddy
- Load the --stdin-filename config in render (#8779) @Jackmeson1, @claude
- Oracle: parse flashback query AS OF TIMESTAMP/SCN (#8699) @adhavan18
- ClickHouse: parse the query-level SAMPLE clause (#8696) @adhavan18
- DuckDB: Parse CREATE MACRO IF NOT EXISTS (#8695) @dheeraj-juvvadi, @claude
- SQLite: recognize hexadecimal literals with an uppercase 0X prefix (#8780) @CLCK0622
- Trino: parse MATCH_RECOGNIZE row pattern matching (#8701) @adhavan18
- Postgres: support RETURNING WITH (OLD/NEW AS alias) (PostgreSQL 18) (#8719) @reyhaan07
- DuckDB: parse DESCRIBE and the extra SHOW forms (#8711) @devanshranjan10, @claude
- DuckDB: parse GROUPING SETS, CUBE and ROLLUP in GROUP BY (#8702) @devanshranjan10, @claude
- MariaDB: parse RENAME COLUMN IF EXISTS (#8725) @sovopr
- Keep subquery and row-constructor parentheses in ST08 fixes (#8745) @Jackmeson1, @claude
- LT01: don't glue a prefix operator onto another operator (#8768) @pandasuwu
- SQLite: parse FTS5 UNINDEXED column declarations (#8772) @CLCK0622
- Support LINENO statement in T-SQL dialect (#8775) @yagruda
- perf(runner): send less data to and from worker processes (#8769) @joshmarkovic
- SparkSQL: Support qualified star among function arguments (#8760) @WittierDinosaur, @claude
- SparkSQL: Support chained LATERAL VIEW without AS (#8759) @WittierDinosaur, @claude
- SparkSQL: Allow PRIOR as an identifier (#8758) @WittierDinosaur, @claude
- fix(tsql): parse END CONVERSATION statements (#8755) @oxura
- perf(templater): compile each Jinja macro file once (#8763) @joshmarkovic
- Fix Rust escaping of StringLexer templates (#8753) @yousefissa
- StarRocks: Parse index types and properties (#8762) @01zhas
- Snowflake: Support SECRET statements (#8754) @sai-sakalam
- perf: avoid quadratic work in layout rules (#8743) @joshmarkovic
- perf(reflow): speed up building reflow sequences (#8751) @joshmarkovic
- Postgres: support ENFORCED / NOT ENFORCED constraint attribute (#8694) @devanshranjan10, @claude
- Postgres: support ONLY in VACUUM and ANALYZE (#8712) @devanshranjan10, @claude
- Snowflake: fix ROW ACCESS POLICY parsing allow schema in FQN (#8574) @fozcodes
- docs: remove outdated Snowflake USING note from Rule ST07 (#8715) @Shahzeb-DataEngineer
- DuckDB: Parse CREATE OR REPLACE TYPE (#8698) @dheeraj-juvvadi, @claude
- Keep the null-safe equals operator when ST09 swaps operands (#8710) @Jackmeson1, @claude
- docs: Fix Gitlab image (#8717) @sam-mosleh
- fix(postgres): preserve spacing after VARIADIC (#8623) (#8661) @mikamikasuki, mac
- SparkSQL: Support GROUP BY ALL and keys as an alias (#8730) @WittierDinosaur, @claude
- LT09: Don't move meta segments out of the select clause (#8733) @WittierDinosaur, @claude
- Fix LT02 crash when implicit_indents = require collapses a line break (#8731) @WittierDinosaur, @claude
- perf(LT09): avoid quadratic search in wide select clauses (#8726) @joshmarkovic
- perf(rust): only probe
greedy_matchterminators where their hint hits (#8663) @keraion - docs: Add notes for cubic that were noise or wrong (#8724) @keraion
- DuckDB: Parse list-comprehension position variables (#8676) @dheeraj-juvvadi, @claude
- feat(snowflake): Add Storage Lifecycle Policy DDL support (#8679) @Abhidas747
- T-SQL: allow bare SYSTEM_VERSIONING = ON with no history-table options (#8700) @adhavan18
- Add an RF06 case for a case-sensitive quoted alias in Oracle (#8655) @ColinHouse
- fix(mysql): Make FUNCTION/PROCEDURE parse and indent for MySQL/MariaDB declarations (#8692) @rfanth, @claude
- fix(mysql): parse CASE statements (#8689) @rfanth, @claude
- feat(clickhouse): add support for hypothetical projections (#8601) @AndrewKurg
- build(deps): bump rustls from 0.23.37 to 0.23.45 in /sqlfluffrs (#8684) @dependabot[bot]
- fix: Send diagnostics to stderr in the Rust parser (#8665) @keraion
- fix(mysql): indent procedural bodies, conditions and assignment lists (#8682) @rfanth, @claude
- DuckDB: Parse expressions in SET VARIABLE assignments (#8659) @dheeraj-juvvadi
- docs: link navbar logo to sqlfluff.com (#8683) @alanmcruickshank
- DuckDB: Parse CSV export options in COPY TO (#8672) @dheeraj-juvvadi
- DuckDB: Parse CHECKPOINT statements (#8674) @dheeraj-juvvadi, @claude
- fix(mysql): parse BEGIN...END bodies as compound statements (#8531) @rfanth, @claude
- Databricks: restore LIVE and STREAMING LIVE view support (#8513) @taslater, @claude
- SparkSQL: support EXECUTE IMMEDIATE (#8515) @taslater, @claude
- SQLite: Parse multiple ON CONFLICT clauses in INSERT (#8658) @dheeraj-juvvadi
- SparkSQL/Databricks: accept NOT NULL and COLLATE on a struct field (#8522) @taslater, @claude
- Databricks: parse DROP MATERIALIZED VIEW (#8519) @taslater
- Add sparksql fixtures for CREATE TEMPORARY TABLE with a USING provider (#8656) @ColinHouse
- DuckDB: Parse human-readable ROW_GROUP_SIZE_BYTES values (#8657) @dheeraj-juvvadi
- perf(rust): cut frame-engine allocation and copying (#8650) @keraion
- perf(rust): use a per-process regex cache (#8645) @keraion
- fix: check that verbose-debug compiles (#8652) @keraion
- fix(LT09): preserve comments after SELECT modifiers (#8647) @XerxesC-CN
- LT05: Do not move a trailing comment that contains a template tag (#8617) @devYRPauli, @claude
- Oracle: parse common SQL*Plus SET commands (#8577) @MrDKOz
- build(deps): bump shell-quote from 1.8.3 to 1.12.0 in /docsv (#8644) @dependabot[bot]
- Snowflake: parse Cortex search service REFRESH (#8586) @kovaacs
- Oracle: support DELETE WHERE and INSERT ... WHERE in MERGE (#8541) @adhavan18
- feat(clickhouse): add support for replace table and for clone as (#8591) @AndrewKurg
- Postgres: accept PG 16-17 utility options and ON/OFF/0/1 option values (#8604) @devYRPauli, @claude
- docs: retire legacy Sphinx source after VitePress cutover (#8636) @alanmcruickshank
- fix(CV07): guard one-sided liftable-whitespace fix independently (#8521) @udsy19
- Add multiline-aware CV03 trailing comma policy (#8473) @nickita-khylkouski
- fix(dialect): allow column reference in redshift's exclude syntax (#8633) @luqmansen
- LT05: add a list_wrapping option to fill long lists (#8580) @devYRPauli, @claude
- RF06: Preserve MySQL and MariaDB account quotes (#8638) @yuefdev
- fix(mysql): parse KILL statements (#8584) @rfanth, @claude
- build(deps): bump joi from 17.13.3 to 17.13.8 in /docsv (#8640) @dependabot[bot]
- build(deps): bump postcss from 8.5.14 to 8.5.28 in /docsv (#8639) @dependabot[bot]
- build(deps): bump axios from 1.16.1 to 1.20.0 in /docsv (#8630) @dependabot[bot]
- SparkSQL: accept a table identifier as the CONVERT TO DELTA target (#8517) @taslater, @claude