Repository navigation
feat(rules)!: check audit, test and hook SQL and enforce SQL quality rules - #910
Merged
Merged
Conversation
…ooks
Bind singular and generic audits (including measurement and evidence queries),
SQL-test bodies and inline and named SQL hooks against the same closed relation
shapes as models, so unknown columns, unknown functions (B101) and semantic type
errors fail compile instead of the warehouse. Audit and SQL-test bodies the
parser rejects are P001 syntax errors rather than silent passes.
Every finding names its owner: the SQL test, or the audit with the model and
column it is attached to. Set-operation, comparison and unknown-column findings
show the explicit fix, such as CAST('1' AS NUMBER) in a test's expected rows or
TO_DATE(@date_column) in a generic audit. Refs CHI-459.
…ejects A DuckDB lambda compiles but the project Rules parser cannot read it; the model is reported as rules-unevaluated, fails rules run and compile, and is not counted as evaluated. Refs CHI-382.
…nding expression Native cast, coercible-literal and set-operation findings carry no span, so they landed on the statement start and identical messages were merged. Match each position-less finding to its own cast, literal, set-operation operator or branch projection in source order, and stop merging position-less duplicates: two failing casts are two findings at their own casts. Refs CHI-413.
…tputs and ranking proofs SQBRSQL042 reports non-final CTE output columns no later step reads, with a verified removal fix. SQBRSQL043 caps ranking window sorts at rules.thresholds.max_ranking_order_by (default 5). SQBRSQL044 reports authored string literals longer than rules.thresholds.max_literal_length and points at a constant in the narrowest scope; when other files repeat the identical literal the help lists them and names the nearest common folder's constants directory. Literals generated by @const or macros are not reported. Both threshold remediations show the exact sqlbuild_project.toml setting and current value. SQBRSQL018 now requires ROW_NUMBER, FIRST_VALUE and LAST_VALUE windows to cover a declared unique key, propagated through CTEs, renames, one-to-one joins, GROUP BY, DISTINCT, UNION and QUALIFY deduplication. Rules findings with a fix that format --fix applies now say so: fixable: true in rules JSON, a note in text and compile output. Refs CHI-385.
…g help [settings] require_sql_analysis = true (project file only, default false) accepts sql_analysis false from a MODEL header or a [path_defaults] entry only on SQL the parser cannot read. On a parseable model it is a P009 error at the header key or path_defaults entry that counts the findings it was hiding. sqlbuild_local.toml cannot turn SQL analysis off project-wide under the policy and cannot set require_sql_analysis; --no-sql-analysis still works for one run. Every error and Rule remediation that names a setting now shows the exact file, section and key = value to write and states the current value, and the parser-rejection error shows the exact MODEL header entry. A catalogue scan test keeps loosely named settings out of Python and Rust diagnostics.
… errors format --fix required a clean compile, so on a project with any existing compile error every fix was refused, after recompiling the whole project once per edited file. Verification now compares the fixed compile with the baseline file by file: an edited file may lose diagnostics but not gain any (compared by code, resource and message), its models must keep columns, types, nullability, dependencies and lineage (absent lineage on both sides matches), and nothing else may change. One compile of all edits attributes failures to the file that caused them; files are checked one by one only when a difference is unattributable. Refusals give the specific reason. A file whose SQL cannot be expanded is skipped with a format-fix-skipped warning instead of failing the run.
kvlonge
enabled auto-merge (squash)
October 2, 2026 14:45
Built-in not_null and unique audits on a column their closed target shape contains cannot produce a finding, so they skip native binding; any other case is still bound and reported unchanged. Identical normalized SQL with the same relations is bound once and its result shared, and SQL test bodies are prepared once per distinct body.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
SQL in audits, SQL tests and hooks was never type- or reference-checked, several Rule findings pointed at the statement start, and CHI-385 asked for enforceable SQL quality: no dead CTE columns, bounded ranking sorts, proven-deterministic rankings and no sprawling literals (CHI-459, CHI-382, CHI-413, CHI-385).
Changes
TEST/AUDITacceptsql_analysis falsefor unparseable SQL;--no-sql-analysisskips them.max_ranking_order_by, default 5), SQBRSQL044 long literals (help leads with the narrowest constant scope and lists duplicates). SQBRSQL018 requires a proven key (tie-breaker,unique+not_nullaudit, ormerge/cursor-lessdelete_insertunique_key).sqb format --fixapplies only row-neutral fixes, verifies each file (no new diagnostics; outputs, types, nullability, lineage and dependencies unchanged) and works on projects that already have errors.[settings] require_sql_analysis:sql_analysis falseonly where SQL cannot be parsed.Verification
format --fixremoved ~4,800 dead lines with all 1,022 model outputs identical; second run no-op; new test/audit errors reviewed as genuine.make test,make check-ci; one independent review plus a follow-up.