Repository navigation
fix(test): isolate unit-test SQL per model and reserve helper names - #986
Merged
Merged
Conversation
SQL unit tests hoisted the CTEs of the model under test into the test's top-level WITH for `__actual__` and also nested the model again as its `__ref__` CTE. Every model was emitted twice, and a hoisted name such as `final` could resolve inside a later step's nested WITH on warehouses that look up outer CTE names first. Each planned model step is now defined once as `__ref__<model> AS (<model SQL>)`, its own CTEs stay nested, and `__actual__<model>` reads `SELECT * FROM __ref__<model>`. Only T-SQL, which rejects a nested WITH, still flattens model CTEs, renaming collisions as before.
Every mock CTE carried a copy of every test-defined helper CTE, so a helper such as `expected_rows` used only by an assertion was repeated in each fixture. Mocks now contain only their own SQL, and the helpers a mock reads are defined once in the test's top-level WITH. A mock inlined into model SQL, where a model CTE could shadow a top-level helper, still carries only the helpers it reads.
`sqb test --json-output` checks had no timing, although the text output shows one per test. Each SQL test check now reports `duration_ms` from the same lifecycle record, matching the unit used by JSON assets.
JSON output looked up SQL test results by test name only, so parameterized cases, whose events carry the path, block and case identity, were dropped from checks. Use the shared sql_test_resource_id for both.
Helpers placed at the top level of the test query could be read by a nested model CTE or bare table of the same name on warehouses where outer CTEs win or are ambiguous. With analysis, helpers now get reserved __helper__<name> CTE names and test-authored readers are rewritten through the AST; without analysis they stay inline in the fixtures that read them. Rendering refuses any nested CTE that reuses a top-level name, a test CTE that redefines a helper is a compile error, and model bodies drop a trailing terminator in planning so downstream steps share one definition.
A WINDOW clause entry such as `base AS (ORDER BY id)` was read as a CTE, so an assertion with a named window sharing a helper's name was refused. Only commas directly inside a WITH list now separate CTE definitions.
kvlonge
enabled auto-merge (squash)
October 6, 2026 18:26
…-test SQL shape The guards hash every compiled artifact, including compiled unit-test SQL, whose shape changed intentionally (models nested once under __ref__). Compile JSON and model artifacts are unchanged.
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 unit tests that chain models could read the wrong relation. Model CTEs were hoisted to the top level of the test query, so two models that both end in
final(or a model CTE and a test helper with the same name) shared one name. On warehouses where an outer CTE wins over a nested redefinition, such as Snowflake, a model silently read another model's or a helper's rows. Models referenced by several steps were also inlined repeatedly.Changes
__ref__<model>with its own CTEs nested;__actual__<model>, later steps and assertions reuse it.__helper__<name>); references in fixtures, mocks, expectations and assertions are rewritten through the parsed SQL, so models never see helper names and bare table names read the real table. Without SQL analysis, helpers stay inline in the fixtures that read them. SQL Server keeps hoisting with renaming.;on a model no longer breaks later steps or assertions.--json-outputreports every parameterized case and each test'sduration_ms.Verification
;, parameterized JSON cases andduration_ms.make rust-check,make test,make check-ci.