sqlmesh 0.196.5.dev16__py3-none-any.whl → 0.196.5.dev17__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/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.196.5.dev16'
21
- __version_tuple__ = version_tuple = (0, 196, 5, 'dev16')
20
+ __version__ = version = '0.196.5.dev17'
21
+ __version_tuple__ = version_tuple = (0, 196, 5, 'dev17')
@@ -1514,6 +1514,7 @@ class EngineAdapter:
1514
1514
  unique_key: t.Sequence[exp.Expression],
1515
1515
  valid_from_col: exp.Column,
1516
1516
  valid_to_col: exp.Column,
1517
+ start: TimeLike,
1517
1518
  execution_time: t.Union[TimeLike, exp.Column],
1518
1519
  invalidate_hard_deletes: bool = True,
1519
1520
  updated_at_col: t.Optional[exp.Column] = None,
@@ -1708,8 +1709,14 @@ class EngineAdapter:
1708
1709
  existing_rows_query = exp.select(*table_columns, exp.true().as_("_exists")).from_(
1709
1710
  target_table
1710
1711
  )
1712
+
1713
+ cleanup_ts = None
1711
1714
  if truncate:
1712
1715
  existing_rows_query = existing_rows_query.limit(0)
1716
+ else:
1717
+ # If truncate is false it is not the first insert
1718
+ # Determine the cleanup timestamp for restatement or a regular incremental run
1719
+ cleanup_ts = to_time_column(start, time_data_type, self.dialect, nullable=True)
1713
1720
 
1714
1721
  with source_queries[0] as source_query:
1715
1722
  prefixed_columns_to_types = []
@@ -1747,12 +1754,41 @@ class EngineAdapter:
1747
1754
  # Historical Records that Do Not Change
1748
1755
  .with_(
1749
1756
  "static",
1750
- existing_rows_query.where(valid_to_col.is_(exp.Null()).not_()),
1757
+ existing_rows_query.where(valid_to_col.is_(exp.Null()).not_())
1758
+ if truncate
1759
+ else existing_rows_query.where(
1760
+ exp.and_(
1761
+ valid_to_col.is_(exp.Null().not_()),
1762
+ valid_to_col < cleanup_ts,
1763
+ ),
1764
+ ),
1751
1765
  )
1752
1766
  # Latest Records that can be updated
1753
1767
  .with_(
1754
1768
  "latest",
1755
- existing_rows_query.where(valid_to_col.is_(exp.Null())),
1769
+ existing_rows_query.where(valid_to_col.is_(exp.Null()))
1770
+ if truncate
1771
+ else exp.select(
1772
+ *(
1773
+ to_time_column(
1774
+ exp.null(), time_data_type, self.dialect, nullable=True
1775
+ ).as_(col)
1776
+ if col == valid_to_col.name
1777
+ else exp.column(col)
1778
+ for col in columns_to_types
1779
+ ),
1780
+ exp.true().as_("_exists"),
1781
+ )
1782
+ .from_(target_table)
1783
+ .where(
1784
+ exp.and_(
1785
+ valid_from_col <= cleanup_ts,
1786
+ exp.or_(
1787
+ valid_to_col.is_(exp.null()),
1788
+ valid_to_col >= cleanup_ts,
1789
+ ),
1790
+ )
1791
+ ),
1756
1792
  )
1757
1793
  # Deleted records which can be used to determine `valid_from` for undeleted source records
1758
1794
  .with_(
@@ -256,6 +256,7 @@ class TrinoEngineAdapter(
256
256
  unique_key: t.Sequence[exp.Expression],
257
257
  valid_from_col: exp.Column,
258
258
  valid_to_col: exp.Column,
259
+ start: TimeLike,
259
260
  execution_time: t.Union[TimeLike, exp.Column],
260
261
  invalidate_hard_deletes: bool = True,
261
262
  updated_at_col: t.Optional[exp.Column] = None,
@@ -277,6 +278,7 @@ class TrinoEngineAdapter(
277
278
  unique_key,
278
279
  valid_from_col,
279
280
  valid_to_col,
281
+ start,
280
282
  execution_time,
281
283
  invalidate_hard_deletes,
282
284
  updated_at_col,
@@ -140,7 +140,6 @@ class ModelKindMixin:
140
140
  self.is_incremental_unmanaged
141
141
  or self.is_incremental_by_unique_key
142
142
  or self.is_incremental_by_partition
143
- or self.is_scd_type_2
144
143
  or self.is_managed
145
144
  or self.is_full
146
145
  or self.is_view
@@ -405,7 +405,7 @@ class PlanBuilder:
405
405
  elif (not self._is_dev or not snapshot.is_paused) and snapshot.disable_restatement:
406
406
  self._console.log_warning(
407
407
  f"Cannot restate model '{snapshot.name}'. "
408
- "Restatement is disabled for this model to prevent possible data loss."
408
+ "Restatement is disabled for this model to prevent possible data loss. "
409
409
  "If you want to restate this model, change the model's `disable_restatement` setting to `false`."
410
410
  )
411
411
  continue
@@ -797,6 +797,21 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
797
797
 
798
798
  removal_interval = expanded_removal_interval
799
799
 
800
+ # SCD Type 2 validation that end date is the latest interval if it was provided
801
+ if not is_preview and self.is_scd_type_2 and self.intervals:
802
+ requested_start, requested_end = removal_interval
803
+ latest_end = self.intervals[-1][1]
804
+ if requested_end < latest_end:
805
+ from sqlmesh.core.console import get_console
806
+
807
+ get_console().log_warning(
808
+ f"SCD Type 2 model '{self.model.name}' does not support end date in restatements.\n"
809
+ f"Requested end date [{to_ts(requested_end)}] is less than the latest interval end date.\n"
810
+ f"The requested end date will be ignored. Using the latest interval end instead: [{to_ts(latest_end)}]"
811
+ )
812
+
813
+ removal_interval = self.inclusive_exclusive(requested_start, latest_end, strict)
814
+
800
815
  return removal_interval
801
816
 
802
817
  @property
@@ -1788,6 +1788,7 @@ class SCDType2Strategy(MaterializableStrategy):
1788
1788
  table_description=model.description,
1789
1789
  column_descriptions=model.column_descriptions,
1790
1790
  truncate=is_first_insert,
1791
+ start=kwargs["start"],
1791
1792
  )
1792
1793
  elif isinstance(model.kind, SCDType2ByColumnKind):
1793
1794
  self.adapter.scd_type_2_by_column(
@@ -1805,6 +1806,7 @@ class SCDType2Strategy(MaterializableStrategy):
1805
1806
  table_description=model.description,
1806
1807
  column_descriptions=model.column_descriptions,
1807
1808
  truncate=is_first_insert,
1809
+ start=kwargs["start"],
1808
1810
  )
1809
1811
  else:
1810
1812
  raise SQLMeshError(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.196.5.dev16
3
+ Version: 0.196.5.dev17
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -1,5 +1,5 @@
1
1
  sqlmesh/__init__.py,sha256=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
2
- sqlmesh/_version.py,sha256=2TFk82XWA2X5PtM5G6k0sVLoGgJEReIoCAD6fqzZWS0,530
2
+ sqlmesh/_version.py,sha256=rLbV4hLoU9ecx9UrZoa9wKIl0Owes29-dAHNbw7wyx8,530
3
3
  sqlmesh/magics.py,sha256=R9U0Mp9ZQhDYe751nxAQDLaMv3zLAR4HcTdIflKTmEE,41709
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -59,7 +59,7 @@ sqlmesh/core/config/ui.py,sha256=jsO-S6_d9NkLZGG5pT4mgKgxMF34KzkDociZAMvCX3U,278
59
59
  sqlmesh/core/engine_adapter/__init__.py,sha256=two_WTs4UnSNp-fscJh8vOunJq0Xi37EuDuMjKsKuNE,2281
60
60
  sqlmesh/core/engine_adapter/_typing.py,sha256=_63pYCThfC39UtPVHY3N0H6qJ1YBT32OqwwR3swolGM,1037
61
61
  sqlmesh/core/engine_adapter/athena.py,sha256=WBVAB_YzBJXdiqq51LTd2jmYoMtGrLmtsA8IrIFVnQ0,26199
62
- sqlmesh/core/engine_adapter/base.py,sha256=R90ZhxpVb58Vl-zVse9fkNVbm3eD3lqi1PhW_WBOtAQ,102263
62
+ sqlmesh/core/engine_adapter/base.py,sha256=9dMfOQtgjTi551xM9Lxm5FK4MUoopvzwwgHjjDFnpzw,103788
63
63
  sqlmesh/core/engine_adapter/base_postgres.py,sha256=DOsOdCJyQAVfA9S0GznuH0J1bonMqYVP_yJLDYcxFYM,6772
64
64
  sqlmesh/core/engine_adapter/bigquery.py,sha256=qJE8vHLKKAeWMvltmYaUvWS95jM_UEZ6UzYLlr58sGo,50424
65
65
  sqlmesh/core/engine_adapter/clickhouse.py,sha256=LoPdm_s_s-ZxS1XJPA3Et0iOHeJ1LgqTAFbwBdiqE7A,34912
@@ -74,7 +74,7 @@ sqlmesh/core/engine_adapter/risingwave.py,sha256=YYCQ0EJaSrR9_P1_2_LmElQ6zSxqkZz
74
74
  sqlmesh/core/engine_adapter/shared.py,sha256=zL2W2t9af9mo80aSO0fz5TqV6mY8_kI5VYLswbKdZyk,13369
75
75
  sqlmesh/core/engine_adapter/snowflake.py,sha256=IEEzepxNpfqBIMe4ziz2k8fjOcJPeQPZyM3XljymAj0,28874
76
76
  sqlmesh/core/engine_adapter/spark.py,sha256=sYkVOPS0X43UPbI0z7Hh_EpKlI36qkOcr4NNFOTQlLs,21045
77
- sqlmesh/core/engine_adapter/trino.py,sha256=7WdLFlT0AyD5NF0EDP7GqX0SHF8sTm7cafBZxk84cmY,15798
77
+ sqlmesh/core/engine_adapter/trino.py,sha256=Ik5yOW_gYahVq6ksZPzE2Um-5J4A2AJv-QZiZYUPeP8,15842
78
78
  sqlmesh/core/linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
79
  sqlmesh/core/linter/definition.py,sha256=pXDxl8TxTGNuVc1B5ywYmaH7dDjsoMRvCtLCK_co-ek,5567
80
80
  sqlmesh/core/linter/helpers.py,sha256=VF4hsdzGZ8srpbtCjdRN_Hd8S_er5KTAaLXLde27Yxo,4032
@@ -89,12 +89,12 @@ sqlmesh/core/model/cache.py,sha256=csun0RJguHzKX6-qITcOs4fVP4f8_Ts8qiUVV4sHY6Q,7
89
89
  sqlmesh/core/model/common.py,sha256=PcQS3rHFNIXV_Z1dGwLQ7gLPbYVlrbWGGKAyc58-9Xk,17379
90
90
  sqlmesh/core/model/decorator.py,sha256=wUUg5t0K559tV9Pqt6FE2EWXt5TPGb4wF2Yg4B4hX4w,9251
91
91
  sqlmesh/core/model/definition.py,sha256=QUxpnWAmUDKw8GfdISPgL_W4cYII8LrwOj4-49e8XgE,111143
92
- sqlmesh/core/model/kind.py,sha256=iTfkZIeZ5GfJvW8MpjSOAIXJo-RtS-6JhGmgGSt_Q8s,36143
92
+ sqlmesh/core/model/kind.py,sha256=_SBjhrTUrCGkmcsKmabbmBIe1s_6aMIEPEaQh0cDIok,36109
93
93
  sqlmesh/core/model/meta.py,sha256=D9InI9M2-IXeb34vkXNQSLALL8xVXjZ_LXwI-Tqxm7I,21197
94
94
  sqlmesh/core/model/schema.py,sha256=OClbAeA8LpW-IiSiLT_TlDWkEqmIIvSk0GXq8SWI-GQ,3443
95
95
  sqlmesh/core/model/seed.py,sha256=a0M-1zY1gOkN5ph2GQyataEdBSCtq50YjeFk2LyvInI,5058
96
96
  sqlmesh/core/plan/__init__.py,sha256=NKSvM7ZBVjw9ho3J65M1wFvG3KURB8PJ0FHHLmtSF44,443
97
- sqlmesh/core/plan/builder.py,sha256=9M8Bzf6SZ3nnawowvu0jHSVCCVblz3srevJoOS7ppkM,41415
97
+ sqlmesh/core/plan/builder.py,sha256=g07h-NOsOr_4spnOrlQ4KrFjh3RmbvHSydEuSOsShNc,41416
98
98
  sqlmesh/core/plan/definition.py,sha256=OxgbvkMGNdlvYF2BjFJt_lINsBw38Fq1IX25P8_Z_Z0,13734
99
99
  sqlmesh/core/plan/evaluator.py,sha256=DkpJ78R33_RBx5MVY13CcGU0x2-EcKWkcrETsjuyn10,20484
100
100
  sqlmesh/core/plan/explainer.py,sha256=BEtww_UVa1gMkzL6-y2yrcy1EMQ8MbkElvO6L6s_TYU,12011
@@ -102,8 +102,8 @@ sqlmesh/core/plan/stages.py,sha256=5cvEbrQsw_cx1gayxwLRwkIehQPixrbUT9B4BbEOj3A,2
102
102
  sqlmesh/core/snapshot/__init__.py,sha256=Z5HTetNCZGoKF1WAKXk4LWL9dc8EC8lwS2O4TtoBmt4,1317
103
103
  sqlmesh/core/snapshot/cache.py,sha256=bgqCR2hyf6r2A_8QP1EnXFK25gDX37-Zg0YeMuETWxg,3934
104
104
  sqlmesh/core/snapshot/categorizer.py,sha256=qGG5870mu1jR2whKisSBH_GFbsyh96RnzJDgkN7DV9g,2482
105
- sqlmesh/core/snapshot/definition.py,sha256=a0pGUPHqlK_vBAaR0RZYloSiwkned07vT_KbxDs1ak8,84575
106
- sqlmesh/core/snapshot/evaluator.py,sha256=RA-ZFwG_BtkXSmls41gHRaCqa-h-evxXsDLE5jtgxvU,90173
105
+ sqlmesh/core/snapshot/definition.py,sha256=zbNqxmIi136n4Ee-25vvEVK0pICQM2KVsgm2qGR12l0,85447
106
+ sqlmesh/core/snapshot/evaluator.py,sha256=i5T5EZ4lEw7X7ZGapIhau6IxJ52nJcdvSixBu_utrhE,90251
107
107
  sqlmesh/core/state_sync/__init__.py,sha256=B60xj-_Xk-4jas3UphLvwkuf04G-9AyGckcblXE0aRg,869
108
108
  sqlmesh/core/state_sync/base.py,sha256=Drq4MDWWxO_J-sJIxsMG1-YSgj2L42n5WM2vh1sr6bc,18334
109
109
  sqlmesh/core/state_sync/cache.py,sha256=0AsYdQyBqbLdJvkBQ-hDAipsvnn_jSps-nya-Q4XeL0,5337
@@ -283,7 +283,7 @@ sqlmesh/utils/pydantic.py,sha256=I898jAFqa3qU6lG2uPpRebVFncOUo8ZrLWM_R3K3DHU,116
283
283
  sqlmesh/utils/rich.py,sha256=BpB47G0-JcU41LkGkeGKroexj4NOV5fox4-GOIXPgIc,3545
284
284
  sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
285
285
  sqlmesh/utils/yaml.py,sha256=hvo5lmybYLcIx4p6CQwufS8X4MbwS60lEBnCmYJCXmU,2336
286
- sqlmesh-0.196.5.dev16.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
286
+ sqlmesh-0.196.5.dev17.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
287
287
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
288
288
  web/client/dist/index.html,sha256=kNpFjWxt34Pf-P-cROtPWi3GNSVk6zqA3eoN9tlZXI0,5472
289
289
  web/client/dist/assets/Audits-DKgXravk.js,sha256=SaVQhNlislD_yQc_KivO7SPi1JH0ts1GnDPD5Zssutw,1041
@@ -401,8 +401,8 @@ web/server/api/endpoints/models.py,sha256=ud-lRwriyI_OYg9tZchrBgeiXELiRTLNEodraf
401
401
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
402
402
  web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
403
403
  web/server/api/endpoints/table_diff.py,sha256=SCy3-pr5x6bEEiOaZGCDbiHQhpgxwmnz3Acqa2Ie6jI,2090
404
- sqlmesh-0.196.5.dev16.dist-info/METADATA,sha256=kG1DmT409ZRa6Fx6zBvp4m7xlIKR73oggOdNDVPbft0,26621
405
- sqlmesh-0.196.5.dev16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
406
- sqlmesh-0.196.5.dev16.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
407
- sqlmesh-0.196.5.dev16.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
408
- sqlmesh-0.196.5.dev16.dist-info/RECORD,,
404
+ sqlmesh-0.196.5.dev17.dist-info/METADATA,sha256=tafFP47LimiJmXpFam5y9UY22QMDLypbXp1HuJv1JeI,26621
405
+ sqlmesh-0.196.5.dev17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
406
+ sqlmesh-0.196.5.dev17.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
407
+ sqlmesh-0.196.5.dev17.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
408
+ sqlmesh-0.196.5.dev17.dist-info/RECORD,,