Skip to content

feat(rules): repeated JSON parse rule and allow_exceptions setting - #936

Merged
kvlonge merged 3 commits into
mainfrom
feat/json-parse-rule-and-exception-ban
Oct 4, 2026
Merged

kvlonge merged 3 commits into
mainfrom
feat/json-parse-rule-and-exception-ban

Conversation

@kvlonge

@kvlonge kvlonge commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Why

Projects enforce two common policies with custom rules: "parse each JSON payload once per SELECT" and "no rule exceptions or scoped ignores". The first is costly in Python (it walks every model's syntax tree) and is generally useful; the second needs a regex over the project config. Both belong in SQLBuild (CHI-488, CHI-489).

Changes

  • New native rule SQBRSQL045: the same JSON parse function applied to the same column more than once in one SELECT scope (Snowflake/Databricks PARSE_JSON/TRY_PARSE_JSON, BigQuery PARSE_JSON/SAFE.PARSE_JSON, DuckDB json()). Names compare the way each warehouse resolves them; multi-argument wrappers aren't plain columns. Not in the default lint set.
  • New [rules] allow_exceptions (default true). When false, [[rules.rule_exceptions]]/[[rules.rule_ignores]] are config errors and inline -- sqb: ignore directives become SQBRSQL000 errors that suppress nothing. The project-wide ignore list stays allowed. Help shows the exact TOML and current value; sqb format uses the same loader.
  • Docs and skill references.

Verification

  • Rust rule cases across scopes, wrappers, quoting and dialects; real-CLI tests for compile, rules run and format.
  • One independent review plus follow-up; make test, make check-ci.

SQBRSQL045 reports the same JSON parse function applied to the same
column more than once in one SELECT scope, at the second call, and names
the count, for example `TRY_PARSE_JSON(e.value) is parsed 3 times in one
SELECT`. Parse the payload once in the CTE that reads it and read every
field from that column.

Each SELECT is its own scope; nested SELECTs, subqueries, CTE bodies and
set-operation branches are checked separately. Calls are keyed by
function, table qualifier and column (case-insensitive) through
parentheses, LOWER, UPPER, TRIM, CAST, TRY_CAST and the first COALESCE
argument. Parse functions: Snowflake and Databricks PARSE_JSON and
TRY_PARSE_JSON, BigQuery PARSE_JSON and SAFE.PARSE_JSON, DuckDB and
MotherDuck JSON. PostgreSQL and SQL Server have no single-argument
equivalent. The check is native and walks each body once. Refs CHI-488.
With `[rules] allow_exceptions = false` (default true), any
[[rules.rule_exceptions]] or [[rules.rule_ignores]] entry fails rules
configuration loading, so compile and rules run stop with an error that
counts the entries, states the current value and shows the exact TOML to
allow them again. Each inline `-- sqb: ignore` directive becomes a
SQBRSQL000 error at the directive and suppresses nothing, so the hidden
finding is reported too. The project-wide `ignore` list stays allowed.

Document inline suppressions and the new setting in the Rules and
project configuration references. Refs CHI-489.
@kvlonge
kvlonge enabled auto-merge (squash) October 4, 2026 10:03
@kvlonge
kvlonge merged commit f16a20a into main Oct 4, 2026
36 checks passed
@kvlonge
kvlonge deleted the feat/json-parse-rule-and-exception-ban branch October 4, 2026 10:50
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.

1 participant