Skip to content

Commit f86eda7

Browse files
committed
FO model partition changes are breaking not FO
1 parent e24c9da commit f86eda7

3 files changed

Lines changed: 61 additions & 4 deletions

File tree

sqlmesh/core/model/definition.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,9 @@ def is_breaking_change(self, previous: Model) -> t.Optional[bool]:
14471447
if self.lookback != previous.lookback:
14481448
return None
14491449

1450+
if self.partitioned_by != previous.partitioned_by:
1451+
return None
1452+
14501453
try:
14511454
# the previous model which comes from disk could be unrenderable
14521455
previous_query = previous.render_query()

sqlmesh/core/plan/builder.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,13 @@ def _categorize_snapshots(
547547
if snapshot.is_seed
548548
else SnapshotChangeCategory.FORWARD_ONLY
549549
)
550-
# If the model kind changes mark as breaking
550+
# If the model kind or partitioning changes mark as breaking
551551
if snapshot.is_model and snapshot.name in self._context_diff.modified_snapshots:
552552
_, old = self._context_diff.modified_snapshots[snapshot.name]
553-
if old.model.kind.name != snapshot.model.kind.name:
553+
if (
554+
old.model.kind.name != snapshot.model.kind.name
555+
or old.model.partitioned_by != snapshot.model.partitioned_by
556+
):
554557
category = SnapshotChangeCategory.BREAKING
555558

556559
snapshot.categorize_as(category)
@@ -714,8 +717,11 @@ def _is_forward_only_change(self, s_id: SnapshotId) -> bool:
714717
snapshot = self._context_diff.snapshots[s_id]
715718
if snapshot.name in self._context_diff.modified_snapshots:
716719
_, old = self._context_diff.modified_snapshots[snapshot.name]
717-
# If the model kind has changed, then we should not consider this to be a forward-only change.
718-
if snapshot.is_model and old.model.kind.name != snapshot.model.kind.name:
720+
# If the model kind or partitioning has changed, then we should not consider this to be a forward-only change.
721+
if snapshot.is_model and (
722+
old.model.kind.name != snapshot.model.kind.name
723+
or old.model.partitioned_by != snapshot.model.partitioned_by
724+
):
719725
return False
720726
return (
721727
snapshot.is_model

tests/core/test_plan.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,54 @@ def test_forward_only_models_model_kind_changed(make_snapshot, mocker: MockerFix
17241724
assert updated_snapshot.change_category == SnapshotChangeCategory.BREAKING
17251725

17261726

1727+
def test_forward_only_models_partition_changed(make_snapshot, mocker: MockerFixture):
1728+
snapshot = make_snapshot(
1729+
SqlModel(
1730+
name="a",
1731+
query=parse_one("select 3, ds, ds2"),
1732+
kind=IncrementalByTimeRangeKind(time_column="ds", forward_only=True),
1733+
partitioned_by=[parse_one("ds")],
1734+
)
1735+
)
1736+
snapshot.categorize_as(SnapshotChangeCategory.BREAKING)
1737+
updated_snapshot = make_snapshot(
1738+
SqlModel(
1739+
name="a",
1740+
query=parse_one("select 3, ds, ds2"),
1741+
kind=IncrementalByTimeRangeKind(time_column="ds", forward_only=True),
1742+
partitioned_by=[parse_one("ds2")],
1743+
)
1744+
)
1745+
updated_snapshot.previous_versions = snapshot.all_versions
1746+
1747+
context_diff = ContextDiff(
1748+
environment="test_environment",
1749+
is_new_environment=True,
1750+
is_unfinalized_environment=False,
1751+
normalize_environment_name=True,
1752+
create_from="prod",
1753+
create_from_env_exists=True,
1754+
added=set(),
1755+
removed_snapshots={},
1756+
modified_snapshots={updated_snapshot.name: (updated_snapshot, snapshot)},
1757+
snapshots={updated_snapshot.snapshot_id: updated_snapshot},
1758+
new_snapshots={updated_snapshot.snapshot_id: updated_snapshot},
1759+
previous_plan_id=None,
1760+
previously_promoted_snapshot_ids=set(),
1761+
previous_finalized_snapshots=None,
1762+
previous_gateway_managed_virtual_layer=False,
1763+
gateway_managed_virtual_layer=False,
1764+
)
1765+
1766+
PlanBuilder(context_diff, DuckDBEngineAdapter.SCHEMA_DIFFER, is_dev=True).build()
1767+
assert updated_snapshot.change_category == SnapshotChangeCategory.BREAKING
1768+
1769+
PlanBuilder(
1770+
context_diff, DuckDBEngineAdapter.SCHEMA_DIFFER, is_dev=True, forward_only=True
1771+
).build()
1772+
assert updated_snapshot.change_category == SnapshotChangeCategory.BREAKING
1773+
1774+
17271775
def test_indirectly_modified_forward_only_model(make_snapshot, mocker: MockerFixture):
17281776
snapshot_a = make_snapshot(SqlModel(name="a", query=parse_one("select 1 as a, ds")))
17291777
snapshot_a.categorize_as(SnapshotChangeCategory.BREAKING)

0 commit comments

Comments
 (0)