Skip to content

Commit 95c283f

Browse files
authored
Include columns provided by a user as part of the seed model definition into the snapshot fingerprint (#394)
1 parent 72721b6 commit 95c283f

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

docs/concepts/audits.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Auditing
2-
Audits are one of the tools SQLMesh provides to validate your models. Along with [tests](tests.md), they are a great way to ensure the quality of your data and to build trust in it across your organization.
2+
Audits are one of the tools SQLMesh provides to validate your models. Along with [tests](tests.md), they are a great way to ensure the quality of your data and to build trust in it across your organization. Unlike tests, audits are used to validate the output of a model after every evaluation.
33

44
A comprehensive suite of audits can identify data issues upstream, whether they are from your vendors or other teams. Audits also empower your data engineers and analysts to work with confidence by catching problems early as they work on new features or make updates to your models.
55

sqlmesh/core/snapshot/definition.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,9 @@ def _model_data_hash(model: Model, physical_schema: str) -> str:
721721
elif isinstance(model, SeedModel):
722722
data.append(str(model.kind.batch_size))
723723
data.append(model.seed.content)
724+
for column_name, column_type in (model.columns_to_types_ or {}).items():
725+
data.append(column_name)
726+
data.append(column_type.sql())
724727

725728
return _hash(data)
726729

tests/core/test_snapshot.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import json
2+
from pathlib import Path
23

34
import pytest
45
from _pytest.monkeypatch import MonkeyPatch
56
from pytest_mock.plugin import MockerFixture
6-
from sqlglot import parse_one
7+
from sqlglot import exp, parse, parse_one
78

89
from sqlmesh.core.macros import macro
9-
from sqlmesh.core.model import Model, SqlModel
10+
from sqlmesh.core.model import Model, SqlModel, load_model
1011
from sqlmesh.core.snapshot import (
1112
Snapshot,
1213
SnapshotChangeCategory,
@@ -275,6 +276,40 @@ def test_fingerprint(model: Model, parent_model: Model):
275276
assert new_fingerprint != fingerprint_from_model(model, models={})
276277

277278

279+
def test_fingerprint_seed_model():
280+
expressions = parse(
281+
"""
282+
MODEL (
283+
name db.seed,
284+
kind SEED (
285+
path '../seeds/waiter_names.csv'
286+
)
287+
);
288+
"""
289+
)
290+
291+
expected_fingerprint = SnapshotFingerprint(
292+
data_hash="941582290",
293+
metadata_hash="2750000337",
294+
)
295+
296+
model = load_model(expressions, path=Path("./examples/sushi/models/test_model.sql"))
297+
actual_fingerprint = fingerprint_from_model(model, models={})
298+
assert actual_fingerprint == expected_fingerprint
299+
300+
updated_model = model.copy(
301+
update={
302+
"columns_to_types_": {
303+
"id": exp.DataType.build("int"),
304+
"name": exp.DataType.build("text"),
305+
}
306+
}
307+
)
308+
updated_actual_fingerprint = fingerprint_from_model(updated_model, models={})
309+
assert updated_actual_fingerprint.data_hash != expected_fingerprint.data_hash
310+
assert updated_actual_fingerprint.metadata_hash == expected_fingerprint.metadata_hash
311+
312+
278313
def test_stamp(model: Model):
279314
original_fingerprint = fingerprint_from_model(model, models={})
280315

0 commit comments

Comments
 (0)