Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
53043e4
Postgres: Fix dialect to allow CTEs in COPY (#7085)
franloza Aug 31, 2025
6e5aecd
Snowflake: add multi_line toggle on csv type copy into <table> (#7107)
julianahrens Aug 31, 2025
86c527b
ClickHouse: Add support for DROP PARTITION and REPLACE PARTITION (#7111)
yuukikuno Aug 31, 2025
5393aa7
Add support for T-SQL binary constants notation (0x, 0xAE, etc.) (#7112)
viblo-majority Sep 1, 2025
ecff46f
Postgres: Support text search configuration statements (#7117)
franloza Sep 6, 2025
6fc36e9
Postgres: Fix parse failure on VARIADIC function calls with named par…
franloza Sep 6, 2025
8f4f1d4
Resolve unused CTE bug (#7095)
reteps Sep 6, 2025
6421419
Postgres: Add support for pg_trgm similarity operators (#7086)
franloza Sep 6, 2025
39c5fd0
Fix mypy error in nested_combine call (#7126)
WittierDinosaur Sep 14, 2025
4d6f970
chore: rename files in trino to comment on (#7125)
benfdking Sep 14, 2025
edb42de
Redshift: Adds NONATOMIC clause support for CREATE PROCEDURE (#7123)
franloza Sep 14, 2025
22934e9
Support brackets in CASE statement condition (#7122)
adam-carruthers Sep 14, 2025
2ad1e3b
fix: allow `STORING` segment in BigQuery `CREATE VECTOR INDEX` (#7119)
agkphysics Sep 14, 2025
9c252f9
TSQL: Rework batch and statement handling (#7113)
peterbud Sep 14, 2025
56a4586
Snowflake: Support warehouse resource constraints (#7128)
WittierDinosaur Sep 15, 2025
655b8f2
Mariadb: Enhance CreateIndex Statement (#7127)
WittierDinosaur Sep 15, 2025
9a5d677
Add `partitioned by` and `cluster by` segments to SparkSQL Create vie…
KikeSenpai Sep 20, 2025
5eecf7d
Fix false positive CV05 detection for T-SQL variable assignments in S…
danparizher Sep 20, 2025
f1ccddd
Streamline release commands (#7005)
WittierDinosaur Sep 20, 2025
73427eb
extend databricks COMMENT ON to include columns (#7140)
VictorAtIfInsurance Sep 24, 2025
44d8c4b
Per Issue 5567 update _common_directives_for_xml to AnyNumberOf (they…
stephen-zabel-q2 Sep 24, 2025
8c65a20
fix[sparksql]: Add support for INSERT INTO REPLACE WHERE/USING statem…
KikeSenpai Sep 24, 2025
fb838bd
CV11: Ignore trino and athena dialects (#7146)
keraion Sep 24, 2025
0038d43
oracle: Add support for utf8 identifiers (#7145)
keraion Sep 24, 2025
eb6cbaa
MySQL: Allow if not exists in create procedure (#7133)
Enterprize1 Sep 24, 2025
604af29
oracle: Support `COLUMN_VALUE` as a bare function (#7144)
keraion Sep 25, 2025
2bb18bd
postgres: Add `DROP COLLATION` statement (#7143)
keraion Sep 25, 2025
114b2fa
Fix typo (#7151)
matthiasbeyer Sep 29, 2025
3ea458a
MariaDB: Adds OR REPLACE clause support for CREATE PROCEDURE and CREA…
franloza Oct 1, 2025
d35ff2d
fix: #7157 (#7158)
LeviticusNelson Oct 3, 2025
b6d321a
TSQL: Allow consecutive semicolons & add rule ST12 (warn and fix) (#7…
axellpadilla Oct 5, 2025
84f5ea1
TSQL: Refactor cursor statements (#7130)
peterbud Oct 5, 2025
97d050e
Add new check for ambiguous`LIMIT` or `OFFSET` without `ORDER BY` (no…
d33bs Oct 6, 2025
099fb2c
SET LANGUAGE statement segment added to tsql dialect. (#7161)
vasiliyk Oct 7, 2025
4ea8861
Correctly handle alias alignment for template siblings
jorenby Aug 8, 2025
d555a8b
Refactor alignment logic to support coordinate spaces
jorenby Aug 8, 2025
5283110
Add alignment coordinate space config
jorenby Aug 8, 2025
e277961
Documentation, formatting, cleanup
jorenby Aug 8, 2025
0174b5e
Add comprehensive test cases for alias alignment with templates
jorenby Sep 15, 2025
5136ec9
Fix documentation warnings in layout.rst
jorenby Oct 6, 2025
334b43f
Mark defensive edge case handlers as excluded from coverage
jorenby Oct 7, 2025
e4dce22
Add pragma no cover for templated content detection in _has_templated…
jorenby Oct 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.idea
/.sqlfluff
**/.DS_Store
.junie

# Ignore Python cache and prebuilt things
.cache
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ repos:
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: [flake8-black>=0.3.6]
additional_dependencies: [flake8-black>=0.3.7]
- repo: https://github.com/pycqa/doc8
rev: v1.1.2
hooks:
Expand Down
9 changes: 4 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,12 @@ need a [GitHub Personal Access Token](https://docs.github.com/en/authentication/
scope, and read permissions on the "Metadata" scope. The reason we need
both read & write access on the "Content" scope is that only tokens with
write access can see _draft_ releases, which is what we need access to).
All maintainers should have sufficient access to generate such a token:
All maintainers should have sufficient access to generate such a token. Once
generated, store it in your env (zshrc, etc) as `SQLFLUFF_GITHUB_TOKEN`. Then:

```shell
source .venv/bin/activate
export GITHUB_REPOSITORY_OWNER=sqlfluff
export GITHUB_TOKEN=gho_xxxxxxxx # Change to your token with "repo" permissions.
python util.py release 2.0.3 # Change to your release number
make shell
make release 3.4.2 # Change to your release number
```

When all of the changes planned for the release have been merged, and
Expand Down
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
.PHONY: help build clean fresh shell start stop
.PHONY: help build clean fresh release shell start stop

.DEFAULT_GOAL := help

# Set VERSION from first argument if provided
VERSION := $(word 2,$(filter-out $(.DEFAULT_GOAL),$(MAKECMDGOALS)))

# Treat flow name as a target (prevents make errors)
$(VERSION):
@:

help: ## Show this available targets
@grep -E '^[/a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'

Expand All @@ -16,6 +23,9 @@ clean: ## Clean up all containers and images
fresh: ## Build the development container from scratch
docker-compose build --no-cache development

release: ## Release a new version
@python util.py release $(VERSION)

shell: ## Start a bash session in the development container
docker-compose exec development bash

Expand Down
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ services:
context: .
dockerfile: ./docker/development/Dockerfile
environment:
- SSH_AUTH_SOCK=/ssh-agent
- GITHUB_REPOSITORY_OWNER=sqlfluff
- GITHUB_TOKEN=${SQLFLUFF_GITHUB_TOKEN}
- POSTGRES_HOST=postgres
- SSH_AUTH_SOCK=/ssh-agent
volumes:
- .:/app
- ./test/fixtures/dbt/profiles_yml:/root/.dbt
Expand Down
55 changes: 53 additions & 2 deletions docs/source/configuration/layout.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,62 @@ the least obvious. The following example illustrates the impact it has.
-- align_scope = file
-- align_within = statement

Templating and alignment coordinate space
-----------------------------------------

When using templating (e.g. Jinja), alignment is for human readability and
stable diffs. SQLFluff aligns based on the source (visible) positions whenever
templated (non-literal) segments are involved in the alignment scope. This
prevents excessive padding caused by the rendered output being longer than the
source template. If all segments are literal (non-templated), alignment uses
the regular templated working positions.

Example (Jinja templating, align alias expressions within a select clause):

.. code-block:: jinja

select
{{ "longtemplated" }} as test_key,
b as b_col

The alignment above is computed against the source text so that both lines line
up visually in the editor, regardless of the rendered length of
``{{ "longtemplated" }}``.

Advanced: coordinate space override
-----------------------------------

You can optionally force the coordinate space either:

1) via the alignment constraint suffix (available for `spacing_before` and
`spacing_after`), or
2) via the `alignment_coordinate_space` key in layout config for the target type.

.. code-block:: ini

[sqlfluff:layout:type:alias_expression]
spacing_before = align:alias_expression:select_clause:bracketed:source

Alternatively, the equivalent can be configured more declaratively:

.. code-block:: ini

[sqlfluff:layout:type:alias_expression]
spacing_before = align
align_within = select_clause
align_scope = bracketed
alignment_coordinate_space = source

Supported values are ``source`` and ``templated``. In most cases, ``source`` is
the recommended choice for readability.

.. code-block:: sql

WITH foo as (
SELECT
a,
b,
c AS first_column
c AS first_column,
d + e AS second_column
)

Expand Down Expand Up @@ -625,7 +676,7 @@ subsections of an :code:`ON` block with each other. If set to :code:`False`

These can also be combined, so if :code:`indented_using_on` config is set to
:code:`False`, :code:`indented_on_contents` is also set to :code:`False`, and
:code:`allow_implicit_indents` is set tot :code:`True` then the SQL would
:code:`allow_implicit_indents` is set to :code:`True` then the SQL would
become:

.. code-block:: sql
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ extend-select = ["I", "D"]
# D418: Function/ Method decorated with @overload shouldn’t contain a docstring
ignore = ["D107", "D105", "D418"]


[tool.ruff.lint.isort]
# Mark sqlfluff, test and it's plugins as known first party
known-first-party = [
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ flake8
flake8-docstrings
pydocstyle!=6.2.0, !=6.2.1 # See: https://github.com/PyCQA/pydocstyle/issues/618
black>=22.1.0
flake8-black>=0.2.4
flake8-black>=0.3.7
ruff
import-linter
yamllint
Expand Down
6 changes: 3 additions & 3 deletions src/sqlfluff/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Export cli to __main__ for use like python -m sqlfluff."""

from sqlfluff.cli.commands import cli
from sqlfluff.cli.commands import cli # pragma: no cover

if __name__ == "__main__":
cli()
if __name__ == "__main__": # pragma: no cover
cli() # pragma: no cover
4 changes: 3 additions & 1 deletion src/sqlfluff/core/config/fluffconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ def __init__(
# If any existing configs are provided. Validate them:
if configs:
validate_config_dict(configs, "<provided configs>")
empty_config: ConfigMappingType = {"core": {}}
empty_overrides: ConfigMappingType = {}
self._configs = nested_combine(
defaults, configs or {"core": {}}, overrides or {}
defaults, configs or empty_config, overrides or empty_overrides
)
# Some configs require special treatment
self._configs["core"]["color"] = (
Expand Down
2 changes: 1 addition & 1 deletion src/sqlfluff/core/helpers/string.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
def curtail_string(s: str, length: int = 20) -> str:
"""Trim a string nicely to length."""
if len(s) > length:
return s[:length] + "..."
return s[:length] + "..." # pragma: no cover
else:
return s

Expand Down
15 changes: 10 additions & 5 deletions src/sqlfluff/dialects/dialect_ansi.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,11 +805,16 @@ class FileSegment(BaseFileSegment):
has no match_grammar.
"""

match_grammar = Delimited(
Ref("StatementSegment"),
delimiter=AnyNumberOf(Ref("DelimiterGrammar"), min_times=1),
allow_gaps=True,
allow_trailing=True,
# Allow leading & trailing delimiters plus runs of delimited statements.
match_grammar = Sequence(
AnyNumberOf(Ref("DelimiterGrammar")),
Delimited(
Ref("StatementSegment"),
delimiter=AnyNumberOf(Ref("DelimiterGrammar"), min_times=1),
allow_gaps=True,
allow_trailing=True,
),
AnyNumberOf(Ref("DelimiterGrammar")),
)

def get_table_references(self) -> set[str]:
Expand Down
17 changes: 16 additions & 1 deletion src/sqlfluff/dialects/dialect_bigquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ class FileSegment(BaseFileSegment):
# NB: We don't need a match_grammar here because we're
# going straight into instantiating it directly usually.
match_grammar = Sequence(
AnyNumberOf(Ref("DelimiterGrammar")),
Sequence(
OneOf(
Ref("MultiStatementSegment"),
Expand All @@ -618,7 +619,7 @@ class FileSegment(BaseFileSegment):
Ref("StatementSegment"),
),
),
Ref("DelimiterGrammar", optional=True),
AnyNumberOf(Ref("DelimiterGrammar")),
)


Expand Down Expand Up @@ -3128,10 +3129,24 @@ class CreateVectorIndexStatementSegment(BaseSegment):
Ref("IndexColumnDefinitionSegment"),
),
),
Ref("StoringSegment", optional=True),
Ref("OptionsSegment"),
)


class StoringSegment(BaseSegment):
"""The `STORING` clause for a `CREATE VECTOR INDEX` statement.

https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_vector_index_statement
"""

type = "storing_segment"
match_grammar: Matchable = Sequence(
"STORING",
Bracketed(Delimited(Ref("SingleIdentifierGrammar"))),
)


class DropVectorIndexStatementSegment(BaseSegment):
"""A `DROP VECTOR INDEX` statement.

Expand Down
1 change: 1 addition & 0 deletions src/sqlfluff/dialects/dialect_bigquery_keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
SOURCE
STAGE
START
STORING
STREAM
STRICT
SUNDAY
Expand Down
45 changes: 45 additions & 0 deletions src/sqlfluff/dialects/dialect_clickhouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,38 @@ class DropUserStatementSegment(ansi.DropUserStatementSegment):
)


class CreateUserStatementSegment(BaseSegment):
"""A `CREATE USER` statement.

As specified in
https://clickhouse.com/docs/en/sql-reference/statements/create/user/
"""

type = "create_user_statement"

match_grammar = Sequence(
"CREATE",
"USER",
Ref("IfNotExistsGrammar", optional=True),
Ref("SingleIdentifierGrammar"),
Ref("OnClusterClauseSegment", optional=True),
# IDENTIFIED BY 'password' or IDENTIFIED WITH ... BY ...
Sequence(
"IDENTIFIED",
Sequence(
"WITH",
Ref("SingleIdentifierGrammar"),
optional=True,
),
Sequence(
"BY",
Ref("QuotedLiteralSegment"),
),
optional=True,
),
)


class DropRoleStatementSegment(ansi.DropRoleStatementSegment):
"""A `DROP ROLE` statement.

Expand Down Expand Up @@ -2119,6 +2151,18 @@ class AlterTableStatementSegment(BaseSegment):
optional=True,
),
),
# ALTER TABLE ... DROP PARTITION|PART partition_expr
Sequence(
"DROP", OneOf("PARTITION", "PART"), Ref("SingleIdentifierGrammar")
),
# ALTER TABLE ... REPLACE PARTITION partition_expr FROM table1
Sequence(
"REPLACE",
"PARTITION",
Ref("SingleIdentifierGrammar"),
"FROM",
Ref("TableReferenceSegment"),
),
),
)

Expand All @@ -2128,6 +2172,7 @@ class StatementSegment(ansi.StatementSegment):

match_grammar = ansi.StatementSegment.match_grammar.copy(
insert=[
Ref("CreateUserStatementSegment"),
Ref("CreateMaterializedViewStatementSegment"),
Ref("DropDictionaryStatementSegment"),
Ref("DropQuotaStatementSegment"),
Expand Down
2 changes: 2 additions & 0 deletions src/sqlfluff/dialects/dialect_clickhouse_keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
"HIERARCHICAL",
"HOUR",
"ID",
"IDENTIFIED",
"IF",
"ILIKE",
"IN",
Expand Down Expand Up @@ -219,6 +220,7 @@
"OR",
"OUTFILE",
"OVERRIDE",
"PART",
"PASTE",
"POPULATE",
"POSTGRESQL",
Expand Down
4 changes: 4 additions & 0 deletions src/sqlfluff/dialects/dialect_databricks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,10 @@ class CommentOnStatementSegment(BaseSegment):
"VOLUME",
Ref("VolumeReferenceSegment"),
),
Sequence(
"COLUMN",
Ref("ColumnReferenceSegment"),
),
# TODO: Split out individual items if they have references
Sequence(
OneOf(
Expand Down
Loading
Loading