Skip to content

Commit 79fbeda

Browse files
Chore: Validate start and end dates during plan build time
1 parent 41d06a0 commit 79fbeda

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
@@ -3002,3 +3002,59 @@ def test_uppercase_gateway_external_models(tmp_path):
30023002
assert len(uppercase_in_yaml_models) == 1, (
30033003
f"External model with uppercase gateway in YAML should be found. Found {len(uppercase_in_yaml_models)} models"
30043004
)
3005+
3006+
3007+
def test_plan_no_start_configured():
3008+
context = Context(config=Config())
3009+
context.upsert_model(
3010+
load_sql_based_model(
3011+
parse(
3012+
"""
3013+
MODEL(
3014+
name db.xvg,
3015+
kind INCREMENTAL_BY_TIME_RANGE (
3016+
time_column ds
3017+
),
3018+
cron '@daily'
3019+
);
3020+
3021+
SELECT id, ds FROM (VALUES
3022+
('1', '2020-01-01'),
3023+
) data(id, ds)
3024+
WHERE ds BETWEEN @start_ds AND @end_ds
3025+
"""
3026+
)
3027+
)
3028+
)
3029+
3030+
prod_plan = context.plan(auto_apply=True)
3031+
assert len(prod_plan.new_snapshots) == 1
3032+
3033+
context.upsert_model(
3034+
load_sql_based_model(
3035+
parse(
3036+
"""
3037+
MODEL(
3038+
name db.xvg,
3039+
kind INCREMENTAL_BY_TIME_RANGE (
3040+
time_column ds
3041+
),
3042+
cron '@daily',
3043+
physical_properties ('some_prop' = 1),
3044+
);
3045+
3046+
SELECT id, ds FROM (VALUES
3047+
('1', '2020-01-01'),
3048+
) data(id, ds)
3049+
WHERE ds BETWEEN @start_ds AND @end_ds
3050+
"""
3051+
)
3052+
)
3053+
)
3054+
3055+
# 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
3056+
with pytest.raises(
3057+
SQLMeshError,
3058+
match=r"Set the `start` attribute in your project config model defaults to avoid this issue",
3059+
):
3060+
context.plan("dev", execution_time="1999-01-05")

0 commit comments

Comments
 (0)