sqlmesh 0.219.0__py3-none-any.whl → 0.219.1.dev2__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 +2 -2
- sqlmesh/core/context.py +21 -2
- sqlmesh/core/plan/builder.py +6 -10
- sqlmesh/core/plan/definition.py +4 -0
- sqlmesh/core/plan/stages.py +12 -6
- sqlmesh/core/snapshot/evaluator.py +6 -2
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/METADATA +1 -1
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/RECORD +14 -14
- sqlmesh_dbt/cli.py +3 -1
- sqlmesh_dbt/operations.py +63 -16
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/WHEEL +0 -0
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.219.0.dist-info → sqlmesh-0.219.1.dev2.dist-info}/top_level.txt +0 -0
sqlmesh/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.219.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 219,
|
|
31
|
+
__version__ = version = '0.219.1.dev2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 219, 1, 'dev2')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
sqlmesh/core/context.py
CHANGED
|
@@ -1429,6 +1429,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1429
1429
|
explain: t.Optional[bool] = None,
|
|
1430
1430
|
ignore_cron: t.Optional[bool] = None,
|
|
1431
1431
|
min_intervals: t.Optional[int] = None,
|
|
1432
|
+
always_include_local_changes: t.Optional[bool] = None,
|
|
1432
1433
|
) -> PlanBuilder:
|
|
1433
1434
|
"""Creates a plan builder.
|
|
1434
1435
|
|
|
@@ -1467,6 +1468,8 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1467
1468
|
diff_rendered: Whether the diff should compare raw vs rendered models
|
|
1468
1469
|
min_intervals: Adjust the plan start date on a per-model basis in order to ensure at least this many intervals are covered
|
|
1469
1470
|
on every model when checking for missing intervals
|
|
1471
|
+
always_include_local_changes: Usually when restatements are present, local changes in the filesystem are ignored.
|
|
1472
|
+
However, it can be desirable to deploy changes + restatements in the same plan, so this flag overrides the default behaviour.
|
|
1470
1473
|
|
|
1471
1474
|
Returns:
|
|
1472
1475
|
The plan builder.
|
|
@@ -1583,13 +1586,20 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1583
1586
|
"Selector did not return any models. Please check your model selection and try again."
|
|
1584
1587
|
)
|
|
1585
1588
|
|
|
1589
|
+
if always_include_local_changes is None:
|
|
1590
|
+
# default behaviour - if restatements are detected; we operate entirely out of state and ignore local changes
|
|
1591
|
+
force_no_diff = restate_models is not None or (
|
|
1592
|
+
backfill_models is not None and not backfill_models
|
|
1593
|
+
)
|
|
1594
|
+
else:
|
|
1595
|
+
force_no_diff = not always_include_local_changes
|
|
1596
|
+
|
|
1586
1597
|
snapshots = self._snapshots(models_override)
|
|
1587
1598
|
context_diff = self._context_diff(
|
|
1588
1599
|
environment or c.PROD,
|
|
1589
1600
|
snapshots=snapshots,
|
|
1590
1601
|
create_from=create_from,
|
|
1591
|
-
force_no_diff=
|
|
1592
|
-
or (backfill_models is not None and not backfill_models),
|
|
1602
|
+
force_no_diff=force_no_diff,
|
|
1593
1603
|
ensure_finalized_snapshots=self.config.plan.use_finalized_state,
|
|
1594
1604
|
diff_rendered=diff_rendered,
|
|
1595
1605
|
always_recreate_environment=self.config.plan.always_recreate_environment,
|
|
@@ -1644,6 +1654,14 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1644
1654
|
elif forward_only is None:
|
|
1645
1655
|
forward_only = self.config.plan.forward_only
|
|
1646
1656
|
|
|
1657
|
+
# When handling prod restatements, only clear intervals from other model versions if we are using full virtual environments
|
|
1658
|
+
# If we are not, then there is no point, because none of the data in dev environments can be promoted by definition
|
|
1659
|
+
restate_all_snapshots = (
|
|
1660
|
+
expanded_restate_models is not None
|
|
1661
|
+
and not is_dev
|
|
1662
|
+
and self.config.virtual_environment_mode.is_full
|
|
1663
|
+
)
|
|
1664
|
+
|
|
1647
1665
|
return self.PLAN_BUILDER_TYPE(
|
|
1648
1666
|
context_diff=context_diff,
|
|
1649
1667
|
start=start,
|
|
@@ -1651,6 +1669,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1651
1669
|
execution_time=execution_time,
|
|
1652
1670
|
apply=self.apply,
|
|
1653
1671
|
restate_models=expanded_restate_models,
|
|
1672
|
+
restate_all_snapshots=restate_all_snapshots,
|
|
1654
1673
|
backfill_models=backfill_models,
|
|
1655
1674
|
no_gaps=no_gaps,
|
|
1656
1675
|
skip_backfill=skip_backfill,
|
sqlmesh/core/plan/builder.py
CHANGED
|
@@ -65,6 +65,9 @@ class PlanBuilder:
|
|
|
65
65
|
restate_models: A list of models for which the data should be restated for the time range
|
|
66
66
|
specified in this plan. Note: models defined outside SQLMesh (external) won't be a part
|
|
67
67
|
of the restatement.
|
|
68
|
+
restate_all_snapshots: If restatements are present, this flag indicates whether or not the intervals
|
|
69
|
+
being restated should be cleared from state for other versions of this model (typically, versions that are present in other environments).
|
|
70
|
+
If set to None, the default behaviour is to not clear anything unless the target environment is prod.
|
|
68
71
|
backfill_models: A list of fully qualified model names for which the data should be backfilled as part of this plan.
|
|
69
72
|
no_gaps: Whether to ensure that new snapshots for nodes that are already a
|
|
70
73
|
part of the target environment have no data gaps when compared against previous
|
|
@@ -103,6 +106,7 @@ class PlanBuilder:
|
|
|
103
106
|
execution_time: t.Optional[TimeLike] = None,
|
|
104
107
|
apply: t.Optional[t.Callable[[Plan], None]] = None,
|
|
105
108
|
restate_models: t.Optional[t.Iterable[str]] = None,
|
|
109
|
+
restate_all_snapshots: bool = False,
|
|
106
110
|
backfill_models: t.Optional[t.Iterable[str]] = None,
|
|
107
111
|
no_gaps: bool = False,
|
|
108
112
|
skip_backfill: bool = False,
|
|
@@ -154,6 +158,7 @@ class PlanBuilder:
|
|
|
154
158
|
self._auto_categorization_enabled = auto_categorization_enabled
|
|
155
159
|
self._include_unmodified = include_unmodified
|
|
156
160
|
self._restate_models = set(restate_models) if restate_models is not None else None
|
|
161
|
+
self._restate_all_snapshots = restate_all_snapshots
|
|
157
162
|
self._effective_from = effective_from
|
|
158
163
|
|
|
159
164
|
# note: this deliberately doesnt default to now() here.
|
|
@@ -277,7 +282,6 @@ class PlanBuilder:
|
|
|
277
282
|
if self._latest_plan:
|
|
278
283
|
return self._latest_plan
|
|
279
284
|
|
|
280
|
-
self._ensure_no_new_snapshots_with_restatements()
|
|
281
285
|
self._ensure_new_env_with_changes()
|
|
282
286
|
self._ensure_valid_date_range()
|
|
283
287
|
self._ensure_no_broken_references()
|
|
@@ -340,6 +344,7 @@ class PlanBuilder:
|
|
|
340
344
|
deployability_index=deployability_index,
|
|
341
345
|
selected_models_to_restate=self._restate_models,
|
|
342
346
|
restatements=restatements,
|
|
347
|
+
restate_all_snapshots=self._restate_all_snapshots,
|
|
343
348
|
start_override_per_model=self._start_override_per_model,
|
|
344
349
|
end_override_per_model=end_override_per_model,
|
|
345
350
|
selected_models_to_backfill=self._backfill_models,
|
|
@@ -859,15 +864,6 @@ class PlanBuilder:
|
|
|
859
864
|
f"""Removed {broken_references_msg} are referenced in '{snapshot.name}'. Please remove broken references before proceeding."""
|
|
860
865
|
)
|
|
861
866
|
|
|
862
|
-
def _ensure_no_new_snapshots_with_restatements(self) -> None:
|
|
863
|
-
if self._restate_models is not None and (
|
|
864
|
-
self._context_diff.new_snapshots or self._context_diff.modified_snapshots
|
|
865
|
-
):
|
|
866
|
-
raise PlanError(
|
|
867
|
-
"Model changes and restatements can't be a part of the same plan. "
|
|
868
|
-
"Revert or apply changes before proceeding with restatements."
|
|
869
|
-
)
|
|
870
|
-
|
|
871
867
|
def _ensure_new_env_with_changes(self) -> None:
|
|
872
868
|
if (
|
|
873
869
|
self._is_dev
|
sqlmesh/core/plan/definition.py
CHANGED
|
@@ -67,6 +67,8 @@ class Plan(PydanticModel, frozen=True):
|
|
|
67
67
|
Note that dev previews are also considered restatements, so :selected_models_to_restate can be empty
|
|
68
68
|
while :restatements is still populated with dev previews
|
|
69
69
|
"""
|
|
70
|
+
restate_all_snapshots: bool
|
|
71
|
+
"""Whether or not to clear intervals from state for other versions of the models listed in :restatements"""
|
|
70
72
|
|
|
71
73
|
start_override_per_model: t.Optional[t.Dict[str, datetime]]
|
|
72
74
|
end_override_per_model: t.Optional[t.Dict[str, datetime]]
|
|
@@ -268,6 +270,7 @@ class Plan(PydanticModel, frozen=True):
|
|
|
268
270
|
skip_backfill=self.skip_backfill,
|
|
269
271
|
empty_backfill=self.empty_backfill,
|
|
270
272
|
restatements={s.name: i for s, i in self.restatements.items()},
|
|
273
|
+
restate_all_snapshots=self.restate_all_snapshots,
|
|
271
274
|
is_dev=self.is_dev,
|
|
272
275
|
allow_destructive_models=self.allow_destructive_models,
|
|
273
276
|
allow_additive_models=self.allow_additive_models,
|
|
@@ -312,6 +315,7 @@ class EvaluatablePlan(PydanticModel):
|
|
|
312
315
|
skip_backfill: bool
|
|
313
316
|
empty_backfill: bool
|
|
314
317
|
restatements: t.Dict[str, Interval]
|
|
318
|
+
restate_all_snapshots: bool
|
|
315
319
|
is_dev: bool
|
|
316
320
|
allow_destructive_models: t.Set[str]
|
|
317
321
|
allow_additive_models: t.Set[str]
|
sqlmesh/core/plan/stages.py
CHANGED
|
@@ -14,6 +14,7 @@ from sqlmesh.core.snapshot.definition import (
|
|
|
14
14
|
SnapshotId,
|
|
15
15
|
snapshots_to_dag,
|
|
16
16
|
)
|
|
17
|
+
from sqlmesh.utils.errors import PlanError
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass
|
|
@@ -461,13 +462,18 @@ class PlanStagesBuilder:
|
|
|
461
462
|
def _get_restatement_stage(
|
|
462
463
|
self, plan: EvaluatablePlan, snapshots_by_name: t.Dict[str, Snapshot]
|
|
463
464
|
) -> t.Optional[RestatementStage]:
|
|
464
|
-
if
|
|
465
|
-
|
|
466
|
-
|
|
465
|
+
if plan.restate_all_snapshots:
|
|
466
|
+
if plan.is_dev:
|
|
467
|
+
raise PlanError(
|
|
468
|
+
"Clearing intervals from state across dev model versions is only valid for prod plans"
|
|
469
|
+
)
|
|
467
470
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
+
if plan.restatements:
|
|
472
|
+
return RestatementStage(
|
|
473
|
+
all_snapshots=snapshots_by_name,
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
return None
|
|
471
477
|
|
|
472
478
|
def _get_physical_layer_update_stage(
|
|
473
479
|
self,
|
|
@@ -746,11 +746,15 @@ class SnapshotEvaluator:
|
|
|
746
746
|
adapter.execute(model.render_pre_statements(**render_statements_kwargs))
|
|
747
747
|
|
|
748
748
|
if not target_table_exists or (model.is_seed and not snapshot.intervals):
|
|
749
|
-
|
|
749
|
+
# Only create the empty table if the columns were provided explicitly by the user
|
|
750
|
+
should_create_empty_table = (
|
|
750
751
|
model.kind.is_materialized
|
|
751
752
|
and model.columns_to_types_
|
|
752
753
|
and columns_to_types_all_known(model.columns_to_types_)
|
|
753
754
|
)
|
|
755
|
+
if not should_create_empty_table:
|
|
756
|
+
# Or if the model is self-referential and its query is fully annotated with types
|
|
757
|
+
should_create_empty_table = model.depends_on_self and model.annotated
|
|
754
758
|
if self._can_clone(snapshot, deployability_index):
|
|
755
759
|
self._clone_snapshot_in_dev(
|
|
756
760
|
snapshot=snapshot,
|
|
@@ -763,7 +767,7 @@ class SnapshotEvaluator:
|
|
|
763
767
|
)
|
|
764
768
|
runtime_stage = RuntimeStage.EVALUATING
|
|
765
769
|
target_table_exists = True
|
|
766
|
-
elif
|
|
770
|
+
elif should_create_empty_table or model.is_seed or model.kind.is_scd_type_2:
|
|
767
771
|
self._execute_create(
|
|
768
772
|
snapshot=snapshot,
|
|
769
773
|
table_name=target_table_name,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
sqlmesh/__init__.py,sha256=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
|
|
2
|
-
sqlmesh/_version.py,sha256=
|
|
2
|
+
sqlmesh/_version.py,sha256=gcGONnIcxilCZ4d_C8R95DfiO4eV7bcVx6lyptEjD7Y,721
|
|
3
3
|
sqlmesh/magics.py,sha256=xLh3u4eqpVrKRVN5KF3X84RPRqjygAB9AJP1TXwH8hg,42086
|
|
4
4
|
sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -13,7 +13,7 @@ sqlmesh/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
13
13
|
sqlmesh/core/_typing.py,sha256=e1f7xO2aZCy38M_3VoDy-XI3shyd99-IFctgIFSgXWM,497
|
|
14
14
|
sqlmesh/core/console.py,sha256=0LGXUw7wFGeX-PhsKUIscE1d8mMtoqgPe4WzMiiqw1g,172752
|
|
15
15
|
sqlmesh/core/constants.py,sha256=y92qUS6s5upGr1Kvbf9KXJticNmehBxSM1kzbwSXFAE,2664
|
|
16
|
-
sqlmesh/core/context.py,sha256=
|
|
16
|
+
sqlmesh/core/context.py,sha256=uU9GGzXETS28Sjr-_8gNskshgO-KbTp-Th4Tf4FdQI4,130553
|
|
17
17
|
sqlmesh/core/context_diff.py,sha256=mxkJu0IthFMOlaQ_kcq5C09mlgkq2RQb-pG2rd-x_nA,21648
|
|
18
18
|
sqlmesh/core/dialect.py,sha256=CnKcPj6BnREfu9Zn1OyS7hZ3ktnaX03ygOg91nADlTU,53029
|
|
19
19
|
sqlmesh/core/environment.py,sha256=Kgs_gUEUI072mh0JJFWNRynrCxp1TzRHZhX_NWJRfXc,13142
|
|
@@ -94,17 +94,17 @@ sqlmesh/core/model/meta.py,sha256=a68bnvc-qCCRLo-KCqc1JTrI9faDxsgrR4-P9jeZB0w,20
|
|
|
94
94
|
sqlmesh/core/model/schema.py,sha256=_HMYfzK9wWXh7_CQDIIGnuQUD4aiX3o5D2cRp2sERzc,3387
|
|
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=
|
|
97
|
+
sqlmesh/core/plan/builder.py,sha256=enW5o_PaWYZ0YRT7UMPy-mk5lqkwUgy7kndvegbTTA0,43679
|
|
98
98
|
sqlmesh/core/plan/common.py,sha256=V5mBYa_iQEB-fe9eqQQdMO2ow8cDVXRtnowUucQi9Mg,10453
|
|
99
|
-
sqlmesh/core/plan/definition.py,sha256=
|
|
99
|
+
sqlmesh/core/plan/definition.py,sha256=YPpp7ABu77UznIHjhcPiDi7vxLyhj4II9CED_cQ19g4,15225
|
|
100
100
|
sqlmesh/core/plan/evaluator.py,sha256=lJe3cwSICGiJ3KdGxvfpPfkaWzoJg49LAAjawz5QYoU,21062
|
|
101
101
|
sqlmesh/core/plan/explainer.py,sha256=UITln7f4vxf6-nx7mV_IBbtIZ4f8ob4TyooqZMB9Pqg,15442
|
|
102
|
-
sqlmesh/core/plan/stages.py,sha256=
|
|
102
|
+
sqlmesh/core/plan/stages.py,sha256=ZRwJqf1XM7Yep9qzynYPpX9XzhaL4ZkxxPlLhcuKoIE,27476
|
|
103
103
|
sqlmesh/core/snapshot/__init__.py,sha256=NUhvP-glftOWwxONK79Bud93yNQJv8ApBUjkV35RhMY,1465
|
|
104
104
|
sqlmesh/core/snapshot/cache.py,sha256=bgqCR2hyf6r2A_8QP1EnXFK25gDX37-Zg0YeMuETWxg,3934
|
|
105
105
|
sqlmesh/core/snapshot/categorizer.py,sha256=iNBEqK2KIyTAYURlB9KLfyKCpXN7vjxSqA7QjFa7e5c,2418
|
|
106
106
|
sqlmesh/core/snapshot/definition.py,sha256=2Pob60pngLy70C5HWbb_tE7wkgsUddZdOZ4HNxJq0sk,95140
|
|
107
|
-
sqlmesh/core/snapshot/evaluator.py,sha256=
|
|
107
|
+
sqlmesh/core/snapshot/evaluator.py,sha256=sSHRnkYoW8jhPiKmmckTl8eo1FiG0jnLDfFVvSpyalI,111886
|
|
108
108
|
sqlmesh/core/snapshot/execution_tracker.py,sha256=Ss1oYgH28Fy1mQ4HriX-luE9MG0eLdecrE1SssUveQI,3651
|
|
109
109
|
sqlmesh/core/state_sync/__init__.py,sha256=B60xj-_Xk-4jas3UphLvwkuf04G-9AyGckcblXE0aRg,869
|
|
110
110
|
sqlmesh/core/state_sync/base.py,sha256=1Q_E8yixUg75PxfaVKOfWQote83ZXwOGN0r9BPiRVpE,19241
|
|
@@ -233,12 +233,12 @@ sqlmesh/utils/pydantic.py,sha256=o_NsXbIpDqNpUA1Uc5xF0ZzoXQYYB0DfHwdRxBwXPNk,120
|
|
|
233
233
|
sqlmesh/utils/rich.py,sha256=cwQ5nJ6sgz64xHtoh6_ec7ReV5YpsOGhMtUJnwoRfEI,3549
|
|
234
234
|
sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
|
|
235
235
|
sqlmesh/utils/yaml.py,sha256=KFBd7hsKNRTtRudGR7d410qUYffQv0EWRcDM8hVNNZg,3025
|
|
236
|
-
sqlmesh-0.219.
|
|
236
|
+
sqlmesh-0.219.1.dev2.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
|
|
237
237
|
sqlmesh_dbt/__init__.py,sha256=awYS5y5mz-1NUmx6i5h5NSTJ7tidRl9NC0FAnFWSF6U,350
|
|
238
|
-
sqlmesh_dbt/cli.py,sha256=
|
|
238
|
+
sqlmesh_dbt/cli.py,sha256=z07hDwEU46k3mAbSKVBsvPWnwXOOOFnYw2kQSRJahPA,4524
|
|
239
239
|
sqlmesh_dbt/console.py,sha256=80sCEbrKfR5f3SvxIyI7hw_SuiDiiUwuJYxXbQO2014,830
|
|
240
240
|
sqlmesh_dbt/error.py,sha256=1sPNU6Dik30DR9WTCvGp3ED-pzNmAA3LhP95BXb3ndI,1146
|
|
241
|
-
sqlmesh_dbt/operations.py,sha256=
|
|
241
|
+
sqlmesh_dbt/operations.py,sha256=PrbS2wiWCliMMgMBxnBl6eDltSwUEXcZ3a4Zy6qOaVA,13089
|
|
242
242
|
sqlmesh_dbt/options.py,sha256=noB_qK4uGGi7Erqk1XkkMaFz5aUc6lp44wwn1Nv_LI4,737
|
|
243
243
|
sqlmesh_dbt/selectors.py,sha256=4w8eE0qAgoYC2K8afk3whfju-u3e5muXGwgkfXxQR3Y,5228
|
|
244
244
|
web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -358,8 +358,8 @@ web/server/api/endpoints/models.py,sha256=kwj0s7uve3iZSMfmjkoPVMFMeY1sD0peTeyrWf
|
|
|
358
358
|
web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
|
|
359
359
|
web/server/api/endpoints/plan.py,sha256=bbbY50W_2MsZSTxOHWMKz0tbIm75nsRSlPy8GI2fg9Q,9306
|
|
360
360
|
web/server/api/endpoints/table_diff.py,sha256=8XTwgOh6QBbNy_hTM1JuHgRjbnie-pGPrphiW-FNLjQ,6058
|
|
361
|
-
sqlmesh-0.219.
|
|
362
|
-
sqlmesh-0.219.
|
|
363
|
-
sqlmesh-0.219.
|
|
364
|
-
sqlmesh-0.219.
|
|
365
|
-
sqlmesh-0.219.
|
|
361
|
+
sqlmesh-0.219.1.dev2.dist-info/METADATA,sha256=R34m7XRaIfBEA4SGbU-rkE8uA2QMR59dY2LtbULxm_o,26691
|
|
362
|
+
sqlmesh-0.219.1.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
363
|
+
sqlmesh-0.219.1.dev2.dist-info/entry_points.txt,sha256=sHAf6tQczIM8xZoduN4qaUjV7QEPVUUW_LCT8EDUMv4,155
|
|
364
|
+
sqlmesh-0.219.1.dev2.dist-info/top_level.txt,sha256=RQ-33FPe2IgL0rgossAfJkCRtqslz9b7wFARqiWLC5Q,24
|
|
365
|
+
sqlmesh-0.219.1.dev2.dist-info/RECORD,,
|
sqlmesh_dbt/cli.py
CHANGED
|
@@ -90,7 +90,9 @@ def dbt(
|
|
|
90
90
|
@click.option(
|
|
91
91
|
"-f",
|
|
92
92
|
"--full-refresh",
|
|
93
|
-
|
|
93
|
+
is_flag=True,
|
|
94
|
+
default=False,
|
|
95
|
+
help="If specified, sqlmesh will drop incremental models and fully-recalculate the incremental table from the model definition.",
|
|
94
96
|
)
|
|
95
97
|
@click.option(
|
|
96
98
|
"--env",
|
sqlmesh_dbt/operations.py
CHANGED
|
@@ -11,7 +11,7 @@ if t.TYPE_CHECKING:
|
|
|
11
11
|
from sqlmesh.dbt.project import Project
|
|
12
12
|
from sqlmesh_dbt.console import DbtCliConsole
|
|
13
13
|
from sqlmesh.core.model import Model
|
|
14
|
-
from sqlmesh.core.plan import Plan
|
|
14
|
+
from sqlmesh.core.plan import Plan, PlanBuilder
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -42,8 +42,39 @@ class DbtOperations:
|
|
|
42
42
|
full_refresh: bool = False,
|
|
43
43
|
empty: bool = False,
|
|
44
44
|
) -> Plan:
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
plan_builder = self._plan_builder(
|
|
46
|
+
environment=environment,
|
|
47
|
+
select=select,
|
|
48
|
+
exclude=exclude,
|
|
49
|
+
full_refresh=full_refresh,
|
|
50
|
+
empty=empty,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
plan = plan_builder.build()
|
|
54
|
+
|
|
55
|
+
self.console.plan(
|
|
56
|
+
plan_builder,
|
|
57
|
+
default_catalog=self.context.default_catalog,
|
|
58
|
+
# start doing work immediately (since no_diff is set, there isnt really anything for the user to say yes/no to)
|
|
59
|
+
auto_apply=True,
|
|
60
|
+
# dont output a diff of model changes
|
|
61
|
+
no_diff=True,
|
|
62
|
+
# don't throw up any prompts like "set the effective date" - use defaults
|
|
63
|
+
no_prompts=True,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return plan
|
|
67
|
+
|
|
68
|
+
def _plan_builder(
|
|
69
|
+
self,
|
|
70
|
+
environment: t.Optional[str] = None,
|
|
71
|
+
select: t.Optional[t.List[str]] = None,
|
|
72
|
+
exclude: t.Optional[t.List[str]] = None,
|
|
73
|
+
full_refresh: bool = False,
|
|
74
|
+
empty: bool = False,
|
|
75
|
+
) -> PlanBuilder:
|
|
76
|
+
return self.context.plan_builder(
|
|
77
|
+
**self._plan_builder_options(
|
|
47
78
|
environment=environment,
|
|
48
79
|
select=select,
|
|
49
80
|
exclude=exclude,
|
|
@@ -71,13 +102,15 @@ class DbtOperations:
|
|
|
71
102
|
|
|
72
103
|
return selected_models
|
|
73
104
|
|
|
74
|
-
def
|
|
105
|
+
def _plan_builder_options(
|
|
75
106
|
self,
|
|
76
|
-
|
|
107
|
+
# upstream dbt options
|
|
77
108
|
select: t.Optional[t.List[str]] = None,
|
|
78
109
|
exclude: t.Optional[t.List[str]] = None,
|
|
79
110
|
empty: bool = False,
|
|
80
111
|
full_refresh: bool = False,
|
|
112
|
+
# sqlmesh extra options
|
|
113
|
+
environment: t.Optional[str] = None,
|
|
81
114
|
) -> t.Dict[str, t.Any]:
|
|
82
115
|
import sqlmesh.core.constants as c
|
|
83
116
|
|
|
@@ -130,24 +163,38 @@ class DbtOperations:
|
|
|
130
163
|
# `dbt --empty` adds LIMIT 0 to the queries, resulting in empty tables. In addition, it happily clobbers existing tables regardless of if they are populated.
|
|
131
164
|
# This *partially* lines up with --skip-backfill in SQLMesh, which indicates to not populate tables if they happened to be created/updated as part of this plan.
|
|
132
165
|
# However, if a table already exists and has data in it, there is no change so SQLMesh will not recreate the table and thus it will not be cleared.
|
|
133
|
-
#
|
|
166
|
+
# Currently, SQLMesh has no way to say "restate with empty data", because --restate-model coupled with --skip-backfill ends up being a no-op
|
|
134
167
|
options["skip_backfill"] = True
|
|
135
|
-
|
|
168
|
+
|
|
169
|
+
self.console.log_warning(
|
|
170
|
+
"dbt's `--empty` drops the tables for all selected models and replaces them with empty ones.\n"
|
|
171
|
+
"This can easily result in accidental data loss, so SQLMesh limits this to only new or modified models and leaves the tables for existing unmodified models alone.\n\n"
|
|
172
|
+
"If you were creating empty tables to preview model changes, please consider using `--environment` to preview these changes in an isolated Virtual Data Environment instead.\n\n"
|
|
173
|
+
"Otherwise, if you really do want dbt's `--empty` behaviour of clearing every selected table, please file an issue on GitHub so we can better understand the use-case.\n"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
if full_refresh:
|
|
177
|
+
# --full-refresh is implemented in terms of "add every model as a restatement"
|
|
178
|
+
# however, `--empty` sets skip_backfill=True, which causes the BackfillStage of the plan to be skipped.
|
|
179
|
+
# the re-processing of data intervals happens in the BackfillStage, so if it gets skipped, restatements become a no-op
|
|
180
|
+
raise ValueError("`--full-refresh` alongside `--empty` is not currently supported.")
|
|
136
181
|
|
|
137
182
|
if full_refresh:
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
183
|
+
options.update(
|
|
184
|
+
dict(
|
|
185
|
+
# Add every selected model as a restatement to force them to get repopulated from scratch
|
|
186
|
+
restate_models=list(self.context.models)
|
|
187
|
+
if not select_models
|
|
188
|
+
else select_models,
|
|
189
|
+
# by default in SQLMesh, restatements only operate on what has been committed to state.
|
|
190
|
+
# in order to emulate dbt, we need to use the local filesystem instead, so we override this default
|
|
191
|
+
always_include_local_changes=True,
|
|
192
|
+
)
|
|
193
|
+
)
|
|
141
194
|
|
|
142
195
|
return dict(
|
|
143
196
|
environment=environment,
|
|
144
197
|
select_models=select_models,
|
|
145
|
-
# dont output a diff of model changes
|
|
146
|
-
no_diff=True,
|
|
147
|
-
# don't throw up any prompts like "set the effective date" - use defaults
|
|
148
|
-
no_prompts=True,
|
|
149
|
-
# start doing work immediately (since no_diff is set, there isnt really anything for the user to say yes/no to)
|
|
150
|
-
auto_apply=True,
|
|
151
198
|
**options,
|
|
152
199
|
)
|
|
153
200
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|