sqlmesh 0.217.1.dev1__py3-none-any.whl → 0.227.2.dev20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqlmesh/__init__.py +12 -2
- sqlmesh/_version.py +2 -2
- sqlmesh/cli/project_init.py +10 -2
- sqlmesh/core/_typing.py +1 -0
- sqlmesh/core/audit/definition.py +8 -2
- sqlmesh/core/config/__init__.py +1 -1
- sqlmesh/core/config/connection.py +20 -5
- sqlmesh/core/config/dbt.py +13 -0
- sqlmesh/core/config/janitor.py +12 -0
- sqlmesh/core/config/loader.py +7 -0
- sqlmesh/core/config/model.py +2 -0
- sqlmesh/core/config/root.py +3 -0
- sqlmesh/core/console.py +80 -2
- sqlmesh/core/constants.py +1 -1
- sqlmesh/core/context.py +112 -35
- sqlmesh/core/dialect.py +3 -0
- sqlmesh/core/engine_adapter/_typing.py +2 -0
- sqlmesh/core/engine_adapter/base.py +330 -23
- sqlmesh/core/engine_adapter/base_postgres.py +17 -1
- sqlmesh/core/engine_adapter/bigquery.py +146 -7
- sqlmesh/core/engine_adapter/clickhouse.py +17 -13
- sqlmesh/core/engine_adapter/databricks.py +50 -2
- sqlmesh/core/engine_adapter/fabric.py +110 -29
- sqlmesh/core/engine_adapter/mixins.py +142 -48
- sqlmesh/core/engine_adapter/mssql.py +15 -4
- sqlmesh/core/engine_adapter/mysql.py +2 -2
- sqlmesh/core/engine_adapter/postgres.py +9 -3
- sqlmesh/core/engine_adapter/redshift.py +4 -0
- sqlmesh/core/engine_adapter/risingwave.py +1 -0
- sqlmesh/core/engine_adapter/shared.py +6 -0
- sqlmesh/core/engine_adapter/snowflake.py +82 -11
- sqlmesh/core/engine_adapter/spark.py +14 -10
- sqlmesh/core/engine_adapter/trino.py +5 -2
- sqlmesh/core/janitor.py +181 -0
- sqlmesh/core/lineage.py +1 -0
- sqlmesh/core/linter/rules/builtin.py +15 -0
- sqlmesh/core/loader.py +17 -30
- sqlmesh/core/macros.py +35 -13
- sqlmesh/core/model/common.py +2 -0
- sqlmesh/core/model/definition.py +72 -4
- sqlmesh/core/model/kind.py +66 -2
- sqlmesh/core/model/meta.py +107 -2
- sqlmesh/core/node.py +101 -2
- sqlmesh/core/plan/builder.py +15 -10
- sqlmesh/core/plan/common.py +196 -2
- sqlmesh/core/plan/definition.py +21 -6
- sqlmesh/core/plan/evaluator.py +72 -113
- sqlmesh/core/plan/explainer.py +90 -8
- sqlmesh/core/plan/stages.py +42 -21
- sqlmesh/core/renderer.py +26 -18
- sqlmesh/core/scheduler.py +60 -19
- sqlmesh/core/selector.py +137 -9
- sqlmesh/core/signal.py +64 -1
- sqlmesh/core/snapshot/__init__.py +1 -0
- sqlmesh/core/snapshot/definition.py +109 -25
- sqlmesh/core/snapshot/evaluator.py +610 -50
- sqlmesh/core/state_sync/__init__.py +0 -1
- sqlmesh/core/state_sync/base.py +31 -27
- sqlmesh/core/state_sync/cache.py +12 -4
- sqlmesh/core/state_sync/common.py +216 -111
- sqlmesh/core/state_sync/db/facade.py +30 -15
- sqlmesh/core/state_sync/db/interval.py +27 -7
- sqlmesh/core/state_sync/db/migrator.py +14 -8
- sqlmesh/core/state_sync/db/snapshot.py +119 -87
- sqlmesh/core/table_diff.py +2 -2
- sqlmesh/core/test/definition.py +14 -9
- sqlmesh/core/test/discovery.py +4 -0
- sqlmesh/dbt/adapter.py +20 -11
- sqlmesh/dbt/basemodel.py +52 -41
- sqlmesh/dbt/builtin.py +27 -11
- sqlmesh/dbt/column.py +17 -5
- sqlmesh/dbt/common.py +4 -2
- sqlmesh/dbt/context.py +14 -1
- sqlmesh/dbt/loader.py +60 -8
- sqlmesh/dbt/manifest.py +136 -8
- sqlmesh/dbt/model.py +105 -25
- sqlmesh/dbt/package.py +16 -1
- sqlmesh/dbt/profile.py +3 -3
- sqlmesh/dbt/project.py +12 -7
- sqlmesh/dbt/seed.py +1 -1
- sqlmesh/dbt/source.py +6 -1
- sqlmesh/dbt/target.py +25 -6
- sqlmesh/dbt/test.py +31 -1
- sqlmesh/integrations/github/cicd/controller.py +6 -2
- sqlmesh/lsp/context.py +4 -2
- sqlmesh/magics.py +1 -1
- sqlmesh/migrations/v0000_baseline.py +3 -6
- sqlmesh/migrations/v0061_mysql_fix_blob_text_type.py +2 -5
- sqlmesh/migrations/v0062_add_model_gateway.py +2 -2
- sqlmesh/migrations/v0063_change_signals.py +2 -4
- sqlmesh/migrations/v0064_join_when_matched_strings.py +2 -4
- sqlmesh/migrations/v0065_add_model_optimize.py +2 -2
- sqlmesh/migrations/v0066_add_auto_restatements.py +2 -6
- sqlmesh/migrations/v0067_add_tsql_date_full_precision.py +2 -2
- sqlmesh/migrations/v0068_include_unrendered_query_in_metadata_hash.py +2 -2
- sqlmesh/migrations/v0069_update_dev_table_suffix.py +2 -4
- sqlmesh/migrations/v0070_include_grains_in_metadata_hash.py +2 -2
- sqlmesh/migrations/v0071_add_dev_version_to_intervals.py +2 -6
- sqlmesh/migrations/v0072_add_environment_statements.py +2 -4
- sqlmesh/migrations/v0073_remove_symbolic_disable_restatement.py +2 -4
- sqlmesh/migrations/v0074_add_partition_by_time_column_property.py +2 -2
- sqlmesh/migrations/v0075_remove_validate_query.py +2 -4
- sqlmesh/migrations/v0076_add_cron_tz.py +2 -2
- sqlmesh/migrations/v0077_fix_column_type_hash_calculation.py +2 -2
- sqlmesh/migrations/v0078_warn_if_non_migratable_python_env.py +2 -4
- sqlmesh/migrations/v0079_add_gateway_managed_property.py +7 -9
- sqlmesh/migrations/v0080_add_batch_size_to_scd_type_2_models.py +2 -2
- sqlmesh/migrations/v0081_update_partitioned_by.py +2 -4
- sqlmesh/migrations/v0082_warn_if_incorrectly_duplicated_statements.py +2 -4
- sqlmesh/migrations/v0083_use_sql_for_scd_time_data_type_data_hash.py +2 -2
- sqlmesh/migrations/v0084_normalize_quote_when_matched_and_merge_filter.py +2 -2
- sqlmesh/migrations/v0085_deterministic_repr.py +2 -4
- sqlmesh/migrations/v0086_check_deterministic_bug.py +2 -4
- sqlmesh/migrations/v0087_normalize_blueprint_variables.py +2 -4
- sqlmesh/migrations/v0088_warn_about_variable_python_env_diffs.py +2 -4
- sqlmesh/migrations/v0089_add_virtual_environment_mode.py +2 -2
- sqlmesh/migrations/v0090_add_forward_only_column.py +2 -6
- sqlmesh/migrations/v0091_on_additive_change.py +2 -2
- sqlmesh/migrations/v0092_warn_about_dbt_data_type_diff.py +2 -4
- sqlmesh/migrations/v0093_use_raw_sql_in_fingerprint.py +2 -2
- sqlmesh/migrations/v0094_add_dev_version_and_fingerprint_columns.py +2 -6
- sqlmesh/migrations/v0095_warn_about_dbt_raw_sql_diff.py +2 -4
- sqlmesh/migrations/v0096_remove_plan_dags_table.py +2 -4
- sqlmesh/migrations/v0097_add_dbt_name_in_node.py +2 -2
- sqlmesh/migrations/v0098_add_dbt_node_info_in_node.py +103 -0
- sqlmesh/migrations/v0099_add_last_altered_to_intervals.py +25 -0
- sqlmesh/migrations/v0100_add_grants_and_grants_target_layer.py +9 -0
- sqlmesh/utils/__init__.py +8 -1
- sqlmesh/utils/cache.py +5 -1
- sqlmesh/utils/date.py +1 -1
- sqlmesh/utils/errors.py +4 -0
- sqlmesh/utils/git.py +3 -1
- sqlmesh/utils/jinja.py +25 -2
- sqlmesh/utils/pydantic.py +6 -6
- sqlmesh/utils/windows.py +13 -3
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/METADATA +5 -5
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/RECORD +188 -183
- sqlmesh_dbt/cli.py +70 -7
- sqlmesh_dbt/console.py +14 -6
- sqlmesh_dbt/operations.py +103 -24
- sqlmesh_dbt/selectors.py +39 -1
- web/client/dist/assets/{Audits-Ucsx1GzF.js → Audits-CBiYyyx-.js} +1 -1
- web/client/dist/assets/{Banner-BWDzvavM.js → Banner-DSRbUlO5.js} +1 -1
- web/client/dist/assets/{ChevronDownIcon-D2VL13Ah.js → ChevronDownIcon-MK_nrjD_.js} +1 -1
- web/client/dist/assets/{ChevronRightIcon-DWGYbf1l.js → ChevronRightIcon-CLWtT22Q.js} +1 -1
- web/client/dist/assets/{Content-DdHDZM3I.js → Content-BNuGZN5l.js} +1 -1
- web/client/dist/assets/{Content-Bikfy8fh.js → Content-CSHJyW0n.js} +1 -1
- web/client/dist/assets/{Data-CzAJH7rW.js → Data-C1oRDbLx.js} +1 -1
- web/client/dist/assets/{DataCatalog-BJF11g8f.js → DataCatalog-HXyX2-_j.js} +1 -1
- web/client/dist/assets/{Editor-s0SBpV2y.js → Editor-BDyfpUuw.js} +1 -1
- web/client/dist/assets/{Editor-DgLhgKnm.js → Editor-D0jNItwC.js} +1 -1
- web/client/dist/assets/{Errors-D0m0O1d3.js → Errors-BfuFLcPi.js} +1 -1
- web/client/dist/assets/{FileExplorer-CEv0vXkt.js → FileExplorer-BR9IE3he.js} +1 -1
- web/client/dist/assets/{Footer-BwzXn8Ew.js → Footer-CgBEtiAh.js} +1 -1
- web/client/dist/assets/{Header-6heDkEqG.js → Header-DSqR6nSO.js} +1 -1
- web/client/dist/assets/{Input-obuJsD6k.js → Input-B-oZ6fGO.js} +1 -1
- web/client/dist/assets/Lineage-DYQVwDbD.js +1 -0
- web/client/dist/assets/{ListboxShow-HM9_qyrt.js → ListboxShow-BE5-xevs.js} +1 -1
- web/client/dist/assets/{ModelLineage-zWdKo0U2.js → ModelLineage-DkIFAYo4.js} +1 -1
- web/client/dist/assets/{Models-Bcu66SRz.js → Models-D5dWr8RB.js} +1 -1
- web/client/dist/assets/{Page-BWEEQfIt.js → Page-C-XfU5BR.js} +1 -1
- web/client/dist/assets/{Plan-C4gXCqlf.js → Plan-ZEuTINBq.js} +1 -1
- web/client/dist/assets/{PlusCircleIcon-CVDO651q.js → PlusCircleIcon-DVXAHG8_.js} +1 -1
- web/client/dist/assets/{ReportErrors-BT6xFwAr.js → ReportErrors-B7FEPzMB.js} +1 -1
- web/client/dist/assets/{Root-ryJoBK4h.js → Root-8aZyhPxF.js} +1 -1
- web/client/dist/assets/{SearchList-DB04sPb9.js → SearchList-W_iT2G82.js} +1 -1
- web/client/dist/assets/{SelectEnvironment-CUYcXUu6.js → SelectEnvironment-C65jALmO.js} +1 -1
- web/client/dist/assets/{SourceList-Doo_9ZGp.js → SourceList-DSLO6nVJ.js} +1 -1
- web/client/dist/assets/{SourceListItem-D5Mj7Dly.js → SourceListItem-BHt8d9-I.js} +1 -1
- web/client/dist/assets/{SplitPane-qHmkD1qy.js → SplitPane-CViaZmw6.js} +1 -1
- web/client/dist/assets/{Tests-DH1Z74ML.js → Tests-DhaVt5t1.js} +1 -1
- web/client/dist/assets/{Welcome-DqUJUNMF.js → Welcome-DvpjH-_4.js} +1 -1
- web/client/dist/assets/context-BctCsyGb.js +71 -0
- web/client/dist/assets/{context-Dr54UHLi.js → context-DFNeGsFF.js} +1 -1
- web/client/dist/assets/{editor-DYIP1yQ4.js → editor-CcO28cqd.js} +1 -1
- web/client/dist/assets/{file-DarlIDVi.js → file-CvJN3aZO.js} +1 -1
- web/client/dist/assets/{floating-ui.react-dom-BH3TFvkM.js → floating-ui.react-dom-CjE-JNW1.js} +1 -1
- web/client/dist/assets/{help-Bl8wqaQc.js → help-DuPhjipa.js} +1 -1
- web/client/dist/assets/{index-D1sR7wpN.js → index-C-dJH7yZ.js} +1 -1
- web/client/dist/assets/{index-O3mjYpnE.js → index-Dj0i1-CA.js} +2 -2
- web/client/dist/assets/{plan-CehRrJUG.js → plan-BTRSbjKn.js} +1 -1
- web/client/dist/assets/{popover-CqgMRE0G.js → popover-_Sf0yvOI.js} +1 -1
- web/client/dist/assets/{project-6gxepOhm.js → project-BvSOI8MY.js} +1 -1
- web/client/dist/index.html +1 -1
- web/client/dist/assets/Lineage-D0Hgdz2v.js +0 -1
- web/client/dist/assets/context-DgX0fp2E.js +0 -68
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/WHEEL +0 -0
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev20.dist-info}/top_level.txt +0 -0
|
@@ -11,6 +11,7 @@ from sqlmesh.core.snapshot.definition import (
|
|
|
11
11
|
SnapshotId as SnapshotId,
|
|
12
12
|
SnapshotIdBatch as SnapshotIdBatch,
|
|
13
13
|
SnapshotIdLike as SnapshotIdLike,
|
|
14
|
+
SnapshotIdAndVersionLike as SnapshotIdAndVersionLike,
|
|
14
15
|
SnapshotInfoLike as SnapshotInfoLike,
|
|
15
16
|
SnapshotIntervals as SnapshotIntervals,
|
|
16
17
|
SnapshotNameVersion as SnapshotNameVersion,
|
|
@@ -185,6 +185,8 @@ class SnapshotIntervals(PydanticModel):
|
|
|
185
185
|
intervals: Intervals = []
|
|
186
186
|
dev_intervals: Intervals = []
|
|
187
187
|
pending_restatement_intervals: Intervals = []
|
|
188
|
+
last_altered_ts: t.Optional[int] = None
|
|
189
|
+
dev_last_altered_ts: t.Optional[int] = None
|
|
188
190
|
|
|
189
191
|
@property
|
|
190
192
|
def snapshot_id(self) -> t.Optional[SnapshotId]:
|
|
@@ -205,6 +207,12 @@ class SnapshotIntervals(PydanticModel):
|
|
|
205
207
|
def add_pending_restatement_interval(self, start: int, end: int) -> None:
|
|
206
208
|
self._add_interval(start, end, "pending_restatement_intervals")
|
|
207
209
|
|
|
210
|
+
def update_last_altered_ts(self, last_altered_ts: t.Optional[int]) -> None:
|
|
211
|
+
self._update_last_altered_ts(last_altered_ts, "last_altered_ts")
|
|
212
|
+
|
|
213
|
+
def update_dev_last_altered_ts(self, last_altered_ts: t.Optional[int]) -> None:
|
|
214
|
+
self._update_last_altered_ts(last_altered_ts, "dev_last_altered_ts")
|
|
215
|
+
|
|
208
216
|
def remove_interval(self, start: int, end: int) -> None:
|
|
209
217
|
self._remove_interval(start, end, "intervals")
|
|
210
218
|
|
|
@@ -224,6 +232,13 @@ class SnapshotIntervals(PydanticModel):
|
|
|
224
232
|
target_intervals = merge_intervals([*target_intervals, (start, end)])
|
|
225
233
|
setattr(self, interval_attr, target_intervals)
|
|
226
234
|
|
|
235
|
+
def _update_last_altered_ts(
|
|
236
|
+
self, last_altered_ts: t.Optional[int], last_altered_attr: str
|
|
237
|
+
) -> None:
|
|
238
|
+
if last_altered_ts:
|
|
239
|
+
existing_last_altered_ts = getattr(self, last_altered_attr)
|
|
240
|
+
setattr(self, last_altered_attr, max(existing_last_altered_ts or 0, last_altered_ts))
|
|
241
|
+
|
|
227
242
|
def _remove_interval(self, start: int, end: int, interval_attr: str) -> None:
|
|
228
243
|
target_intervals = getattr(self, interval_attr)
|
|
229
244
|
target_intervals = remove_interval(target_intervals, start, end)
|
|
@@ -587,14 +602,26 @@ class SnapshotTableInfo(PydanticModel, SnapshotInfoMixin, frozen=True):
|
|
|
587
602
|
"""Returns the name and version of the snapshot."""
|
|
588
603
|
return SnapshotNameVersion(name=self.name, version=self.version)
|
|
589
604
|
|
|
605
|
+
@property
|
|
606
|
+
def id_and_version(self) -> SnapshotIdAndVersion:
|
|
607
|
+
return SnapshotIdAndVersion(
|
|
608
|
+
name=self.name,
|
|
609
|
+
kind_name=self.kind_name,
|
|
610
|
+
identifier=self.identifier,
|
|
611
|
+
version=self.version,
|
|
612
|
+
dev_version=self.dev_version,
|
|
613
|
+
fingerprint=self.fingerprint,
|
|
614
|
+
)
|
|
590
615
|
|
|
591
|
-
|
|
616
|
+
|
|
617
|
+
class SnapshotIdAndVersion(PydanticModel, ModelKindMixin):
|
|
592
618
|
"""A stripped down version of a snapshot that is used in situations where we want to fetch the main fields of the snapshots table
|
|
593
619
|
without the overhead of parsing the full snapshot payload and fetching intervals.
|
|
594
620
|
"""
|
|
595
621
|
|
|
596
622
|
name: str
|
|
597
623
|
version: str
|
|
624
|
+
kind_name_: t.Optional[ModelKindName] = Field(default=None, alias="kind_name")
|
|
598
625
|
dev_version_: t.Optional[str] = Field(alias="dev_version")
|
|
599
626
|
identifier: str
|
|
600
627
|
fingerprint_: t.Union[str, SnapshotFingerprint] = Field(alias="fingerprint")
|
|
@@ -603,6 +630,10 @@ class SnapshotIdAndVersion(PydanticModel):
|
|
|
603
630
|
def snapshot_id(self) -> SnapshotId:
|
|
604
631
|
return SnapshotId(name=self.name, identifier=self.identifier)
|
|
605
632
|
|
|
633
|
+
@property
|
|
634
|
+
def id_and_version(self) -> SnapshotIdAndVersion:
|
|
635
|
+
return self
|
|
636
|
+
|
|
606
637
|
@property
|
|
607
638
|
def name_version(self) -> SnapshotNameVersion:
|
|
608
639
|
return SnapshotNameVersion(name=self.name, version=self.version)
|
|
@@ -618,6 +649,20 @@ class SnapshotIdAndVersion(PydanticModel):
|
|
|
618
649
|
def dev_version(self) -> str:
|
|
619
650
|
return self.dev_version_ or self.fingerprint.to_version()
|
|
620
651
|
|
|
652
|
+
@property
|
|
653
|
+
def model_kind_name(self) -> t.Optional[ModelKindName]:
|
|
654
|
+
return self.kind_name_
|
|
655
|
+
|
|
656
|
+
def display_name(
|
|
657
|
+
self,
|
|
658
|
+
environment_naming_info: EnvironmentNamingInfo,
|
|
659
|
+
default_catalog: t.Optional[str],
|
|
660
|
+
dialect: DialectType = None,
|
|
661
|
+
) -> str:
|
|
662
|
+
return model_display_name(
|
|
663
|
+
self.name, environment_naming_info, default_catalog, dialect=dialect
|
|
664
|
+
)
|
|
665
|
+
|
|
621
666
|
|
|
622
667
|
class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
623
668
|
"""A snapshot represents a node at a certain point in time.
|
|
@@ -683,6 +728,10 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
683
728
|
dev_table_suffix: str = "dev"
|
|
684
729
|
table_naming_convention: TableNamingConvention = TableNamingConvention.default
|
|
685
730
|
forward_only: bool = False
|
|
731
|
+
# Physical table last modified timestamp, not to be confused with the "updated_ts" field
|
|
732
|
+
# which is for the snapshot record itself
|
|
733
|
+
last_altered_ts: t.Optional[int] = None
|
|
734
|
+
dev_last_altered_ts: t.Optional[int] = None
|
|
686
735
|
|
|
687
736
|
@field_validator("ttl")
|
|
688
737
|
@classmethod
|
|
@@ -721,6 +770,7 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
721
770
|
)
|
|
722
771
|
for interval in snapshot_intervals:
|
|
723
772
|
snapshot.merge_intervals(interval)
|
|
773
|
+
|
|
724
774
|
result.append(snapshot)
|
|
725
775
|
|
|
726
776
|
return result
|
|
@@ -927,12 +977,20 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
927
977
|
if not apply_effective_from or end <= effective_from_ts:
|
|
928
978
|
self.add_interval(start, end)
|
|
929
979
|
|
|
980
|
+
if other.last_altered_ts:
|
|
981
|
+
self.last_altered_ts = max(self.last_altered_ts or 0, other.last_altered_ts)
|
|
982
|
+
|
|
930
983
|
if self.dev_version == other.dev_version:
|
|
931
984
|
# Merge dev intervals if the dev versions match which would mean
|
|
932
985
|
# that this and the other snapshot are pointing to the same dev table.
|
|
933
986
|
for start, end in other.dev_intervals:
|
|
934
987
|
self.add_interval(start, end, is_dev=True)
|
|
935
988
|
|
|
989
|
+
if other.dev_last_altered_ts:
|
|
990
|
+
self.dev_last_altered_ts = max(
|
|
991
|
+
self.dev_last_altered_ts or 0, other.dev_last_altered_ts
|
|
992
|
+
)
|
|
993
|
+
|
|
936
994
|
self.pending_restatement_intervals = merge_intervals(
|
|
937
995
|
[*self.pending_restatement_intervals, *other.pending_restatement_intervals]
|
|
938
996
|
)
|
|
@@ -1051,6 +1109,7 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
1051
1109
|
python_env=signals.python_env,
|
|
1052
1110
|
dialect=self.model.dialect,
|
|
1053
1111
|
path=self.model._path,
|
|
1112
|
+
snapshot=self,
|
|
1054
1113
|
kwargs=kwargs,
|
|
1055
1114
|
)
|
|
1056
1115
|
except SQLMeshError as e:
|
|
@@ -1424,6 +1483,10 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
1424
1483
|
"""Returns the name and version of the snapshot."""
|
|
1425
1484
|
return SnapshotNameVersion(name=self.name, version=self.version)
|
|
1426
1485
|
|
|
1486
|
+
@property
|
|
1487
|
+
def id_and_version(self) -> SnapshotIdAndVersion:
|
|
1488
|
+
return self.table_info.id_and_version
|
|
1489
|
+
|
|
1427
1490
|
@property
|
|
1428
1491
|
def disable_restatement(self) -> bool:
|
|
1429
1492
|
"""Is restatement disabled for the node"""
|
|
@@ -1443,19 +1506,19 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
|
|
|
1443
1506
|
check_categorical_relative_expression=False,
|
|
1444
1507
|
)
|
|
1445
1508
|
|
|
1509
|
+
@property
|
|
1510
|
+
def supports_schema_migration_in_prod(self) -> bool:
|
|
1511
|
+
"""Returns whether or not this snapshot supports schema migration when deployed to production."""
|
|
1512
|
+
return self.is_paused and self.is_model and not self.is_symbolic and not self.is_seed
|
|
1513
|
+
|
|
1446
1514
|
@property
|
|
1447
1515
|
def requires_schema_migration_in_prod(self) -> bool:
|
|
1448
1516
|
"""Returns whether or not this snapshot requires a schema migration when deployed to production."""
|
|
1449
|
-
return (
|
|
1450
|
-
self.
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
(self.previous_version and self.previous_version.version == self.version)
|
|
1455
|
-
or self.model.forward_only
|
|
1456
|
-
or bool(self.model.physical_version)
|
|
1457
|
-
or not self.virtual_environment_mode.is_full
|
|
1458
|
-
)
|
|
1517
|
+
return self.supports_schema_migration_in_prod and (
|
|
1518
|
+
(self.previous_version and self.previous_version.version == self.version)
|
|
1519
|
+
or self.model.forward_only
|
|
1520
|
+
or bool(self.model.physical_version)
|
|
1521
|
+
or not self.virtual_environment_mode.is_full
|
|
1459
1522
|
)
|
|
1460
1523
|
|
|
1461
1524
|
@property
|
|
@@ -1494,7 +1557,8 @@ class SnapshotTableCleanupTask(PydanticModel):
|
|
|
1494
1557
|
dev_table_only: bool
|
|
1495
1558
|
|
|
1496
1559
|
|
|
1497
|
-
SnapshotIdLike = t.Union[SnapshotId,
|
|
1560
|
+
SnapshotIdLike = t.Union[SnapshotId, SnapshotIdAndVersion, SnapshotTableInfo, Snapshot]
|
|
1561
|
+
SnapshotIdAndVersionLike = t.Union[SnapshotIdAndVersion, SnapshotTableInfo, Snapshot]
|
|
1498
1562
|
SnapshotInfoLike = t.Union[SnapshotTableInfo, Snapshot]
|
|
1499
1563
|
SnapshotNameVersionLike = t.Union[
|
|
1500
1564
|
SnapshotNameVersion, SnapshotTableInfo, SnapshotIdAndVersion, Snapshot
|
|
@@ -1763,7 +1827,19 @@ def display_name(
|
|
|
1763
1827
|
"""
|
|
1764
1828
|
if snapshot_info_like.is_audit:
|
|
1765
1829
|
return snapshot_info_like.name
|
|
1766
|
-
|
|
1830
|
+
|
|
1831
|
+
return model_display_name(
|
|
1832
|
+
snapshot_info_like.name, environment_naming_info, default_catalog, dialect
|
|
1833
|
+
)
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
def model_display_name(
|
|
1837
|
+
node_name: str,
|
|
1838
|
+
environment_naming_info: EnvironmentNamingInfo,
|
|
1839
|
+
default_catalog: t.Optional[str],
|
|
1840
|
+
dialect: DialectType = None,
|
|
1841
|
+
) -> str:
|
|
1842
|
+
view_name = exp.to_table(node_name)
|
|
1767
1843
|
|
|
1768
1844
|
catalog = (
|
|
1769
1845
|
None
|
|
@@ -2005,16 +2081,20 @@ def missing_intervals(
|
|
|
2005
2081
|
continue
|
|
2006
2082
|
snapshot_end_date = existing_interval_end
|
|
2007
2083
|
|
|
2084
|
+
snapshot_start_date = max(
|
|
2085
|
+
to_datetime(snapshot_start_date),
|
|
2086
|
+
to_datetime(start_date(snapshot, snapshots, cache, relative_to=snapshot_end_date)),
|
|
2087
|
+
)
|
|
2088
|
+
if snapshot_start_date > to_datetime(snapshot_end_date):
|
|
2089
|
+
continue
|
|
2090
|
+
|
|
2008
2091
|
missing_interval_end_date = snapshot_end_date
|
|
2009
2092
|
node_end_date = snapshot.node.end
|
|
2010
2093
|
if node_end_date and (to_datetime(node_end_date) < to_datetime(snapshot_end_date)):
|
|
2011
2094
|
missing_interval_end_date = node_end_date
|
|
2012
2095
|
|
|
2013
2096
|
intervals = snapshot.missing_intervals(
|
|
2014
|
-
|
|
2015
|
-
to_datetime(snapshot_start_date),
|
|
2016
|
-
to_datetime(start_date(snapshot, snapshots, cache, relative_to=snapshot_end_date)),
|
|
2017
|
-
),
|
|
2097
|
+
snapshot_start_date,
|
|
2018
2098
|
missing_interval_end_date,
|
|
2019
2099
|
execution_time=execution_time,
|
|
2020
2100
|
deployability_index=deployability_index,
|
|
@@ -2219,14 +2299,16 @@ def start_date(
|
|
|
2219
2299
|
if not isinstance(snapshots, dict):
|
|
2220
2300
|
snapshots = {snapshot.snapshot_id: snapshot for snapshot in snapshots}
|
|
2221
2301
|
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
if parent in snapshots
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2302
|
+
parent_starts = [
|
|
2303
|
+
start_date(snapshots[parent], snapshots, cache=cache, relative_to=relative_to)
|
|
2304
|
+
for parent in snapshot.parents
|
|
2305
|
+
if parent in snapshots
|
|
2306
|
+
]
|
|
2307
|
+
earliest = (
|
|
2308
|
+
min(parent_starts)
|
|
2309
|
+
if parent_starts
|
|
2310
|
+
else snapshot.node.cron_prev(snapshot.node.cron_floor(relative_to or now()))
|
|
2311
|
+
)
|
|
2230
2312
|
|
|
2231
2313
|
cache[key] = earliest
|
|
2232
2314
|
return earliest
|
|
@@ -2374,6 +2456,7 @@ def check_ready_intervals(
|
|
|
2374
2456
|
python_env: t.Dict[str, Executable],
|
|
2375
2457
|
dialect: DialectType = None,
|
|
2376
2458
|
path: t.Optional[Path] = None,
|
|
2459
|
+
snapshot: t.Optional[Snapshot] = None,
|
|
2377
2460
|
kwargs: t.Optional[t.Dict] = None,
|
|
2378
2461
|
) -> Intervals:
|
|
2379
2462
|
checked_intervals: Intervals = []
|
|
@@ -2389,6 +2472,7 @@ def check_ready_intervals(
|
|
|
2389
2472
|
provided_args=(batch,),
|
|
2390
2473
|
provided_kwargs=(kwargs or {}),
|
|
2391
2474
|
context=context,
|
|
2475
|
+
snapshot=snapshot,
|
|
2392
2476
|
)
|
|
2393
2477
|
except Exception as ex:
|
|
2394
2478
|
raise SignalEvalError(format_evaluated_code_exception(ex, python_env))
|