Skip to content

Commit 596e55e

Browse files
committed
Narrow seed PR stale override fix
1 parent 0c421d0 commit 596e55e

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

sqlmesh/core/context.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,16 +1684,6 @@ def plan_builder(
16841684
plan_execution_time,
16851685
)
16861686

1687-
if (
1688-
start
1689-
and default_end
1690-
and to_datetime(start, relative_base=to_datetime(plan_execution_time))
1691-
> to_datetime(default_end)
1692-
):
1693-
# If the requested start is newer than prod's latest interval end, fall back to execution time
1694-
# instead of forcing an invalid [start, default_end] range.
1695-
default_start, default_end = None, None
1696-
16971687
# Refresh snapshot intervals to ensure that they are up to date with values reflected in the max_interval_end_per_model.
16981688
self.state_sync.refresh_snapshot_intervals(context_diff.snapshots.values())
16991689
max_interval_end_per_model = self._filter_stale_end_overrides(

tests/core/test_context.py

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,9 @@ def test_plan_seed_model_excluded_from_default_end(copy_to_temp_path: t.Callable
12241224

12251225

12261226
@pytest.mark.slow
1227-
def test_seed_model_pr_plan_with_stale_prod_intervals(copy_to_temp_path: t.Callable):
1227+
def test_seed_model_pr_plan_filters_stale_end_override(
1228+
copy_to_temp_path: t.Callable, mocker: MockerFixture
1229+
):
12281230
path = copy_to_temp_path("examples/sushi")
12291231

12301232
with time_machine.travel("2024-06-01 00:00:00 UTC"):
@@ -1238,24 +1240,64 @@ def test_seed_model_pr_plan_with_stale_prod_intervals(copy_to_temp_path: t.Calla
12381240
model = context.get_model("sushi.waiter_names").copy()
12391241
model.seed.content += "10,Trey\n"
12401242
context.upsert_model(model)
1243+
context.upsert_model(
1244+
load_sql_based_model(
1245+
parse(
1246+
"""
1247+
MODEL (
1248+
name sushi.waiter_rollup,
1249+
kind FULL,
1250+
cron '@daily'
1251+
);
1252+
1253+
SELECT waiter_id, waiter_name, event_date
1254+
FROM sushi.waiter_as_customer_by_day
1255+
"""
1256+
),
1257+
default_catalog=context.default_catalog,
1258+
)
1259+
)
1260+
1261+
waiter_as_customer_by_day = context.get_snapshot(
1262+
"sushi.waiter_as_customer_by_day", raise_if_missing=True
1263+
)
1264+
orders = context.get_snapshot("sushi.orders", raise_if_missing=True)
1265+
original_get_max_interval_end_per_model = context._get_max_interval_end_per_model
1266+
1267+
def _mocked_max_interval_end_per_model(
1268+
snapshots: t.Dict[str, t.Any], backfill_models: t.Optional[t.Set[str]]
1269+
) -> t.Dict[str, datetime]:
1270+
result = original_get_max_interval_end_per_model(snapshots, backfill_models)
1271+
# Keep the overall plan end recent via another affected model while making the old prod end for
1272+
# waiter_as_customer_by_day older than the PR start. Without filtering, that stale end_override
1273+
# causes the new waiter_as_customer_by_day snapshot to be skipped and waiter_rollup fails when it
1274+
# references the missing physical table.
1275+
result[waiter_as_customer_by_day.name] = to_datetime("2026-01-01")
1276+
result[orders.name] = to_datetime("2026-04-13")
1277+
return result
1278+
1279+
mocker.patch.object(
1280+
context,
1281+
"_get_max_interval_end_per_model",
1282+
side_effect=_mocked_max_interval_end_per_model,
1283+
)
12411284

12421285
plan = context.plan("dev", start="2 months ago", no_prompts=True)
12431286
missing_interval_names = {si.snapshot_id.name for si in plan.missing_intervals}
12441287

12451288
assert plan.user_provided_flags == {"start": "2 months ago"}
1246-
assert plan.provided_end is None
12471289
assert to_timestamp(plan.start) == to_timestamp("2026-02-13")
12481290
assert to_timestamp(plan.end) == to_timestamp("2026-04-13")
1249-
assert any("waiter_names" in name for name in missing_interval_names)
12501291
assert any("waiter_as_customer_by_day" in name for name in missing_interval_names)
1292+
assert any("waiter_rollup" in name for name in missing_interval_names)
12511293

12521294
context.apply(plan)
12531295

12541296
promoted_snapshot_names = {
12551297
snapshot.name for snapshot in context.state_sync.get_environment("dev").promoted_snapshots
12561298
}
1257-
assert any("waiter_names" in name for name in promoted_snapshot_names)
12581299
assert any("waiter_as_customer_by_day" in name for name in promoted_snapshot_names)
1300+
assert any("waiter_rollup" in name for name in promoted_snapshot_names)
12591301
context.close()
12601302

12611303

0 commit comments

Comments
 (0)