Skip to content

Commit 6302571

Browse files
Chore: Validate start and end dates during plan build time
1 parent d177625 commit 6302571

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

sqlmesh/core/context.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,28 @@ def plan_builder(
16031603
execution_time or now(),
16041604
)
16051605

1606+
# Validate that the start is not greater than the end date / time
1607+
effective_start = start or default_start
1608+
effective_end = end or default_end
1609+
if effective_start is not None and effective_end is not None:
1610+
start_ts = to_timestamp(effective_start)
1611+
end_ts = to_timestamp(effective_end)
1612+
if start_ts > end_ts:
1613+
for model_name in (
1614+
set(backfill_models or {})
1615+
| set(modified_model_names)
1616+
| set(max_interval_end_per_model)
1617+
):
1618+
if snapshot := snapshots.get(model_name):
1619+
if (
1620+
snapshot.node.start is None
1621+
or to_timestamp(snapshot.node.start) > end_ts
1622+
):
1623+
raise SQLMeshError(
1624+
f"Start date / time ({to_datetime(start_ts)}) can't be greater than end date / time ({to_datetime(end_ts)}).\n"
1625+
f"Set the `start` attribute in your project config model defaults to avoid this issue."
1626+
)
1627+
16061628
# Refresh snapshot intervals to ensure that they are up to date with values reflected in the max_interval_end_per_model.
16071629
self.state_sync.refresh_snapshot_intervals(context_diff.snapshots.values())
16081630

tests/core/test_context.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3007,3 +3007,59 @@ def test_uppercase_gateway_external_models(tmp_path):
30073007
assert len(uppercase_in_yaml_models) == 1, (
30083008
f"External model with uppercase gateway in YAML should be found. Found {len(uppercase_in_yaml_models)} models"
30093009
)
3010+
3011+
3012+
def test_plan_no_start_configured():
3013+
context = Context(config=Config())
3014+
context.upsert_model(
3015+
load_sql_based_model(
3016+
parse(
3017+
"""
3018+
MODEL(
3019+
name db.xvg,
3020+
kind INCREMENTAL_BY_TIME_RANGE (
3021+
time_column ds
3022+
),
3023+
cron '@daily'
3024+
);
3025+
3026+
SELECT id, ds FROM (VALUES
3027+
('1', '2020-01-01'),
3028+
) data(id, ds)
3029+
WHERE ds BETWEEN @start_ds AND @end_ds
3030+
"""
3031+
)
3032+
)
3033+
)
3034+
3035+
prod_plan = context.plan(auto_apply=True)
3036+
assert len(prod_plan.new_snapshots) == 1
3037+
3038+
context.upsert_model(
3039+
load_sql_based_model(
3040+
parse(
3041+
"""
3042+
MODEL(
3043+
name db.xvg,
3044+
kind INCREMENTAL_BY_TIME_RANGE (
3045+
time_column ds
3046+
),
3047+
cron '@daily',
3048+
physical_properties ('some_prop' = 1),
3049+
);
3050+
3051+
SELECT id, ds FROM (VALUES
3052+
('1', '2020-01-01'),
3053+
) data(id, ds)
3054+
WHERE ds BETWEEN @start_ds AND @end_ds
3055+
"""
3056+
)
3057+
)
3058+
)
3059+
3060+
# This should raise an error because the model has no start configured and the end time is less than the start time which will be calculated from the intervals
3061+
with pytest.raises(
3062+
SQLMeshError,
3063+
match=r"Set the `start` attribute in your project config model defaults to avoid this issue",
3064+
):
3065+
context.plan("dev", execution_time="1999-01-05")

0 commit comments

Comments
 (0)