Skip to content

fix(audits): fail at_least_one when no row has a non-NULL value - #6199

Open
DG47 wants to merge 2 commits into
SQLMesh:mainfrom
DG47:fix/audit-at-least-one-empty-table
Open

DG47 wants to merge 2 commits into
SQLMesh:mainfrom
DG47:fix/audit-at-least-one-empty-table

Conversation

@DG47

@DG47 DG47 commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes #6198

at_least_one grouped by the constant 1, so on an empty table, or when condition filters out every row, there were no groups for HAVING to reject and the audit passed. It aggregates over the whole table now, which yields a single row whenever the non-NULL count is zero:

SELECT COUNT(@column) AS cnt_not_null
FROM @this_model
WHERE @condition
HAVING COUNT(@column) = 0

This matches the shape of the equivalent dbt_utils.at_least_one test and also avoids GROUP BY 1, which engines such as SQL Server reject when the grouped expression is a constant.

Test Plan

  • Updated test_at_least_one_audit for the new rendered query.
  • Added test_at_least_one_audit_fails_when_no_row_has_a_value, which executes the rendered audit against DuckDB for an empty table, an all-NULL table, a table with one value, and a condition that excludes the only value. The new test fails on main and passes with this change.
  • pytest tests/core/test_audit.py (51 passed) and the test_context.py tests that use at_least_one_non_blocking (5 passed).
  • pre-commit run --files sqlmesh/core/audit/builtin.py tests/core/test_audit.py (ruff, ruff-format, mypy passed).
  • make fast-test: 2809 passed; the only failures are the MSSQL pyodbc connection-string tests in tests/core/test_connection_config.py, which cannot load the unixODBC library on my machine and are unrelated to this change.

Checklist

  • I have run make style and fixed any issues
  • I have added tests for my changes (if applicable)
  • All existing tests pass (make fast-test)
  • My commits are signed off (git commit -s) per the DCO

Summary by CodeRabbit

  • Bug Fixes
    • The “at least one” audit now reports failure when a table is empty, contains only NULL values, or has no non-NULL values that meet its filter. It reports success when at least one non-NULL value meets the filter. This resolves incorrect audit results for empty and filtered tables.

The at_least_one audit grouped by the constant 1, so an empty table, or
a condition that filters out every row, produced no groups at all and
the audit passed even though no row has a non-NULL value in the column.

Aggregate over the whole table instead and keep the HAVING check, which
returns a single row whenever the non-NULL count is zero.

Signed-off-by: Dhruv Gupta <todhruvg@gmail.com>
@coderabbitai

coderabbitai Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The at_least_one_audit query now counts non-NULL values after applying its condition. Tests verify failures for empty or fully filtered results and success when a qualifying non-NULL value exists.

Changes: at_least_one audit behavior

Layer / File(s) Summary
Count matching non-NULL values
sqlmesh/core/audit/builtin.py, tests/core/test_audit.py
The audit uses a table-wide COUNT with a HAVING check. Tests verify the generated SQL and cover empty tables, NULL-only values, included values, and conditions that filter out values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: mday-io, nicksspirit

Merge Risk: Minimal · up to b3556

The at_least_one audit now fails when the table is empty or no row matching the condition has a non-NULL value. It also no longer uses GROUP BY 1, which SQL Server rejects. No actionable merge risk remains.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the main change: the at_least_one audit now fails when no row has a non-NULL value. It matches the raw summary, which says the audit counts non-NULL values over the filtered table and …
Description check Passed The description follows the repository template. It has a Description section that explains the bug and the fix, and a Test Plan section that lists the updated and new tests and the validation command…
Linked Issues check Passed [#6198] The issue requires the built-in at_least_one audit to fail when no row that satisfies condition has a non-NULL value, including on an empty table. At the reviewed head, sqlmesh/core/audit/buil…
Out of Scope Changes check Passed [#6198] The whole-PR diff against the merge base changes two files. sqlmesh/core/audit/builtin.py changes only the at_least_one_audit query and adds a comment explaining the change. tests/core/test_au…
Full details: Title check

Explanation

The title names the main change: the at_least_one audit now fails when no row has a non-NULL value. It matches the raw summary, which says the audit counts non-NULL values over the filtered table and fails on zero. The title uses the conventional fix(scope) format and is 63 characters long.

Full details: Description check

Explanation

The description follows the repository template. It has a Description section that explains the bug and the fix, and a Test Plan section that lists the updated and new tests and the validation commands run. The Checklist is complete. It links issue #6198. The description does not contain the template's HTML comment placeholders, and it does not state whether the new DuckDB test covers the MSSQL behavior it cites. Those gaps are minor.

Full details: Linked Issues check

Explanation

[#6198] The issue requires the built-in at_least_one audit to fail when no row that satisfies condition has a non-NULL value, including on an empty table. At the reviewed head, sqlmesh/core/audit/builtin.py renders SELECT COUNT(@column) AS cnt_not_null FROM @this_model WHERE @condition HAVING COUNT(@column) = 0. With no GROUP BY, the aggregate returns one row when the non-NULL count is zero, and zero rows otherwise. This removes the dependence on GROUP BY 1, which the issue identifies as rejected by SQL Server. tests/core/test_audit.py adds test_at_least_one_audit_fails_when_no_row_has_a_value. It runs the rendered audit on DuckDB for an empty table, an all-NULL table, a table with a non-NULL value, and a condition that excludes the only non-NULL value. It asserts the failing row in the zero-count cases and no rows when a non-NULL value is included. test_at_least_one_audit is updated to the new rendered SQL. The issue's expected behavior is met in the code and tests. The SQL Server claim is supported by the query shape only; no MSSQL test was run.

Full details: Out of Scope Changes check

Explanation

[#6198] The whole-PR diff against the merge base changes two files. sqlmesh/core/audit/builtin.py changes only the at_least_one_audit query and adds a comment explaining the change. tests/core/test_audit.py updates the expected rendered SQL for that audit, adds a DuckDB behavioral test for the linked issue, and adds an import of typing for the new test's type annotations. All changes connect to the at_least_one audit in #6198. No unrelated change is present.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b18185d6-ec2b-470b-9b4a-a15ceccfe20d
Commits

Reviewing files that changed from the base of the PR and between 735b26f and b35567e.

Files selected for processing: 1

  • sqlmesh/core/audit/builtin.py

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

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.

at_least_one audit passes on an empty table or when condition filters out every row

1 participant