Skip to content

Fix: Make plan dates relative to --execution-time#4702

Merged
erindru merged 2 commits intomainfrom
erin/plan-relative-start
Jun 13, 2025
Merged

Fix: Make plan dates relative to --execution-time#4702
erindru merged 2 commits intomainfrom
erin/plan-relative-start

Conversation

@erindru
Copy link
Copy Markdown
Collaborator

@erindru erindru commented Jun 10, 2025

This addresses some issues with setting --execution-time on a plan, which is intended to run a plan "as at" a certain time.

Currently, if you specify a relative start date like --start '2 days ago' and then you specify a fixed --execution-time, eg --execution-time '2020-01-05', SQLMesh will make the start date relative to the current time and not the execution time.

This gets confusing because it makes the plan start / end and any relative dates show no relation to the execution time.

This is also causes problems when --execution-time is set to a value older than the latest prod interval for a model, eg:

$ sqlmesh plan dev --execution-time 2020-01-05 --start '2 days ago'
...SNIP
Error: Start date / time (2 days ago) can't be greater than end date / time (1749168000000)

This PR tightens up the behavior, adds new checks at the plan building stage and adds tests to verify the relative date behaviour.

After this PR, the above command works as intended by making the plan end time not able to exceed the execution time

@erindru erindru force-pushed the erin/plan-relative-start branch from 6ddf355 to b4ddf75 Compare June 10, 2025 05:06

@property
def execution_time(self) -> TimeLike:
return self._execution_time or now()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we fall back to now() in constructor? So that we have it return the same value throughout the plan building process?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that seems to work. I've updated it

Copy link
Copy Markdown
Collaborator Author

@erindru erindru Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reverted defaulting to now() in the constructor and left a comment for next time, based on the conversation below

Comment thread sqlmesh/core/plan/builder.py Outdated
models_to_backfill=models_to_backfill,
effective_from=self._effective_from,
execution_time=self._execution_time,
execution_time=self.execution_time,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we should keep None if the execution_time wasn't specified explicitly. This way the execution_time will be determined at runtime, which is something I believe we want.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been defaulted to now() in the PlanBuilder constructor, right?

In general, allowing it to be None is a bit annoying because every place that needs to use the value has to implement fallback behaviour if the value is not specified.

If the fallback is always "default to now()" then isn't it better to make this explicit up front?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been defaulted to now() in the PlanBuilder constructor, right?

sorry, the 2 suggestions were made independently. As far as I can tell we don't fall back to now() in constructor in main.

In general, allowing it to be None is a bit annoying because every place that needs to use the value has to implement fallback behaviour if the value is not specified.

I think it's fine to have it as @cached_property in the builder and elsewhere. But I'd prefer the value to be correctly set at runtime since there can be a non-insignificant delay between plan construction and application.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so if I understand correctly, if it's sent to the PlanBuilder as None then that should still be None in the resulting Plan as well?

i.e as part of building the plan, don't default it to now()?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's exactly what I mean, yes

Copy link
Copy Markdown
Collaborator Author

@erindru erindru Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I've removed the default in the constructor and use it like self._execution_time or now() when it is referenced in the PlanBuilder in places that might be dealing with relative time strings.

I stopped short of adding @cached_property for it because I thought it might be confusing having self.execution_time used within the PlanBuilder but self._execution_time being used when constructing the Plan

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stopped short of adding @cached_property for it because I thought it might be confusing having self.execution_time used within the PlanBuilder but self._execution_time being used when constructing the Plan

Isn't this problematic too? Now we get inconsistent execution_time throughout the plan building process

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, i've reverted this back to my original design except with @cached_property instead of @property and added a comment explaining what's going on

Comment thread sqlmesh/core/plan/definition.py Outdated
@erindru erindru force-pushed the erin/plan-relative-start branch 2 times, most recently from ce2fdfb to 52786d5 Compare June 11, 2025 01:07
@erindru erindru requested a review from izeigerman June 11, 2025 01:18
@erindru erindru force-pushed the erin/plan-relative-start branch from 52786d5 to d70504a Compare June 12, 2025 03:50
@erindru erindru force-pushed the erin/plan-relative-start branch from d70504a to 3934324 Compare June 12, 2025 20:26
@erindru erindru merged commit 660be25 into main Jun 13, 2025
25 checks passed
@erindru erindru deleted the erin/plan-relative-start branch June 13, 2025 00:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants