Skip to content

Commit 65774e6

Browse files
committed
Handle versioned models
1 parent 98b6293 commit 65774e6

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

sqlmesh/dbt/manifest.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,12 @@ def _test_model(node: ManifestNode) -> t.Optional[str]:
744744
attached_node = getattr(node, "attached_node", None)
745745
if attached_node:
746746
pieces = attached_node.split(".")
747-
return pieces[-1] if pieces[0] in ["model", "seed"] else None
747+
if pieces[0] in ["model", "seed"]:
748+
# versioned models have format "model.package.model_name.v1" (4 parts)
749+
if len(pieces) == 4:
750+
return f"{pieces[2]}_{pieces[3]}"
751+
return pieces[-1]
752+
return None
748753

749754
key_name = getattr(node, "file_key_name", None)
750755
if key_name:
@@ -824,31 +829,30 @@ def _build_test_name(node: ManifestNode, dependencies: Dependencies) -> str:
824829
source_parts = list(dependencies.sources)[0].split(".")
825830
source_name = "_".join(source_parts) if len(source_parts) == 2 else source_parts[-1]
826831
entity_name = model_name or source_name or ""
832+
entity_name = f"_{entity_name}" if entity_name else ""
827833

828834
name_prefix = ""
829835
if namespace := getattr(node.test_metadata, "namespace", None):
830836
name_prefix += f"{namespace}_"
831837
if source_name and not model_name:
832838
name_prefix += "source_"
833839

834-
name_suffix = f"_{entity_name}"
835-
if column_name := getattr(node, "column_name", None):
836-
name_suffix += f"_{column_name}"
837-
838840
metadata_kwargs = node.test_metadata.kwargs
839841
arg_val_parts = []
840842
for arg, val in sorted(metadata_kwargs.items()):
841-
if arg in ("model", "column_name"):
843+
if arg == "model":
842844
continue
843845
if isinstance(val, dict):
844846
val = list(val.values())
845847
val = [re.sub("[^0-9a-zA-Z_]+", "_", str(v)) for v in ensure_list(val)]
846848
arg_val_parts.extend(val)
847-
arg_vals = ("__" + "__".join(arg_val_parts)) if arg_val_parts else ""
849+
unique_args = "__".join(arg_val_parts) if arg_val_parts else ""
850+
unique_args = f"_{unique_args}" if unique_args else ""
848851

849-
auto_name = f"{name_prefix}{node.test_metadata.name}{name_suffix}{arg_vals}"
852+
auto_name = f"{name_prefix}{node.test_metadata.name}{entity_name}{unique_args}"
850853

851854
if node.name == auto_name:
852855
return node.name
853856

854-
return f"{name_prefix}{node.name}{name_suffix}{arg_vals}"
857+
custom_prefix = name_prefix if source_name and not model_name else ""
858+
return f"{custom_prefix}{node.name}{entity_name}{unique_args}"

tests/dbt/test_test.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def test_tests_get_unique_names(tmp_path: Path, create_empty_project) -> None:
2929
# Create schema.yml with:
3030
# 1. Same test on model and source, both with/without custom test name
3131
# 2. Same test on same model with different args, both with/without custom test name
32+
# 3. Versioned model with tests (both built-in and custom named)
3233
schema_yaml = {
3334
"version": 2,
3435
"sources": [
@@ -81,24 +82,61 @@ def test_tests_get_unique_names(tmp_path: Path, create_empty_project) -> None:
8182
],
8283
},
8384
],
84-
}
85+
},
86+
{
87+
"name": "versioned_model",
88+
"columns": [
89+
{
90+
"name": "id",
91+
"data_tests": [
92+
{"not_null": {}},
93+
{"not_null": {"name": "custom_versioned_notnull"}},
94+
],
95+
},
96+
{
97+
"name": "amount",
98+
"data_tests": [
99+
{"accepted_values": {"values": ["low", "high"]}},
100+
],
101+
},
102+
],
103+
"versions": [
104+
{"v": 1},
105+
{"v": 2},
106+
],
107+
},
85108
],
86109
}
87110

88111
schema_file = model_dir / "schema.yml"
89112
with open(schema_file, "w", encoding="utf-8") as f:
90113
yaml.dump(schema_yaml, f)
91114

115+
# Create versioned model files
116+
versioned_model_v1_file = model_dir / "versioned_model_v1.sql"
117+
with open(versioned_model_v1_file, "w", encoding="utf-8") as f:
118+
f.write("SELECT 1 as id, 'low' as amount")
119+
120+
versioned_model_v2_file = model_dir / "versioned_model_v2.sql"
121+
with open(versioned_model_v2_file, "w", encoding="utf-8") as f:
122+
f.write("SELECT 1 as id, 'low' as amount")
123+
92124
context = Context(paths=project_dir)
93125

94126
all_audit_names = list(context._audits.keys()) + list(context._standalone_audits.keys())
95127
assert sorted(all_audit_names) == [
96128
"local.accepted_values_my_model_status__value1__value2",
97129
"local.accepted_values_my_model_status__value1__value2__value3",
130+
"local.accepted_values_versioned_model_v1_amount__low__high",
131+
"local.accepted_values_versioned_model_v2_amount__low__high",
98132
"local.custom_accepted_values_name_my_model_status__value1__value2",
99133
"local.custom_accepted_values_name_my_model_status__value1__value2__value3",
100134
"local.custom_notnull_name_my_model_id",
135+
"local.custom_versioned_notnull_versioned_model_v1_id",
136+
"local.custom_versioned_notnull_versioned_model_v2_id",
101137
"local.not_null_my_model_id",
138+
"local.not_null_versioned_model_v1_id",
139+
"local.not_null_versioned_model_v2_id",
102140
"local.source_custom_notnull_name_raw_my_source_id",
103141
"local.source_not_null_raw_my_source_id",
104142
]

0 commit comments

Comments
 (0)