Skip to content

fix(CV11): preserve the full operand of a shorthand cast - #8392

Merged
peterbud merged 1 commit into
sqlfluff:mainfrom
winklemad:fix/cv11-shorthand-cast-multi-child-operand
Aug 28, 2026
Merged

peterbud merged 1 commit into
sqlfluff:mainfrom
winklemad:fix/cv11-shorthand-cast-multi-child-operand

Conversation

@winklemad

@winklemad winklemad commented Aug 23, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #8391

Brief summary of the change made

CV11's shorthand-cast rewrite assumed the SQL data type was the cast_expression child at a fixed positional index. When the operand parses into more than one child — e.g. an array subscript a[1]::INT (column_reference + array_accessor) — it picked the wrong child, so sqlfluff fix rewrote a[1]::INT into cast(cast(a as [1]) as INT), destroying the subscript.

This locates the data_type child by type and splits the cast_expression into (operand-before-the-type, the type, any chained casts after it), so the full left operand is preserved. a[1]::INT now correctly becomes cast(a[1] as INT), and the convert styles preserve it too. Chained shorthand casts like 1::int::text are handled by the same split.

Added CV11 rule test cases (test/fixtures/rules/std_rule_cases/CV11.yml) covering the array-subscript and nested-operand cases for the cast and both convert targets, plus a plain-cast control to confirm simple casts are unchanged. The new cases fail on main (showing the corruption) and pass with this change; the full CV11 suite stays green.

Are there any other side effects of this change that we should be aware of?

No — the change only affects how the operand/type boundary is located within a cast_expression; simple x::INT casts are unaffected.

AI usage

I used an AI assistant (Claude Code) to help navigate the rule code and draft the fix and test fixtures. I found and reproduced the bug myself against sqlfluff 4.3.0 (the a[1]::INT → cast(cast(a as [1]) as INT) case), verified the root cause is the fixed-index child selection, confirmed the new tests fail on main and pass after the change, and confirmed the existing CV11 suite still passes. I've reviewed every line and stand by it.


Summary by cubic

Preserves the full operand when rewriting CV11 :: shorthand casts. Previously multi‑segment operands (e.g., a[1]::INT) were split incorrectly and rewritten as cast(cast(a as [1]) as INT)/convert(INT, convert([1], a)); now they become cast(a[1] as INT)/convert(INT, a[1]). Chained shorthand casts (e.g., 1::int::text) still rewrite correctly, and simple casts are unchanged.

  • Locate the data_type child by type and split the cast_expression into operand, type, and later casts via _split_shorthand_cast; use this at all shorthand sites.
  • Update _convert_fix_list to accept a sequence for the value argument so multi‑segment operands survive.
  • Add CV11 rule cases for array subscripts and nested operands; existing CV11 tests remain green.

Written for commit e2b0b62. Summary will update on new commits.

Review in cubic

The CV11 shorthand-cast rewrites located the value and the target type by
fixed positional index inside the cast_expression. When the left operand
parses into more than one segment -- an array subscript such as a[1] is a
column_reference plus an array_accessor -- the array_accessor was mistaken
for the target type, so a[1]::INT was rewritten to cast(cast(a as [1]) as
INT) / convert(INT, convert([1], a)), destroying the subscript.

Find the target type by locating the data_type child (as the preferred=cast
path already did) and treat everything before it as the value. Factor that
split into a shared helper and use it at all shorthand sites. _convert_fix_list
now takes the value as a segment sequence so a multi-segment operand survives.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Results ✅

Name    Stmts   Miss  Cover   Missing
-------------------------------------
TOTAL   22865      0   100%

270 files skipped due to complete coverage.

@peterbud peterbud left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @winklemad and welcome to the community.

@peterbud
peterbud added this pull request to the merge queue Aug 28, 2026
Merged via the queue into sqlfluff:main with commit 642e2e4 Aug 28, 2026
51 checks passed
benfdking added a commit to quarylabs/sqruff that referenced this pull request Oct 26, 2026
… (#8427) (#5154)

* fix(redshift): parse SELECT EXCLUDE after the full select list (#8270)

## Summary
- Move Redshift `EXCLUDE` from a wildcard/item suffix on
  `WildcardExpressionSegment` to a select-clause-level clause, mirroring
  SQLFluff: `EXCLUDE` now terminates the select list only after the first
  item, so `SELECT EXCLUDE` still parses as a column while
  `SELECT *, a, EXCLUDE x` is rejected.
- Add a Redshift `SelectClauseElementSegment` that excludes bare `EXCLUDE`
  from being treated as an implicit column alias (without restricting
  `EXCLUDE(...)` expressions or `AS EXCLUDE` aliases), and allow an
  unbracketed delimited identifier list after `EXCLUDE`.
- Port the upstream `select_exclude` SQL/YAML fixtures and add a Rust
  rejection test covering `SELECT ..., EXCLUDE ...` (comma before EXCLUDE).

Ported from SQLFluff f96b816401e06faa525e436aca52c4d4ba419569
sqlfluff/sqlfluff#8270
sqlfluff/sqlfluff@f96b816

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_018PFPYTfUipLRtsgPurtiHk

* feat(snowflake): WHILE/LOOP/REPEAT/CASE scripting control flow (#8344)

## Summary
- Port Snowflake Scripting control-flow statements: WHILE...DO/LOOP, bare
  LOOP, REPEAT...UNTIL, BREAK/CONTINUE/ITERATE and the CASE statement, and
  extend FOR...IN to cover the counter loop ([REVERSE] <start> TO <end>), the
  DO/LOOP body keywords and optional closing labels.
- Add the BREAK/ITERATE/LOOP/REPEAT/REVERSE/UNTIL/WHILE unreserved keywords,
  the repeat_loop_statement/scripting_break_statement/scripting_case_statement
  syntax kinds, and teach the ScriptingBlockStatement terminator and the LSP
  semantic highlighter about the new loop/case statements.
- Add the scripting_control_flow Snowflake fixture and regenerate dialects.md.

Ported from SQLFluff dc44bc5491b312d6ea7657eea9fe7b7417a08983
sqlfluff/sqlfluff#8344
sqlfluff/sqlfluff@dc44bc5

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01649Di8HJEdK3zFSnrTBH5d

* fix(AM07): correct "seleect" typo in rule docstring (#8381)

## Summary
- Fix the "seleect" -> "select" typo in the AM07 rule best-practice docstring
- Regenerate docs/reference/rules.md via the docs codegen to match

Ported from SQLFluff 8d0e59e30f21d122d82b3eaaa65010a8f0271e9f
sqlfluff/sqlfluff#8381
sqlfluff/sqlfluff@8d0e59e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01MBUa8i6MSeHHTHkbgFjea2

* feat(snowflake): accept the exception name on RAISE (#8386)

## Summary
- Extend `ScriptingRaiseStatementSegment` to parse an optional exception name after `RAISE`, matching Snowflake Scripting semantics (the name is omitted only when re-raising inside an exception handler).
- Port the added `raise_statement` fixtures (DECLARE ... EXCEPTION + RAISE <name>, nested blocks with LET/RETURN) and regenerate the snowflake `.yml` parse tree.

Ported from SQLFluff e8e8c5d24dee8371acb94177fd8a7a86a783151c
sqlfluff/sqlfluff#8386
sqlfluff/sqlfluff@e8e8c5d

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011Y4BbJGjQSBWXiBD9mKLNE

* chore: advance .sqlfluff-sha for docs-only AGENTS.md refresh (#8374)

## Summary
- SQLFluff #8374 only refreshes `sqlfluffrs/AGENTS.md`, documentation for
  SQLFluff's own internal experimental Rust port (its `sqlfluffrs_rules`
  crate: CP01/CP03/CP04). sqruff has no equivalent file or component, so
  there is nothing to port — only `.sqlfluff-sha` is advanced.

Ported from SQLFluff b0ec34c4475bc614ec3d968d4b90791f15a4250a
sqlfluff/sqlfluff#8374
sqlfluff/sqlfluff@b0ec34c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HPYeQhihpARhPdbUSKv8dX

* chore: advance .sqlfluff-sha for SQLFluff CI/dependabot update (#8400)

## Summary
- Advance `.sqlfluff-sha` to track SQLFluff commit 6166dcc (PR #8400).
- The upstream change is CI-only: it pins `actions/upload-artifact` and
  `actions/download-artifact` to commit SHAs across SQLFluff's Python/dbt/PyPI
  GitHub Actions workflows and adds a `.github/dependabot.yml` for the
  github-actions ecosystem. All of it is specific to SQLFluff's Python
  packaging and CI; sqruff uses Bazel-based CI and already has its own
  dependabot configuration, so none of these files map onto sqruff. No sqruff
  code change is required — this is a tracking-SHA advance only.

Ported from SQLFluff 6166dcc5059d7d74b8329c38dd49828f22da4b05
sqlfluff/sqlfluff#8400
sqlfluff/sqlfluff@6166dcc

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EqDoykXZgKrStbNCTANkcq

* fix: parse MySQL IF statements as ordered compound statements (#8380)

## Summary
- Rewrote the MySQL/MariaDB `IfExpressionStatement` grammar as an ordered
  `Sequence` and introduced an `IfStatementListSegment` (`if_statement_list`)
  holding the statements in each THEN/ELSEIF/ELSE branch, matching SQLFluff.
- Added the `IfStatementList` syntax kind, handled it in the LSP semantic
  highlighter, and regenerated the mysql/mariadb IF fixtures and dialect docs.

Ported from SQLFluff e28afab6f17b6b158da5a5efc7d8bf882c231d00
sqlfluff/sqlfluff#8380
sqlfluff/sqlfluff@e28afab

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RNJW5C9jPm7CKJjZB8XpDp

* feat(jinja): support custom Jinja delimiters for Snowflake CLI (#8277)

## Summary
- Plumb the six Jinja delimiter overrides (`variable_/block_/comment_start_string`
  and `_end_string`) from config through to the Python Jinja templater, splatting
  them into the `SandboxedEnvironment` and using them when generating variants and
  deciding the literal-only fast path.
- Build the Jinja analyzer's open/close tag regexes from the environment's
  configured delimiters so custom delimiters (e.g. `<% %>`) are traced correctly.
- Make rule JJ01 read the configured delimiter pairs (longest open first) so it
  lints and fixes whitespace in custom-delimited tags, not just `{{ }}`/`{% %}`/`{# #}`.

Ported from SQLFluff 6f65d50151e8db014768838b36d0a0058dbfde4a
sqlfluff/sqlfluff#8277
sqlfluff/sqlfluff@6f65d50

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01N19MQAdjTXBGxuPjzhsqgN

* chore: auto-fix formatting

* feat(clickhouse): support CONSTRAINT ... CHECK/ASSUME table constraints (#8388)

## Summary
- Add a ClickHouse `TableConstraintSegment` override so `CONSTRAINT <name> CHECK/ASSUME <expr>` table constraints parse correctly (previously the CHECK form was mis-parsed as a column definition named `CONSTRAINT`).
- Register `ASSUME` as an unreserved ClickHouse keyword.
- Port the upstream `create_table` fixture additions and regenerate the clickhouse parse-tree YAML.

Ported from SQLFluff 522761ebc239ffb936f82bd6d63b25eaad43cdcf
sqlfluff/sqlfluff#8388
sqlfluff/sqlfluff@522761e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tf8QJZPSGxqtsSuT8jrvj3

* chore: auto-fix formatting

* fix(CV11): preserve the full operand of a shorthand cast (#8392)

## Summary
- The `::` shorthand-cast rewrite split its children by fixed positional
  index, so a multi-segment left operand (e.g. the array subscript `a[1]`,
  which parses as a column_reference plus one or more array_accessor children)
  was mistaken for the target type. Introduce `split_shorthand_cast`, which
  locates the first `data_type` child and keeps the whole left operand intact,
  and use it in all four shorthand branches (consistent cast/convert, preferred
  cast/convert).
- Let `convert_fix_list` accept the converted value as a slice so a
  multi-segment operand is spliced in whole, matching the SQLFluff change.
- Port the six new CV11 fixture cases covering array-subscript operands under
  consistent/cast/convert modes and the unchanged chained-cast case.

Ported from SQLFluff 642e2e4a34a8e8afd36a45debe8bd3ffcf106c37
sqlfluff/sqlfluff#8392
sqlfluff/sqlfluff@642e2e4

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Rc9h69HUWFkssagQJa8iEB

* feat(snowflake): custom incremental dynamic tables (#8403)

## Summary
- Add CUSTOM_INCREMENTAL refresh mode and the BACKFILL FROM / START AT (...)
  dynamic-table options, and accept the unbounded CHANGES() form (empty or
  INFORMATION-only, no time bounds) used by custom incremental dynamic tables.
- Add BACKFILL and CUSTOM_INCREMENTAL as unreserved Snowflake keywords.
- Port the create_dynamic_table_custom_incremental fixture and its generated
  parse tree.

Ported from SQLFluff 5d7c04ba05e4c5612380f66eb6bb96cb9a2db4ee
sqlfluff/sqlfluff#8403
sqlfluff/sqlfluff@5d7c04b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Awvoy3JUXzPfE3nYvC8wjx

* fix(reflow): ignore alignment predecessors from other lines (#8411)

## Summary
- Port SQLFluff #8411: when computing aligned inline spacing, skip siblings
  whose preceding code segment lives on an earlier line. A sibling that is the
  first code on its line has a `last_code` from an earlier line whose column is
  unrelated to where the sibling starts; counting it inflated the alignment
  target and padded every other line to match (e.g. leading commas with T-SQL
  `=` aliases getting two trailing spaces).
- Added a regression test (`test_reflow_respace_align_ignores_predecessor_on_another_line`)
  mirroring the upstream respace test for sqlfluff/sqlfluff#8256.

Ported from SQLFluff 0f1037bcb2fa10b529c23c3fb95bfc3fdaaadbe5
sqlfluff/sqlfluff#8411
sqlfluff/sqlfluff@0f1037b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016XJuKnVGBn4kkwa3AHFRye

* feat(snowflake): CREATE DATA METRIC FUNCTION, TABLE(...) signatures, MEMOIZABLE and CREATE FUNCTION options (#8352)

## Summary
- Add `CreateDataMetricFunctionStatementSegment` (CREATE [OR REPLACE] [SECURE] DATA METRIC FUNCTION ... RETURNS NUMBER), its named TABLE(...) parameter list and NUMBER-only return type, plus the `create_data_metric_function_statement` syntax kind and keywords `MEMOIZABLE`/`METRIC`.
- Add `FunctionSignatureParameterListSegment` accepting the TABLE(...) typed signature of data metric functions, and wire it into ALTER/DROP FUNCTION and GRANT/REVOKE access objects.
- Extend `CreateFunctionStatementSegment` with `MEMOIZABLE`, a nullable `[NOT] NULL` return type and the `ARTIFACT_REPOSITORY` option; port the SQLFluff fixtures and regenerate dialect docs.

Ported from SQLFluff 6ec9260c67a19267e339c99f6245b35942802fe3
sqlfluff/sqlfluff#8352
sqlfluff/sqlfluff@6ec9260

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01GbJMV1m1SGGBUnPknCCGaM

* feat(snowflake): add grammar for alert DDL (#8420)

## Summary
- Add `CreateAlertSegment`, `AlterAlertSegment` and the shared
  `AlertConditionSegment` to the Snowflake dialect, covering
  `CREATE [OR REPLACE] ALERT ... IF (EXISTS (...)) THEN <stmt>`,
  the full `ALTER ALERT` surface (RESUME/SUSPEND, SET/UNSET props and
  tags, MODIFY CONDITION/ACTION) and `DROP ALERT`, plus the new
  `create_alert_statement`, `alter_alert_statement` and `alert_condition`
  syntax kinds and the keywords `CONDITION`, `RUNBOOK` and
  `SUSPEND_ALERT_AFTER_NUM_FAILURES`.
- Port the SQLFluff alert fixtures and regenerate their Snowflake parse
  trees; map the new statement kinds to no semantic token in the LSP.

Ported from SQLFluff 281fe0012d800fb304c63ea1f66d578c813db5af
sqlfluff/sqlfluff#8420
sqlfluff/sqlfluff@281fe00

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011EJXnd57tEQyeCMWy7PhaA

* chore: auto-fix formatting

* chore: advance .sqlfluff-sha for docs-only PyPI link fix (#8413)

## Summary
- Advance .sqlfluff-sha to SQLFluff 8b7339f458bacbe29d76ee48c0dec34e2fb4cbee.
- Upstream change is docs-only: it fixes a link in SQLFluff's CONTRIBUTING.md
  pointing at the `publish-sqlfluff-release-to-pypi.yaml` GitHub Actions
  workflow. This is SQLFluff-specific Python/PyPI release tooling with no
  equivalent in sqruff (a Rust project), so no code or fixture change is
  needed.

Ported from SQLFluff 8b7339f458bacbe29d76ee48c0dec34e2fb4cbee
sqlfluff/sqlfluff#8413
sqlfluff/sqlfluff@8b7339f

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01ADpyBDTgWv7szedTZ8HbQd

* chore: advance .sqlfluff-sha for CI dependabot GitHub Actions bump (#8405)

## Summary
- SQLFluff #8405 is a dependabot `build(deps)` bump of 16 GitHub Actions
  plus a cosmetic YAML casing normalization (`True`/`False` ->
  `true`/`false`) in `test/fixtures/rules/std_rule_cases/LT02-indent.yml`.
- The CI/workflow changes are Python-repo tooling with no sqruff equivalent.
  The LT02 fixture config is already present in sqruff in the correct form
  (lowercase booleans; `implicit_indents: forbid`), so no fixture change is
  needed. Skip-only SHA advance.

Ported from SQLFluff a5dd11eeae0cede92a5e7f152b7dfda731e2996b
sqlfluff/sqlfluff#8405
sqlfluff/sqlfluff@a5dd11e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01XavdStop6NKWs3n5qm9pxq

* fix: Bracketed no longer matches empty brackets when content is required (#8406)

## Summary
- Port the core `Bracketed` grammar fix: when the content grammar contains
  required (non-optional) elements, an empty bracket body no longer matches in
  any parse mode, so other grammars that can match empty brackets are tried or
  the surrounding grammar marks the section as unparsable (sqlfluff/sqlfluff#8368).
- Mark content optional where empty brackets are legitimately allowed, mirroring
  SQLFluff's dialect fixes: BigQuery `OPTIONS()`, ClickHouse `ORDER BY ()` and the
  double-paren function pattern, and Doris dynamic-partition lists.
- Fix two pre-existing sqruff divergences the stricter matching now exposes: the
  nullary T-SQL date functions (`GETDATE()`, `SYSDATETIME()`, ...) are parsed as
  regular functions instead of date-part functions (matching SQLFluff), and the
  empty struct literal (`STRUCT()`) is serialised as `typed_struct_literal` /
  `struct_literal` so spacing rules apply correctly (matching SQLFluff).
- Regenerate the affected dialect parse fixtures and the dialect reference docs,
  and add grammar test cases for the empty-bracket behaviour.

Ported from SQLFluff 39e4f1c409b39de1aef40c351f67085e0d9138f1
sqlfluff/sqlfluff#8406
sqlfluff/sqlfluff@39e4f1c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_012ZLS6Hu3u7gan2WYJFHDMH

* feat(snowflake): adaptive/interactive warehouse actions, name-less ALTER WAREHOUSE, ALTER SHARE SET COMMENT, CREATE OR ALTER SHARE (#8360)

## Summary
- Port Snowflake warehouse grammar: ADAPTIVE warehouse type, WAREHOUSE
  GENERATION property (new WarehouseGeneration syntax kind + parser),
  name-less session actions (SUSPEND/RESUME/ABORT) on ALTER WAREHOUSE,
  adaptive ENABLE/DISABLE, interactive ADD/DROP TABLES (...), and
  UNSET DCM PROJECT. Object parameters may now follow the TAG clause on
  CREATE/DEFINE WAREHOUSE.
- Port ALTER SHARE SET COMMENT and CREATE OR ALTER SHARE by moving SHARE
  under the OR ALTER create grammar and folding the ALTER SHARE SET arms
  into one OneOf.
- Add snowflake fixtures (alter_share, alter_warehouse, create_warehouse,
  new create_or_alter_share) with regenerated parse trees; add GENERATION
  keyword.

Ported from SQLFluff 56f9962f31485a9beea502f5257451f2d714c8ae
sqlfluff/sqlfluff#8360
sqlfluff/sqlfluff@56f9962

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_017jDuZRfDb6usXWVyksocGN

* chore: auto-fix formatting

* chore: advance .sqlfluff-sha for CI dependabot GitHub Action bump (#8421)

## Summary
- Advance `.sqlfluff-sha` to track SQLFluff's dependabot bump of the
  `MatteoGabriele/agentscan-action` GitHub Action (2.4.0 -> 2.5.0).
- CI-only change to SQLFluff's own `.github/workflows/agent-scan.yml`; sqruff
  has no equivalent workflow or action, so no code or fixture change is needed.

Ported from SQLFluff 6d88cb1456a04b3888ad4bc2783a3214489522a0
sqlfluff/sqlfluff#8421
sqlfluff/sqlfluff@6d88cb1

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01V4W4kQzW2RSVFwG7iDDebr

* feat(snowflake): event table WITH-less clauses, external table gaps, SHOW/DESC table variants (#8353)

## Summary
- Make the `WITH` prefix optional on event/external table `ROW ACCESS POLICY`
  and `COMMENT` clauses, add `CONTACT (...)`, and add `ON (columns)` to the
  external table row-access policy.
- Support `USING TEMPLATE (...)` and `TABLE_FORMAT = DELTA` on
  `CREATE EXTERNAL TABLE`.
- Extend `SHOW ... TABLES` with `EXTERNAL`/`ICEBERG`/`HYBRID`/`EVENT` variants
  and `APPLICATION [PACKAGE] <name>` object scope; add `DESC EVENT/ICEBERG
  TABLE`; add the `PACKAGE` keyword.

Ported from SQLFluff 8df45b30f2664f00e8bfbf1a67b16d01992c65fb
sqlfluff/sqlfluff#8353
sqlfluff/sqlfluff@8df45b3

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01XtYMNVcLW8CFE3kgYDDfcC

* feat(oracle): column-level USING INDEX on inline PRIMARY KEY/UNIQUE (#8426)

## Summary
- Added an Oracle `ColumnConstraintSegment` override extending ANSI to allow
  an inline `USING INDEX` clause after a column-level `PRIMARY KEY` or `UNIQUE`
  constraint (named or anonymous), mirroring SQLFluff.
- Ported the new/updated `oracle/using_index.sql` and `oracle/alter_table.sql`
  fixtures and regenerated their `.yml` parse trees.

Ported from SQLFluff e692709b24f85ff8e8d6aa24eb063aff37c6b0b0
sqlfluff/sqlfluff#8426
sqlfluff/sqlfluff@e692709

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RZ4MNTcG1PtziSa5R8S1Ct

* fix(RF05): cover underscore-only identifiers that strip to empty (#8422)

## Summary
- Port SQLFluff's RF05 regression tests for all-underscore identifiers, which
  strip to an empty string once the allowed underscores are removed.
- sqruff already produces the correct result here: `"".starts_with('#')` is
  `false` (no Redshift index panic) and `"".chars().all(..)` is vacuously
  `true` (no special-character false positive), so no rule code change is
  needed — the upstream Python fix guards cases Rust semantics already handle.
- Add the redshift and postgres pass fixtures to lock in that behavior.

Ported from SQLFluff 42ebac7be69f9bb1c9a9cd3fede0bdcc7458d724
sqlfluff/sqlfluff#8422
sqlfluff/sqlfluff@42ebac7

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RdQi1XbTLZCG4Lu8fWb6JR

* feat(redshift): scoped permissions in GRANT (#8402)

## Summary
- Add Redshift scoped `GRANT ... FOR <objects> IN DATABASE|SCHEMA <name>`
  grammar via a new `ScopedAccessObjectSegment`
  (SCHEMAS/TABLES/FUNCTIONS/PROCEDURES/LANGUAGES/COPY JOBS/TEMPLATES).
- Extend the Redshift `AccessPermissionSegment` with DROP and ALTER so
  scoped grants like `GRANT ALTER, DROP FOR TEMPLATES ...` parse.
- Add JOBS, LANGUAGES and TEMPLATES unreserved keywords and port the
  upstream grant.sql fixture with its regenerated parse tree.

Ported from SQLFluff 47bc24bfe8f3d7969d65948950f33b9b857f9124
sqlfluff/sqlfluff#8402
sqlfluff/sqlfluff@47bc24b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01U24FRqDphq9cazZgEMVk8N

* chore: advance .sqlfluff-sha for docs-site tooling change (#8412)

## Summary
- Advance `.sqlfluff-sha` to eabdba02 (SQLFluff #8412), which only changes
  SQLFluff's VitePress docs site (permalink redirects, mixed-builder version
  picker, assemble/inject scripts and their Python tests).
- Docs-site infrastructure only; nothing maps to sqruff's Rust codebase, so
  no code or fixture changes are needed.

Ported from SQLFluff eabdba0230a025a07a23860ba445f6535175b7eb
sqlfluff/sqlfluff#8412
sqlfluff/sqlfluff@eabdba0

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VX8pxqWx6rjTY5jRjZQx8w

* chore: advance .sqlfluff-sha for release-workflow env hardening (#8375)

## Summary
- SQLFluff #8375 hardens its own `create-release-pull-request.yaml` CI
  workflow by passing `newVersionNumber` through an environment variable
  instead of inlining it in the shell commands.
- This touches only SQLFluff's Python release tooling; sqruff has no
  equivalent workflow (`util.py release` / `create-release-pull-request.yaml`
  do not exist), so no code change is needed — only the `.sqlfluff-sha`
  marker advances.

Ported from SQLFluff e64a69ccc5391c492496d0783990e76ebd95b3cf
sqlfluff/sqlfluff#8375
sqlfluff/sqlfluff@e64a69c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_0145UKyMnuFjv1LHAs85cy5c

* fix(reflow): anchor duplicate-whitespace fixes on the whitespace removed (#8419)

## Summary
- Anchor each "Unnecessary trailing whitespace" lint result in `process_spacing`
  on the `ws` segment being removed instead of the last segment of the buffer,
  so for three or more adjacent whitespaces every removed whitespace is its own
  anchor rather than all results pointing at the final segment.
- Add a `process_spacing` unit test asserting each pruned whitespace anchors its
  own result/fix and the kept whitespace is never targeted.

Ported from SQLFluff ddd83f1d7546dfb7cbcbca829cb649b2415c996c
sqlfluff/sqlfluff#8419
sqlfluff/sqlfluff@ddd83f1

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZfRoSfBCiqCWvPJuzKFma

* feat(sqlite): add ATTACH, DETACH, VACUUM, REINDEX, ANALYZE statements (#8427)

- Port SQLite ATTACH/DETACH DATABASE, VACUUM (with INTO), REINDEX and ANALYZE
  statement grammar from SQLFluff and wire them into the SQLite StatementSegment.
- Add AttachStatement, DetachStatement and ReindexStatement SyntaxKind variants
  (reusing the existing VacuumStatement and AnalyzeStatement kinds) and extend the
  LSP semantic classification to cover them.
- Add the admin_statements fixture (SQL + generated parse tree).

Ported from SQLFluff 63df28344f8bdfb934723aeaf740678aedf2d35b
sqlfluff/sqlfluff#8427
sqlfluff/sqlfluff@63df283

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01LdXANQfk9yazGdsbrnCBm3

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
benfdking added a commit to quarylabs/sqruff that referenced this pull request Oct 26, 2026
* fix(redshift): parse SELECT EXCLUDE after the full select list (#8270)

## Summary
- Move Redshift `EXCLUDE` from a wildcard/item suffix on
  `WildcardExpressionSegment` to a select-clause-level clause, mirroring
  SQLFluff: `EXCLUDE` now terminates the select list only after the first
  item, so `SELECT EXCLUDE` still parses as a column while
  `SELECT *, a, EXCLUDE x` is rejected.
- Add a Redshift `SelectClauseElementSegment` that excludes bare `EXCLUDE`
  from being treated as an implicit column alias (without restricting
  `EXCLUDE(...)` expressions or `AS EXCLUDE` aliases), and allow an
  unbracketed delimited identifier list after `EXCLUDE`.
- Port the upstream `select_exclude` SQL/YAML fixtures and add a Rust
  rejection test covering `SELECT ..., EXCLUDE ...` (comma before EXCLUDE).

Ported from SQLFluff f96b816401e06faa525e436aca52c4d4ba419569
sqlfluff/sqlfluff#8270
sqlfluff/sqlfluff@f96b816

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_018PFPYTfUipLRtsgPurtiHk

* feat(snowflake): WHILE/LOOP/REPEAT/CASE scripting control flow (#8344)

## Summary
- Port Snowflake Scripting control-flow statements: WHILE...DO/LOOP, bare
  LOOP, REPEAT...UNTIL, BREAK/CONTINUE/ITERATE and the CASE statement, and
  extend FOR...IN to cover the counter loop ([REVERSE] <start> TO <end>), the
  DO/LOOP body keywords and optional closing labels.
- Add the BREAK/ITERATE/LOOP/REPEAT/REVERSE/UNTIL/WHILE unreserved keywords,
  the repeat_loop_statement/scripting_break_statement/scripting_case_statement
  syntax kinds, and teach the ScriptingBlockStatement terminator and the LSP
  semantic highlighter about the new loop/case statements.
- Add the scripting_control_flow Snowflake fixture and regenerate dialects.md.

Ported from SQLFluff dc44bc5491b312d6ea7657eea9fe7b7417a08983
sqlfluff/sqlfluff#8344
sqlfluff/sqlfluff@dc44bc5

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01649Di8HJEdK3zFSnrTBH5d

* fix(AM07): correct "seleect" typo in rule docstring (#8381)

## Summary
- Fix the "seleect" -> "select" typo in the AM07 rule best-practice docstring
- Regenerate docs/reference/rules.md via the docs codegen to match

Ported from SQLFluff 8d0e59e30f21d122d82b3eaaa65010a8f0271e9f
sqlfluff/sqlfluff#8381
sqlfluff/sqlfluff@8d0e59e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01MBUa8i6MSeHHTHkbgFjea2

* feat(snowflake): accept the exception name on RAISE (#8386)

## Summary
- Extend `ScriptingRaiseStatementSegment` to parse an optional exception name after `RAISE`, matching Snowflake Scripting semantics (the name is omitted only when re-raising inside an exception handler).
- Port the added `raise_statement` fixtures (DECLARE ... EXCEPTION + RAISE <name>, nested blocks with LET/RETURN) and regenerate the snowflake `.yml` parse tree.

Ported from SQLFluff e8e8c5d24dee8371acb94177fd8a7a86a783151c
sqlfluff/sqlfluff#8386
sqlfluff/sqlfluff@e8e8c5d

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011Y4BbJGjQSBWXiBD9mKLNE

* chore: advance .sqlfluff-sha for docs-only AGENTS.md refresh (#8374)

## Summary
- SQLFluff #8374 only refreshes `sqlfluffrs/AGENTS.md`, documentation for
  SQLFluff's own internal experimental Rust port (its `sqlfluffrs_rules`
  crate: CP01/CP03/CP04). sqruff has no equivalent file or component, so
  there is nothing to port — only `.sqlfluff-sha` is advanced.

Ported from SQLFluff b0ec34c4475bc614ec3d968d4b90791f15a4250a
sqlfluff/sqlfluff#8374
sqlfluff/sqlfluff@b0ec34c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HPYeQhihpARhPdbUSKv8dX

* chore: advance .sqlfluff-sha for SQLFluff CI/dependabot update (#8400)

## Summary
- Advance `.sqlfluff-sha` to track SQLFluff commit 6166dcc (PR #8400).
- The upstream change is CI-only: it pins `actions/upload-artifact` and
  `actions/download-artifact` to commit SHAs across SQLFluff's Python/dbt/PyPI
  GitHub Actions workflows and adds a `.github/dependabot.yml` for the
  github-actions ecosystem. All of it is specific to SQLFluff's Python
  packaging and CI; sqruff uses Bazel-based CI and already has its own
  dependabot configuration, so none of these files map onto sqruff. No sqruff
  code change is required — this is a tracking-SHA advance only.

Ported from SQLFluff 6166dcc5059d7d74b8329c38dd49828f22da4b05
sqlfluff/sqlfluff#8400
sqlfluff/sqlfluff@6166dcc

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EqDoykXZgKrStbNCTANkcq

* fix: parse MySQL IF statements as ordered compound statements (#8380)

## Summary
- Rewrote the MySQL/MariaDB `IfExpressionStatement` grammar as an ordered
  `Sequence` and introduced an `IfStatementListSegment` (`if_statement_list`)
  holding the statements in each THEN/ELSEIF/ELSE branch, matching SQLFluff.
- Added the `IfStatementList` syntax kind, handled it in the LSP semantic
  highlighter, and regenerated the mysql/mariadb IF fixtures and dialect docs.

Ported from SQLFluff e28afab6f17b6b158da5a5efc7d8bf882c231d00
sqlfluff/sqlfluff#8380
sqlfluff/sqlfluff@e28afab

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RNJW5C9jPm7CKJjZB8XpDp

* feat(jinja): support custom Jinja delimiters for Snowflake CLI (#8277)

## Summary
- Plumb the six Jinja delimiter overrides (`variable_/block_/comment_start_string`
  and `_end_string`) from config through to the Python Jinja templater, splatting
  them into the `SandboxedEnvironment` and using them when generating variants and
  deciding the literal-only fast path.
- Build the Jinja analyzer's open/close tag regexes from the environment's
  configured delimiters so custom delimiters (e.g. `<% %>`) are traced correctly.
- Make rule JJ01 read the configured delimiter pairs (longest open first) so it
  lints and fixes whitespace in custom-delimited tags, not just `{{ }}`/`{% %}`/`{# #}`.

Ported from SQLFluff 6f65d50151e8db014768838b36d0a0058dbfde4a
sqlfluff/sqlfluff#8277
sqlfluff/sqlfluff@6f65d50

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01N19MQAdjTXBGxuPjzhsqgN

* chore: auto-fix formatting

* feat(clickhouse): support CONSTRAINT ... CHECK/ASSUME table constraints (#8388)

## Summary
- Add a ClickHouse `TableConstraintSegment` override so `CONSTRAINT <name> CHECK/ASSUME <expr>` table constraints parse correctly (previously the CHECK form was mis-parsed as a column definition named `CONSTRAINT`).
- Register `ASSUME` as an unreserved ClickHouse keyword.
- Port the upstream `create_table` fixture additions and regenerate the clickhouse parse-tree YAML.

Ported from SQLFluff 522761ebc239ffb936f82bd6d63b25eaad43cdcf
sqlfluff/sqlfluff#8388
sqlfluff/sqlfluff@522761e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tf8QJZPSGxqtsSuT8jrvj3

* chore: auto-fix formatting

* fix(CV11): preserve the full operand of a shorthand cast (#8392)

## Summary
- The `::` shorthand-cast rewrite split its children by fixed positional
  index, so a multi-segment left operand (e.g. the array subscript `a[1]`,
  which parses as a column_reference plus one or more array_accessor children)
  was mistaken for the target type. Introduce `split_shorthand_cast`, which
  locates the first `data_type` child and keeps the whole left operand intact,
  and use it in all four shorthand branches (consistent cast/convert, preferred
  cast/convert).
- Let `convert_fix_list` accept the converted value as a slice so a
  multi-segment operand is spliced in whole, matching the SQLFluff change.
- Port the six new CV11 fixture cases covering array-subscript operands under
  consistent/cast/convert modes and the unchanged chained-cast case.

Ported from SQLFluff 642e2e4a34a8e8afd36a45debe8bd3ffcf106c37
sqlfluff/sqlfluff#8392
sqlfluff/sqlfluff@642e2e4

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Rc9h69HUWFkssagQJa8iEB

* feat(snowflake): custom incremental dynamic tables (#8403)

## Summary
- Add CUSTOM_INCREMENTAL refresh mode and the BACKFILL FROM / START AT (...)
  dynamic-table options, and accept the unbounded CHANGES() form (empty or
  INFORMATION-only, no time bounds) used by custom incremental dynamic tables.
- Add BACKFILL and CUSTOM_INCREMENTAL as unreserved Snowflake keywords.
- Port the create_dynamic_table_custom_incremental fixture and its generated
  parse tree.

Ported from SQLFluff 5d7c04ba05e4c5612380f66eb6bb96cb9a2db4ee
sqlfluff/sqlfluff#8403
sqlfluff/sqlfluff@5d7c04b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Awvoy3JUXzPfE3nYvC8wjx

* fix(reflow): ignore alignment predecessors from other lines (#8411)

## Summary
- Port SQLFluff #8411: when computing aligned inline spacing, skip siblings
  whose preceding code segment lives on an earlier line. A sibling that is the
  first code on its line has a `last_code` from an earlier line whose column is
  unrelated to where the sibling starts; counting it inflated the alignment
  target and padded every other line to match (e.g. leading commas with T-SQL
  `=` aliases getting two trailing spaces).
- Added a regression test (`test_reflow_respace_align_ignores_predecessor_on_another_line`)
  mirroring the upstream respace test for sqlfluff/sqlfluff#8256.

Ported from SQLFluff 0f1037bcb2fa10b529c23c3fb95bfc3fdaaadbe5
sqlfluff/sqlfluff#8411
sqlfluff/sqlfluff@0f1037b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016XJuKnVGBn4kkwa3AHFRye

* feat(snowflake): CREATE DATA METRIC FUNCTION, TABLE(...) signatures, MEMOIZABLE and CREATE FUNCTION options (#8352)

## Summary
- Add `CreateDataMetricFunctionStatementSegment` (CREATE [OR REPLACE] [SECURE] DATA METRIC FUNCTION ... RETURNS NUMBER), its named TABLE(...) parameter list and NUMBER-only return type, plus the `create_data_metric_function_statement` syntax kind and keywords `MEMOIZABLE`/`METRIC`.
- Add `FunctionSignatureParameterListSegment` accepting the TABLE(...) typed signature of data metric functions, and wire it into ALTER/DROP FUNCTION and GRANT/REVOKE access objects.
- Extend `CreateFunctionStatementSegment` with `MEMOIZABLE`, a nullable `[NOT] NULL` return type and the `ARTIFACT_REPOSITORY` option; port the SQLFluff fixtures and regenerate dialect docs.

Ported from SQLFluff 6ec9260c67a19267e339c99f6245b35942802fe3
sqlfluff/sqlfluff#8352
sqlfluff/sqlfluff@6ec9260

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01GbJMV1m1SGGBUnPknCCGaM

* feat(snowflake): add grammar for alert DDL (#8420)

## Summary
- Add `CreateAlertSegment`, `AlterAlertSegment` and the shared
  `AlertConditionSegment` to the Snowflake dialect, covering
  `CREATE [OR REPLACE] ALERT ... IF (EXISTS (...)) THEN <stmt>`,
  the full `ALTER ALERT` surface (RESUME/SUSPEND, SET/UNSET props and
  tags, MODIFY CONDITION/ACTION) and `DROP ALERT`, plus the new
  `create_alert_statement`, `alter_alert_statement` and `alert_condition`
  syntax kinds and the keywords `CONDITION`, `RUNBOOK` and
  `SUSPEND_ALERT_AFTER_NUM_FAILURES`.
- Port the SQLFluff alert fixtures and regenerate their Snowflake parse
  trees; map the new statement kinds to no semantic token in the LSP.

Ported from SQLFluff 281fe0012d800fb304c63ea1f66d578c813db5af
sqlfluff/sqlfluff#8420
sqlfluff/sqlfluff@281fe00

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011EJXnd57tEQyeCMWy7PhaA

* chore: auto-fix formatting

* chore: advance .sqlfluff-sha for docs-only PyPI link fix (#8413)

## Summary
- Advance .sqlfluff-sha to SQLFluff 8b7339f458bacbe29d76ee48c0dec34e2fb4cbee.
- Upstream change is docs-only: it fixes a link in SQLFluff's CONTRIBUTING.md
  pointing at the `publish-sqlfluff-release-to-pypi.yaml` GitHub Actions
  workflow. This is SQLFluff-specific Python/PyPI release tooling with no
  equivalent in sqruff (a Rust project), so no code or fixture change is
  needed.

Ported from SQLFluff 8b7339f458bacbe29d76ee48c0dec34e2fb4cbee
sqlfluff/sqlfluff#8413
sqlfluff/sqlfluff@8b7339f

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01ADpyBDTgWv7szedTZ8HbQd

* chore: advance .sqlfluff-sha for CI dependabot GitHub Actions bump (#8405)

## Summary
- SQLFluff #8405 is a dependabot `build(deps)` bump of 16 GitHub Actions
  plus a cosmetic YAML casing normalization (`True`/`False` ->
  `true`/`false`) in `test/fixtures/rules/std_rule_cases/LT02-indent.yml`.
- The CI/workflow changes are Python-repo tooling with no sqruff equivalent.
  The LT02 fixture config is already present in sqruff in the correct form
  (lowercase booleans; `implicit_indents: forbid`), so no fixture change is
  needed. Skip-only SHA advance.

Ported from SQLFluff a5dd11eeae0cede92a5e7f152b7dfda731e2996b
sqlfluff/sqlfluff#8405
sqlfluff/sqlfluff@a5dd11e

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01XavdStop6NKWs3n5qm9pxq

* fix: Bracketed no longer matches empty brackets when content is required (#8406)

## Summary
- Port the core `Bracketed` grammar fix: when the content grammar contains
  required (non-optional) elements, an empty bracket body no longer matches in
  any parse mode, so other grammars that can match empty brackets are tried or
  the surrounding grammar marks the section as unparsable (sqlfluff/sqlfluff#8368).
- Mark content optional where empty brackets are legitimately allowed, mirroring
  SQLFluff's dialect fixes: BigQuery `OPTIONS()`, ClickHouse `ORDER BY ()` and the
  double-paren function pattern, and Doris dynamic-partition lists.
- Fix two pre-existing sqruff divergences the stricter matching now exposes: the
  nullary T-SQL date functions (`GETDATE()`, `SYSDATETIME()`, ...) are parsed as
  regular functions instead of date-part functions (matching SQLFluff), and the
  empty struct literal (`STRUCT()`) is serialised as `typed_struct_literal` /
  `struct_literal` so spacing rules apply correctly (matching SQLFluff).
- Regenerate the affected dialect parse fixtures and the dialect reference docs,
  and add grammar test cases for the empty-bracket behaviour.

Ported from SQLFluff 39e4f1c409b39de1aef40c351f67085e0d9138f1
sqlfluff/sqlfluff#8406
sqlfluff/sqlfluff@39e4f1c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_012ZLS6Hu3u7gan2WYJFHDMH

* feat(snowflake): adaptive/interactive warehouse actions, name-less ALTER WAREHOUSE, ALTER SHARE SET COMMENT, CREATE OR ALTER SHARE (#8360)

## Summary
- Port Snowflake warehouse grammar: ADAPTIVE warehouse type, WAREHOUSE
  GENERATION property (new WarehouseGeneration syntax kind + parser),
  name-less session actions (SUSPEND/RESUME/ABORT) on ALTER WAREHOUSE,
  adaptive ENABLE/DISABLE, interactive ADD/DROP TABLES (...), and
  UNSET DCM PROJECT. Object parameters may now follow the TAG clause on
  CREATE/DEFINE WAREHOUSE.
- Port ALTER SHARE SET COMMENT and CREATE OR ALTER SHARE by moving SHARE
  under the OR ALTER create grammar and folding the ALTER SHARE SET arms
  into one OneOf.
- Add snowflake fixtures (alter_share, alter_warehouse, create_warehouse,
  new create_or_alter_share) with regenerated parse trees; add GENERATION
  keyword.

Ported from SQLFluff 56f9962f31485a9beea502f5257451f2d714c8ae
sqlfluff/sqlfluff#8360
sqlfluff/sqlfluff@56f9962

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_017jDuZRfDb6usXWVyksocGN

* chore: auto-fix formatting

* chore: advance .sqlfluff-sha for CI dependabot GitHub Action bump (#8421)

## Summary
- Advance `.sqlfluff-sha` to track SQLFluff's dependabot bump of the
  `MatteoGabriele/agentscan-action` GitHub Action (2.4.0 -> 2.5.0).
- CI-only change to SQLFluff's own `.github/workflows/agent-scan.yml`; sqruff
  has no equivalent workflow or action, so no code or fixture change is needed.

Ported from SQLFluff 6d88cb1456a04b3888ad4bc2783a3214489522a0
sqlfluff/sqlfluff#8421
sqlfluff/sqlfluff@6d88cb1

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01V4W4kQzW2RSVFwG7iDDebr

* feat(snowflake): event table WITH-less clauses, external table gaps, SHOW/DESC table variants (#8353)

## Summary
- Make the `WITH` prefix optional on event/external table `ROW ACCESS POLICY`
  and `COMMENT` clauses, add `CONTACT (...)`, and add `ON (columns)` to the
  external table row-access policy.
- Support `USING TEMPLATE (...)` and `TABLE_FORMAT = DELTA` on
  `CREATE EXTERNAL TABLE`.
- Extend `SHOW ... TABLES` with `EXTERNAL`/`ICEBERG`/`HYBRID`/`EVENT` variants
  and `APPLICATION [PACKAGE] <name>` object scope; add `DESC EVENT/ICEBERG
  TABLE`; add the `PACKAGE` keyword.

Ported from SQLFluff 8df45b30f2664f00e8bfbf1a67b16d01992c65fb
sqlfluff/sqlfluff#8353
sqlfluff/sqlfluff@8df45b3

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01XtYMNVcLW8CFE3kgYDDfcC

* feat(oracle): column-level USING INDEX on inline PRIMARY KEY/UNIQUE (#8426)

## Summary
- Added an Oracle `ColumnConstraintSegment` override extending ANSI to allow
  an inline `USING INDEX` clause after a column-level `PRIMARY KEY` or `UNIQUE`
  constraint (named or anonymous), mirroring SQLFluff.
- Ported the new/updated `oracle/using_index.sql` and `oracle/alter_table.sql`
  fixtures and regenerated their `.yml` parse trees.

Ported from SQLFluff e692709b24f85ff8e8d6aa24eb063aff37c6b0b0
sqlfluff/sqlfluff#8426
sqlfluff/sqlfluff@e692709

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RZ4MNTcG1PtziSa5R8S1Ct

* fix(RF05): cover underscore-only identifiers that strip to empty (#8422)

## Summary
- Port SQLFluff's RF05 regression tests for all-underscore identifiers, which
  strip to an empty string once the allowed underscores are removed.
- sqruff already produces the correct result here: `"".starts_with('#')` is
  `false` (no Redshift index panic) and `"".chars().all(..)` is vacuously
  `true` (no special-character false positive), so no rule code change is
  needed — the upstream Python fix guards cases Rust semantics already handle.
- Add the redshift and postgres pass fixtures to lock in that behavior.

Ported from SQLFluff 42ebac7be69f9bb1c9a9cd3fede0bdcc7458d724
sqlfluff/sqlfluff#8422
sqlfluff/sqlfluff@42ebac7

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01RdQi1XbTLZCG4Lu8fWb6JR

* feat(redshift): scoped permissions in GRANT (#8402)

## Summary
- Add Redshift scoped `GRANT ... FOR <objects> IN DATABASE|SCHEMA <name>`
  grammar via a new `ScopedAccessObjectSegment`
  (SCHEMAS/TABLES/FUNCTIONS/PROCEDURES/LANGUAGES/COPY JOBS/TEMPLATES).
- Extend the Redshift `AccessPermissionSegment` with DROP and ALTER so
  scoped grants like `GRANT ALTER, DROP FOR TEMPLATES ...` parse.
- Add JOBS, LANGUAGES and TEMPLATES unreserved keywords and port the
  upstream grant.sql fixture with its regenerated parse tree.

Ported from SQLFluff 47bc24bfe8f3d7969d65948950f33b9b857f9124
sqlfluff/sqlfluff#8402
sqlfluff/sqlfluff@47bc24b

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01U24FRqDphq9cazZgEMVk8N

* chore: advance .sqlfluff-sha for docs-site tooling change (#8412)

## Summary
- Advance `.sqlfluff-sha` to eabdba02 (SQLFluff #8412), which only changes
  SQLFluff's VitePress docs site (permalink redirects, mixed-builder version
  picker, assemble/inject scripts and their Python tests).
- Docs-site infrastructure only; nothing maps to sqruff's Rust codebase, so
  no code or fixture changes are needed.

Ported from SQLFluff eabdba0230a025a07a23860ba445f6535175b7eb
sqlfluff/sqlfluff#8412
sqlfluff/sqlfluff@eabdba0

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VX8pxqWx6rjTY5jRjZQx8w

* chore: advance .sqlfluff-sha for release-workflow env hardening (#8375)

## Summary
- SQLFluff #8375 hardens its own `create-release-pull-request.yaml` CI
  workflow by passing `newVersionNumber` through an environment variable
  instead of inlining it in the shell commands.
- This touches only SQLFluff's Python release tooling; sqruff has no
  equivalent workflow (`util.py release` / `create-release-pull-request.yaml`
  do not exist), so no code change is needed — only the `.sqlfluff-sha`
  marker advances.

Ported from SQLFluff e64a69ccc5391c492496d0783990e76ebd95b3cf
sqlfluff/sqlfluff#8375
sqlfluff/sqlfluff@e64a69c

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_0145UKyMnuFjv1LHAs85cy5c

* fix(reflow): anchor duplicate-whitespace fixes on the whitespace removed (#8419)

## Summary
- Anchor each "Unnecessary trailing whitespace" lint result in `process_spacing`
  on the `ws` segment being removed instead of the last segment of the buffer,
  so for three or more adjacent whitespaces every removed whitespace is its own
  anchor rather than all results pointing at the final segment.
- Add a `process_spacing` unit test asserting each pruned whitespace anchors its
  own result/fix and the kept whitespace is never targeted.

Ported from SQLFluff ddd83f1d7546dfb7cbcbca829cb649b2415c996c
sqlfluff/sqlfluff#8419
sqlfluff/sqlfluff@ddd83f1

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZfRoSfBCiqCWvPJuzKFma

* feat(oracle): support IF NOT EXISTS in CREATE INDEX (#8445)

## Summary
- Add the optional `IfNotExistsGrammar` after the `INDEX` keyword in the
  Oracle `CreateIndexStatementSegment`, matching `CREATE INDEX IF NOT EXISTS`
  (Oracle 19c Release Update 19.28+).
- Port the upstream `create_index` fixture: collapse the `t_ts_idx` TABLESPACE
  statement onto one line and add an `IF NOT EXISTS` case; regenerate the YAML.

Ported from SQLFluff de90d194a429edd4b539a6e3a293d54f09a2e729
sqlfluff/sqlfluff#8445
sqlfluff/sqlfluff@de90d19

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JtZKJSerKLKUqseZgu1imn

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CV11 autofix corrupts a shorthand cast whose operand has multiple children (e.g. array subscript a[1]::INT)

2 participants