Skip to content

Commit a142c5f

Browse files
committed
fix: VIEW model with metadata-only changes in VDE=dev_only should always migrate
1 parent 906be74 commit a142c5f

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

sqlmesh/core/plan/stages.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,6 @@ def build(self, plan: EvaluatablePlan) -> t.List[PlanStage]:
270270
}
271271
after_promote_snapshots = all_selected_for_backfill_snapshots - before_promote_snapshots
272272
deployability_index = DeployabilityIndex.all_deployable()
273-
274273
snapshots_with_schema_migration = [
275274
s for s in snapshots.values() if s.requires_schema_migration_in_prod
276275
]

sqlmesh/core/snapshot/definition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@ def requires_schema_migration_in_prod(self) -> bool:
14831483
return (
14841484
self.is_paused
14851485
and self.is_model
1486-
and self.is_materialized
1486+
and not self.is_symbolic
14871487
and (
14881488
(self.previous_version and self.previous_version.version == self.version)
14891489
or self.model.forward_only

tests/core/test_plan_stages.py

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,16 +1659,17 @@ def test_build_plan_stages_indirect_non_breaking_view_migration(
16591659
stages = build_plan_stages(plan, state_reader, None)
16601660

16611661
# Verify stages
1662-
assert len(stages) == 8
1662+
assert len(stages) == 9
16631663

16641664
assert isinstance(stages[0], CreateSnapshotRecordsStage)
16651665
assert isinstance(stages[1], PhysicalLayerSchemaCreationStage)
16661666
assert isinstance(stages[2], BackfillStage)
16671667
assert isinstance(stages[3], EnvironmentRecordUpdateStage)
1668-
assert isinstance(stages[4], UnpauseStage)
1669-
assert isinstance(stages[5], BackfillStage)
1670-
assert isinstance(stages[6], VirtualLayerUpdateStage)
1671-
assert isinstance(stages[7], FinalizeEnvironmentStage)
1668+
assert isinstance(stages[4], MigrateSchemasStage)
1669+
assert isinstance(stages[5], UnpauseStage)
1670+
assert isinstance(stages[6], BackfillStage)
1671+
assert isinstance(stages[7], VirtualLayerUpdateStage)
1672+
assert isinstance(stages[8], FinalizeEnvironmentStage)
16721673

16731674

16741675
def test_build_plan_stages_virtual_environment_mode_filtering(
@@ -1936,6 +1937,76 @@ def test_build_plan_stages_virtual_environment_mode_no_updates(
19361937
assert len(virtual_stages) == 0
19371938

19381939

1940+
def test_build_plan_stages_virtual_environment_mode_metadata_only_changes(
1941+
mocker: MockerFixture,
1942+
) -> None:
1943+
snapshot_view: Snapshot = Snapshot.from_node(
1944+
SqlModel(
1945+
name="dev_only_view",
1946+
query=parse_one("select 1 as id"),
1947+
kind=dict(name=ModelKindName.VIEW),
1948+
virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY,
1949+
),
1950+
nodes={},
1951+
ttl="in 1 week",
1952+
)
1953+
snapshot_view.categorize_as(SnapshotChangeCategory.METADATA)
1954+
1955+
state_reader = mocker.Mock(spec=StateReader)
1956+
state_reader.get_snapshots.return_value = {}
1957+
state_reader.get_environment.return_value = None
1958+
1959+
# Production environment with the view promoted
1960+
environment = Environment(
1961+
name="prod",
1962+
snapshots=[snapshot_view.table_info],
1963+
start_at="2023-01-01",
1964+
end_at="2023-01-02",
1965+
plan_id="test_plan",
1966+
previous_plan_id=None,
1967+
promoted_snapshot_ids=[snapshot_view.snapshot_id],
1968+
)
1969+
1970+
plan = EvaluatablePlan(
1971+
start="2023-01-01",
1972+
end="2023-01-02",
1973+
new_snapshots=[snapshot_view],
1974+
environment=environment,
1975+
no_gaps=False,
1976+
skip_backfill=True,
1977+
empty_backfill=False,
1978+
restatements={},
1979+
is_dev=False,
1980+
allow_destructive_models=set(),
1981+
allow_additive_models=set(),
1982+
forward_only=False,
1983+
end_bounded=True,
1984+
ensure_finalized_snapshots=False,
1985+
ignore_cron=False,
1986+
directly_modified_snapshots=[snapshot_view.snapshot_id],
1987+
indirectly_modified_snapshots={},
1988+
metadata_updated_snapshots=[snapshot_view.snapshot_id],
1989+
removed_snapshots=[],
1990+
requires_backfill=False,
1991+
models_to_backfill=None,
1992+
execution_time="2023-01-02",
1993+
disabled_restatement_models=set(),
1994+
environment_statements=None,
1995+
user_provided_flags=None,
1996+
)
1997+
1998+
stages = build_plan_stages(plan, state_reader, None)
1999+
2000+
migrate_stages = [s for s in stages if isinstance(s, MigrateSchemasStage)]
2001+
assert migrate_stages, (
2002+
"Expected a MigrateSchemasStage for dev_only VIEW with metadata-only change"
2003+
)
2004+
migrate_stage = migrate_stages[0]
2005+
assert snapshot_view in migrate_stage.snapshots
2006+
2007+
assert not any(isinstance(s, VirtualLayerUpdateStage) for s in stages)
2008+
2009+
19392010
def test_adjust_intervals_new_forward_only_dev_intervals(
19402011
make_snapshot, mocker: MockerFixture
19412012
) -> None:

0 commit comments

Comments
 (0)