Skip to content

Commit e0982fa

Browse files
authored
Fix: The broken reference check shouldn't check removed external models (#2758)
1 parent 1449da1 commit e0982fa

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

sqlmesh/core/model/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
)
55
from sqlmesh.core.model.decorator import model as model
66
from sqlmesh.core.model.definition import (
7+
ExternalModel as ExternalModel,
78
Model as Model,
89
PythonModel as PythonModel,
910
SeedModel as SeedModel,

sqlmesh/core/plan/builder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,9 @@ def _ensure_no_forward_only_revert(self) -> None:
698698

699699
def _ensure_no_broken_references(self) -> None:
700700
for snapshot in self._context_diff.snapshots.values():
701-
broken_references = {x.name for x in self._context_diff.removed_snapshots} & {
702-
x for x in snapshot.node.depends_on
703-
}
701+
broken_references = {
702+
x.name for x in self._context_diff.removed_snapshots.values() if not x.is_external
703+
} & {x for x in snapshot.node.depends_on}
704704
if broken_references:
705705
broken_references_msg = ", ".join(f"'{x}'" for x in broken_references)
706706
raise PlanError(

tests/core/test_plan.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from sqlmesh.core.engine_adapter import DuckDBEngineAdapter
1414
from sqlmesh.core.environment import EnvironmentNamingInfo
1515
from sqlmesh.core.model import (
16+
ExternalModel,
1617
FullKind,
1718
IncrementalByTimeRangeKind,
1819
SeedKind,
@@ -1163,6 +1164,36 @@ def test_broken_references(make_snapshot, mocker: MockerFixture):
11631164
PlanBuilder(context_diff, DuckDBEngineAdapter.SCHEMA_DIFFER).build()
11641165

11651166

1167+
def test_broken_references_external_model(make_snapshot, mocker: MockerFixture):
1168+
snapshot_a = make_snapshot(ExternalModel(name="a", kind=dict(name=ModelKindName.EXTERNAL)))
1169+
snapshot_a.categorize_as(SnapshotChangeCategory.BREAKING)
1170+
1171+
snapshot_b = make_snapshot(SqlModel(name="b", query=parse_one("select 2, ds FROM a")))
1172+
snapshot_b.categorize_as(SnapshotChangeCategory.BREAKING)
1173+
1174+
context_diff = ContextDiff(
1175+
environment="test_environment",
1176+
is_new_environment=True,
1177+
is_unfinalized_environment=False,
1178+
create_from="prod",
1179+
added=set(),
1180+
removed_snapshots={snapshot_a.snapshot_id: snapshot_a.table_info},
1181+
modified_snapshots={snapshot_b.name: (snapshot_b, snapshot_b)},
1182+
snapshots={snapshot_b.snapshot_id: snapshot_b},
1183+
new_snapshots={},
1184+
previous_plan_id=None,
1185+
previously_promoted_snapshot_ids=set(),
1186+
previous_finalized_snapshots=None,
1187+
)
1188+
1189+
# Make sure the downstream snapshot doesn't have any parents,
1190+
# since its only parent has been removed from the project.
1191+
assert not snapshot_b.parents
1192+
1193+
# Shouldn't raise
1194+
PlanBuilder(context_diff, DuckDBEngineAdapter.SCHEMA_DIFFER).build()
1195+
1196+
11661197
def test_effective_from(make_snapshot, mocker: MockerFixture):
11671198
snapshot = make_snapshot(
11681199
SqlModel(

0 commit comments

Comments
 (0)