Skip to content

Commit b2d4a14

Browse files
authored
feat: add forall audit (#698)
* feat: add `forall` audit Add a built-in audit that allows arbitrary expressions that must hold for all rows in a model. * tidy: format and drop unecessary `@SQL` invocation
1 parent 82b0f3f commit b2d4a14

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

docs/concepts/audits.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ MODEL (
113113
);
114114
```
115115

116+
### forall
117+
Ensures that a set of arbitrary boolean expressions are upheld (evaluate to `true`) for all rows in the model. For incremental models, this check only applies to a data interval that is being evaluated, not to the entire table.
118+
119+
Example:
120+
```sql linenums="1"
121+
MODEL (
122+
name sushi.items,
123+
audits (
124+
forall(criteria=[
125+
price >= 0,
126+
LENGTH(name) > 0
127+
])
128+
)
129+
);
130+
```
131+
116132
## Running audits
117133
### The CLI audit command
118134

sqlmesh/core/audit/builtin.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,16 @@
6060
HAVING COUNT(*) <= @threshold
6161
""",
6262
)
63+
64+
65+
forall_audit = Audit(
66+
name="forall",
67+
query="""
68+
SELECT *
69+
FROM @this_model
70+
WHERE @REDUCE(
71+
@criteria,
72+
(l, r) -> NOT (l) OR NOT (r)
73+
)
74+
""",
75+
)

tests/core/test_audit.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,14 @@ def test_number_of_rows_audit(model: Model):
217217
rendered_query.sql()
218218
== """SELECT 1 AS "1" FROM (SELECT * FROM db.test_model AS test_model WHERE test_model.ds <= '1970-01-01' AND test_model.ds >= '1970-01-01') AS _q_0 HAVING COUNT(*) <= 0 LIMIT 0 + 1"""
219219
)
220+
221+
222+
def test_forall_audit(model: Model):
223+
rendered_query_a = builtin.forall_audit.render_query(
224+
model,
225+
criteria=[parse_one("a >= b"), parse_one("c + d - e < 1.0")],
226+
)
227+
assert (
228+
rendered_query_a.sql()
229+
== "SELECT * FROM (SELECT * FROM db.test_model AS test_model WHERE test_model.ds <= '1970-01-01' AND test_model.ds >= '1970-01-01') AS _q_0 WHERE NOT (_q_0.a >= _q_0.b) OR NOT (_q_0.c + _q_0.d - _q_0.e < 1.0)"
230+
)

0 commit comments

Comments
 (0)