Skip to content

Commit b268cea

Browse files
committed
fixes after rebase
1 parent 96e840e commit b268cea

File tree

5 files changed

+21
-71
lines changed

5 files changed

+21
-71
lines changed

docs/guides/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ As the name suggests, 'dev-only' mode means that VDE is applied only in developm
570570
Please note the following tradeoffs when enabling this mode:
571571

572572
- All data inserted in development environments is used only for [preview](../concepts/plans.md#data-preview-for-forward-only-changes) and will **not** be reused in production
573-
- Reverting a model to a previous version will trigger a full rebuild (unless the model is forward-only), as there is no versioned physical table to revert to
573+
- Reverting a model to a previous version will be applied going forward and may require an explicit data restatement
574574

575575
!!! warning
576576
Switching the mode for an existing project will result in a complete rebuild of all models in the project. Refer to the [Table Migration Guide](./table_migration.md) to migrate existing tables without rebuilding them from scratch.

sqlmesh/core/context.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,11 @@ def plan_builder(
16161616
max_interval_end_per_model,
16171617
)
16181618

1619+
if not self.config.virtual_environment_mode.is_full:
1620+
forward_only = True
1621+
elif forward_only is None:
1622+
forward_only = self.config.plan.forward_only
1623+
16191624
return self.PLAN_BUILDER_TYPE(
16201625
context_diff=context_diff,
16211626
start=start,
@@ -1628,9 +1633,7 @@ def plan_builder(
16281633
skip_backfill=skip_backfill,
16291634
empty_backfill=empty_backfill,
16301635
is_dev=is_dev,
1631-
forward_only=(
1632-
forward_only if forward_only is not None else self.config.plan.forward_only
1633-
),
1636+
forward_only=forward_only,
16341637
allow_destructive_models=expanded_destructive_models,
16351638
environment_ttl=environment_ttl,
16361639
environment_suffix_target=self.config.environment_suffix_target,

sqlmesh/core/plan/builder.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -609,13 +609,13 @@ def _categorize_snapshot(
609609

610610
if self._context_diff.directly_modified(s_id.name):
611611
new, old = self._context_diff.modified_snapshots[s_id.name]
612-
is_breaking_kind_change = _is_breaking_kind_change(old, new)
613-
if is_breaking_kind_change or snapshot.is_seed:
612+
should_force_rebuild = _should_force_rebuild(old, new)
613+
if should_force_rebuild or snapshot.is_seed:
614614
# Breaking kind changes and seed changes can't be forward-only.
615615
forward_only = False
616616

617617
if self._auto_categorization_enabled:
618-
if is_breaking_kind_change:
618+
if should_force_rebuild:
619619
snapshot.categorize_as(SnapshotChangeCategory.BREAKING, forward_only)
620620
return
621621

@@ -773,7 +773,7 @@ def _is_forward_only_change(self, s_id: SnapshotId) -> bool:
773773
if snapshot.name in self._context_diff.modified_snapshots:
774774
_, old = self._context_diff.modified_snapshots[snapshot.name]
775775
# If the model kind has changed in a breaking way, then we can't consider this to be a forward-only change.
776-
if snapshot.is_model and _should_force_breaking_change(old, snapshot):
776+
if snapshot.is_model and _should_force_rebuild(old, snapshot):
777777
return False
778778
return (
779779
snapshot.is_model and snapshot.model.forward_only and bool(snapshot.previous_versions)
@@ -894,7 +894,7 @@ def _modified_and_added_snapshots(self) -> t.List[Snapshot]:
894894
]
895895

896896

897-
def _should_force_breaking_change(old: Snapshot, new: Snapshot) -> bool:
897+
def _should_force_rebuild(old: Snapshot, new: Snapshot) -> bool:
898898
if old.virtual_environment_mode != new.virtual_environment_mode:
899899
# If the virtual environment mode has changed, then it's a breaking change
900900
return True

sqlmesh/core/snapshot/definition.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,7 @@ def requires_schema_migration_in_prod(self) -> bool:
14081408
or self.model.forward_only
14091409
or bool(self.model.physical_version)
14101410
or self.is_view
1411+
or not self.virtual_environment_mode.is_full
14111412
)
14121413
)
14131414

tests/core/test_integration.py

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2505,76 +2505,22 @@ def test_virtual_environment_mode_dev_only(init_and_plan_context: t.Callable):
25052505
)[0]
25062506
assert min_event_date == to_date("2023-01-07")
25072507

2508-
# Make sure the changed models are fully rebuilt when deploying to prod
2508+
# Make sure the changes are applied without backfill in prod
25092509
plan_prod = context.plan_builder("prod").build()
2510-
assert plan_prod.requires_backfill
2511-
assert plan_prod.missing_intervals == [
2512-
SnapshotIntervals(
2513-
snapshot_id=context.get_snapshot("sushi.top_waiters").snapshot_id,
2514-
intervals=[
2515-
(to_timestamp("2023-01-01"), to_timestamp("2023-01-02")),
2516-
(to_timestamp("2023-01-02"), to_timestamp("2023-01-03")),
2517-
(to_timestamp("2023-01-03"), to_timestamp("2023-01-04")),
2518-
(to_timestamp("2023-01-04"), to_timestamp("2023-01-05")),
2519-
(to_timestamp("2023-01-05"), to_timestamp("2023-01-06")),
2520-
(to_timestamp("2023-01-06"), to_timestamp("2023-01-07")),
2521-
(to_timestamp("2023-01-07"), to_timestamp("2023-01-08")),
2522-
],
2523-
),
2524-
SnapshotIntervals(
2525-
snapshot_id=context.get_snapshot("sushi.waiter_revenue_by_day").snapshot_id,
2526-
intervals=[
2527-
(to_timestamp("2023-01-01"), to_timestamp("2023-01-02")),
2528-
(to_timestamp("2023-01-02"), to_timestamp("2023-01-03")),
2529-
(to_timestamp("2023-01-03"), to_timestamp("2023-01-04")),
2530-
(to_timestamp("2023-01-04"), to_timestamp("2023-01-05")),
2531-
(to_timestamp("2023-01-05"), to_timestamp("2023-01-06")),
2532-
(to_timestamp("2023-01-06"), to_timestamp("2023-01-07")),
2533-
(to_timestamp("2023-01-07"), to_timestamp("2023-01-08")),
2534-
],
2535-
),
2536-
]
2510+
assert not plan_prod.requires_backfill
2511+
assert not plan_prod.missing_intervals
25372512
context.apply(plan_prod)
25382513
assert "one" in context.engine_adapter.columns("sushi.waiter_revenue_by_day")
2539-
assert (
2540-
context.engine_adapter.fetchone(
2541-
"SELECT COUNT(*) FROM sushi.waiter_revenue_by_day WHERE one is NULL"
2542-
)[0]
2543-
== 0
2544-
)
25452514

25462515
# Make sure the revert of a breaking changes results in a full rebuild
25472516
context.upsert_model(original_model)
25482517
assert context.get_snapshot(original_model.name).fingerprint == original_fingerprint
25492518

2550-
plan_prod = context.plan_builder("prod").build()
2551-
assert plan_prod.requires_backfill
2552-
assert plan_prod.missing_intervals == [
2553-
SnapshotIntervals(
2554-
snapshot_id=context.get_snapshot("sushi.top_waiters").snapshot_id,
2555-
intervals=[
2556-
(to_timestamp("2023-01-01"), to_timestamp("2023-01-02")),
2557-
(to_timestamp("2023-01-02"), to_timestamp("2023-01-03")),
2558-
(to_timestamp("2023-01-03"), to_timestamp("2023-01-04")),
2559-
(to_timestamp("2023-01-04"), to_timestamp("2023-01-05")),
2560-
(to_timestamp("2023-01-05"), to_timestamp("2023-01-06")),
2561-
(to_timestamp("2023-01-06"), to_timestamp("2023-01-07")),
2562-
(to_timestamp("2023-01-07"), to_timestamp("2023-01-08")),
2563-
],
2564-
),
2565-
SnapshotIntervals(
2566-
snapshot_id=context.get_snapshot("sushi.waiter_revenue_by_day").snapshot_id,
2567-
intervals=[
2568-
(to_timestamp("2023-01-01"), to_timestamp("2023-01-02")),
2569-
(to_timestamp("2023-01-02"), to_timestamp("2023-01-03")),
2570-
(to_timestamp("2023-01-03"), to_timestamp("2023-01-04")),
2571-
(to_timestamp("2023-01-04"), to_timestamp("2023-01-05")),
2572-
(to_timestamp("2023-01-05"), to_timestamp("2023-01-06")),
2573-
(to_timestamp("2023-01-06"), to_timestamp("2023-01-07")),
2574-
(to_timestamp("2023-01-07"), to_timestamp("2023-01-08")),
2575-
],
2576-
),
2577-
]
2519+
plan_prod = context.plan_builder(
2520+
"prod", allow_destructive_models=["sushi.waiter_revenue_by_day"]
2521+
).build()
2522+
assert not plan_prod.requires_backfill
2523+
assert not plan_prod.missing_intervals
25782524
context.apply(plan_prod)
25792525
assert "one" not in context.engine_adapter.columns("sushi.waiter_revenue_by_day")
25802526

0 commit comments

Comments
 (0)