sqlmesh 0.213.1.dev1__py3-none-any.whl → 0.227.2.dev4__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/main.py +0 -44
- sqlmesh/cli/project_init.py +11 -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 +17 -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 +81 -3
- sqlmesh/core/constants.py +1 -1
- sqlmesh/core/context.py +69 -26
- sqlmesh/core/dialect.py +3 -0
- sqlmesh/core/engine_adapter/_typing.py +2 -0
- sqlmesh/core/engine_adapter/base.py +322 -22
- 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 +33 -2
- sqlmesh/core/engine_adapter/fabric.py +10 -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 +4 -2
- sqlmesh/core/environment.py +2 -0
- sqlmesh/core/janitor.py +181 -0
- sqlmesh/core/lineage.py +1 -0
- sqlmesh/core/linter/definition.py +13 -13
- sqlmesh/core/linter/rules/builtin.py +29 -0
- sqlmesh/core/macros.py +35 -13
- sqlmesh/core/model/common.py +2 -0
- sqlmesh/core/model/definition.py +82 -28
- sqlmesh/core/model/kind.py +66 -2
- sqlmesh/core/model/meta.py +108 -4
- sqlmesh/core/node.py +101 -1
- sqlmesh/core/plan/builder.py +18 -10
- sqlmesh/core/plan/common.py +199 -2
- sqlmesh/core/plan/definition.py +25 -6
- sqlmesh/core/plan/evaluator.py +75 -113
- sqlmesh/core/plan/explainer.py +90 -8
- sqlmesh/core/plan/stages.py +42 -21
- sqlmesh/core/renderer.py +78 -32
- sqlmesh/core/scheduler.py +102 -22
- sqlmesh/core/selector.py +137 -9
- sqlmesh/core/signal.py +64 -1
- sqlmesh/core/snapshot/__init__.py +2 -0
- sqlmesh/core/snapshot/definition.py +146 -34
- sqlmesh/core/snapshot/evaluator.py +689 -124
- sqlmesh/core/state_sync/__init__.py +0 -1
- sqlmesh/core/state_sync/base.py +55 -33
- sqlmesh/core/state_sync/cache.py +12 -7
- sqlmesh/core/state_sync/common.py +216 -111
- sqlmesh/core/state_sync/db/environment.py +6 -4
- sqlmesh/core/state_sync/db/facade.py +42 -24
- sqlmesh/core/state_sync/db/interval.py +27 -7
- sqlmesh/core/state_sync/db/migrator.py +34 -16
- sqlmesh/core/state_sync/db/snapshot.py +177 -169
- sqlmesh/core/table_diff.py +2 -2
- sqlmesh/core/test/context.py +2 -0
- sqlmesh/core/test/definition.py +14 -9
- sqlmesh/dbt/adapter.py +22 -16
- sqlmesh/dbt/basemodel.py +75 -56
- sqlmesh/dbt/builtin.py +116 -12
- sqlmesh/dbt/column.py +17 -5
- sqlmesh/dbt/common.py +19 -5
- sqlmesh/dbt/context.py +14 -1
- sqlmesh/dbt/loader.py +61 -9
- sqlmesh/dbt/manifest.py +174 -16
- sqlmesh/dbt/model.py +183 -85
- sqlmesh/dbt/package.py +16 -1
- sqlmesh/dbt/profile.py +3 -3
- sqlmesh/dbt/project.py +12 -7
- sqlmesh/dbt/seed.py +6 -1
- sqlmesh/dbt/source.py +13 -1
- sqlmesh/dbt/target.py +25 -6
- sqlmesh/dbt/test.py +36 -5
- sqlmesh/migrations/v0000_baseline.py +95 -0
- sqlmesh/migrations/v0061_mysql_fix_blob_text_type.py +5 -7
- sqlmesh/migrations/v0062_add_model_gateway.py +5 -1
- sqlmesh/migrations/v0063_change_signals.py +5 -3
- sqlmesh/migrations/v0064_join_when_matched_strings.py +5 -3
- sqlmesh/migrations/v0065_add_model_optimize.py +5 -1
- sqlmesh/migrations/v0066_add_auto_restatements.py +8 -3
- sqlmesh/migrations/v0067_add_tsql_date_full_precision.py +5 -1
- sqlmesh/migrations/v0068_include_unrendered_query_in_metadata_hash.py +5 -1
- sqlmesh/migrations/v0069_update_dev_table_suffix.py +5 -3
- sqlmesh/migrations/v0070_include_grains_in_metadata_hash.py +5 -1
- sqlmesh/migrations/v0071_add_dev_version_to_intervals.py +9 -5
- sqlmesh/migrations/v0072_add_environment_statements.py +5 -3
- sqlmesh/migrations/v0073_remove_symbolic_disable_restatement.py +5 -3
- sqlmesh/migrations/v0074_add_partition_by_time_column_property.py +5 -1
- sqlmesh/migrations/v0075_remove_validate_query.py +5 -3
- sqlmesh/migrations/v0076_add_cron_tz.py +5 -1
- sqlmesh/migrations/v0077_fix_column_type_hash_calculation.py +5 -1
- sqlmesh/migrations/v0078_warn_if_non_migratable_python_env.py +5 -3
- sqlmesh/migrations/v0079_add_gateway_managed_property.py +10 -5
- sqlmesh/migrations/v0080_add_batch_size_to_scd_type_2_models.py +5 -1
- sqlmesh/migrations/v0081_update_partitioned_by.py +5 -3
- sqlmesh/migrations/v0082_warn_if_incorrectly_duplicated_statements.py +5 -3
- sqlmesh/migrations/v0083_use_sql_for_scd_time_data_type_data_hash.py +5 -1
- sqlmesh/migrations/v0084_normalize_quote_when_matched_and_merge_filter.py +5 -1
- sqlmesh/migrations/v0085_deterministic_repr.py +5 -3
- sqlmesh/migrations/v0086_check_deterministic_bug.py +5 -3
- sqlmesh/migrations/v0087_normalize_blueprint_variables.py +5 -3
- sqlmesh/migrations/v0088_warn_about_variable_python_env_diffs.py +5 -3
- sqlmesh/migrations/v0089_add_virtual_environment_mode.py +5 -1
- sqlmesh/migrations/v0090_add_forward_only_column.py +9 -5
- sqlmesh/migrations/v0091_on_additive_change.py +5 -1
- sqlmesh/migrations/v0092_warn_about_dbt_data_type_diff.py +5 -3
- sqlmesh/migrations/v0093_use_raw_sql_in_fingerprint.py +5 -1
- sqlmesh/migrations/v0094_add_dev_version_and_fingerprint_columns.py +123 -0
- sqlmesh/migrations/v0095_warn_about_dbt_raw_sql_diff.py +49 -0
- sqlmesh/migrations/v0096_remove_plan_dags_table.py +13 -0
- sqlmesh/migrations/v0097_add_dbt_name_in_node.py +9 -0
- sqlmesh/migrations/{v0060_move_audits_to_model.py → v0098_add_dbt_node_info_in_node.py} +33 -16
- 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/connection_pool.py +2 -1
- sqlmesh/utils/dag.py +65 -10
- sqlmesh/utils/date.py +8 -1
- sqlmesh/utils/errors.py +8 -0
- sqlmesh/utils/jinja.py +54 -4
- sqlmesh/utils/pydantic.py +6 -6
- sqlmesh/utils/windows.py +13 -3
- {sqlmesh-0.213.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/METADATA +7 -10
- sqlmesh-0.227.2.dev4.dist-info/RECORD +370 -0
- 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
- sqlmesh/integrations/llm.py +0 -56
- sqlmesh/migrations/v0001_init.py +0 -60
- sqlmesh/migrations/v0002_remove_identify.py +0 -5
- sqlmesh/migrations/v0003_move_batch_size.py +0 -34
- sqlmesh/migrations/v0004_environmnent_add_finalized_at.py +0 -23
- sqlmesh/migrations/v0005_create_seed_table.py +0 -24
- sqlmesh/migrations/v0006_change_seed_hash.py +0 -5
- sqlmesh/migrations/v0007_env_table_info_to_kind.py +0 -99
- sqlmesh/migrations/v0008_create_intervals_table.py +0 -38
- sqlmesh/migrations/v0009_remove_pre_post_hooks.py +0 -62
- sqlmesh/migrations/v0010_seed_hash_batch_size.py +0 -5
- sqlmesh/migrations/v0011_add_model_kind_name.py +0 -63
- sqlmesh/migrations/v0012_update_jinja_expressions.py +0 -86
- sqlmesh/migrations/v0013_serde_using_model_dialects.py +0 -87
- sqlmesh/migrations/v0014_fix_dev_intervals.py +0 -14
- sqlmesh/migrations/v0015_environment_add_promoted_snapshot_ids.py +0 -26
- sqlmesh/migrations/v0016_fix_windows_path.py +0 -59
- sqlmesh/migrations/v0017_fix_windows_seed_path.py +0 -55
- sqlmesh/migrations/v0018_rename_snapshot_model_to_node.py +0 -53
- sqlmesh/migrations/v0019_add_env_suffix_target.py +0 -28
- sqlmesh/migrations/v0020_remove_redundant_attributes_from_dbt_models.py +0 -80
- sqlmesh/migrations/v0021_fix_table_properties.py +0 -62
- sqlmesh/migrations/v0022_move_project_to_model.py +0 -54
- sqlmesh/migrations/v0023_fix_added_models_with_forward_only_parents.py +0 -65
- sqlmesh/migrations/v0024_replace_model_kind_name_enum_with_value.py +0 -55
- sqlmesh/migrations/v0025_fix_intervals_and_missing_change_category.py +0 -117
- sqlmesh/migrations/v0026_remove_dialect_from_seed.py +0 -55
- sqlmesh/migrations/v0027_minute_interval_to_five.py +0 -57
- sqlmesh/migrations/v0028_add_plan_dags_table.py +0 -29
- sqlmesh/migrations/v0029_generate_schema_types_using_dialect.py +0 -69
- sqlmesh/migrations/v0030_update_unrestorable_snapshots.py +0 -65
- sqlmesh/migrations/v0031_remove_dbt_target_fields.py +0 -65
- sqlmesh/migrations/v0032_add_sqlmesh_version.py +0 -25
- sqlmesh/migrations/v0033_mysql_fix_blob_text_type.py +0 -45
- sqlmesh/migrations/v0034_add_default_catalog.py +0 -367
- sqlmesh/migrations/v0035_add_catalog_name_override.py +0 -22
- sqlmesh/migrations/v0036_delete_plan_dags_bug_fix.py +0 -14
- sqlmesh/migrations/v0037_remove_dbt_is_incremental_macro.py +0 -61
- sqlmesh/migrations/v0038_add_expiration_ts_to_snapshot.py +0 -73
- sqlmesh/migrations/v0039_include_environment_in_plan_dag_spec.py +0 -68
- sqlmesh/migrations/v0040_add_previous_finalized_snapshots.py +0 -26
- sqlmesh/migrations/v0041_remove_hash_raw_query_attribute.py +0 -59
- sqlmesh/migrations/v0042_trim_indirect_versions.py +0 -66
- sqlmesh/migrations/v0043_fix_remove_obsolete_attributes_in_plan_dags.py +0 -61
- sqlmesh/migrations/v0044_quote_identifiers_in_model_attributes.py +0 -5
- sqlmesh/migrations/v0045_move_gateway_variable.py +0 -70
- sqlmesh/migrations/v0046_add_batch_concurrency.py +0 -8
- sqlmesh/migrations/v0047_change_scd_string_to_column.py +0 -5
- sqlmesh/migrations/v0048_drop_indirect_versions.py +0 -59
- sqlmesh/migrations/v0049_replace_identifier_with_version_in_seeds_table.py +0 -57
- sqlmesh/migrations/v0050_drop_seeds_table.py +0 -11
- sqlmesh/migrations/v0051_rename_column_descriptions.py +0 -65
- sqlmesh/migrations/v0052_add_normalize_name_in_environment_naming_info.py +0 -28
- sqlmesh/migrations/v0053_custom_model_kind_extra_attributes.py +0 -5
- sqlmesh/migrations/v0054_fix_trailing_comments.py +0 -5
- sqlmesh/migrations/v0055_add_updated_ts_unpaused_ts_ttl_ms_unrestorable_to_snapshot.py +0 -132
- sqlmesh/migrations/v0056_restore_table_indexes.py +0 -118
- sqlmesh/migrations/v0057_add_table_format.py +0 -5
- sqlmesh/migrations/v0058_add_requirements.py +0 -26
- sqlmesh/migrations/v0059_add_physical_version.py +0 -5
- sqlmesh-0.213.1.dev1.dist-info/RECORD +0 -421
- web/client/dist/assets/Lineage-D0Hgdz2v.js +0 -1
- web/client/dist/assets/context-DgX0fp2E.js +0 -68
- {sqlmesh-0.213.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/WHEEL +0 -0
- {sqlmesh-0.213.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.213.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.213.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/top_level.txt +0 -0
|
@@ -22,19 +22,19 @@ import typing as t
|
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
from datetime import datetime
|
|
24
24
|
|
|
25
|
-
from sqlglot import exp
|
|
26
25
|
|
|
27
26
|
from sqlmesh.core.console import Console, get_console
|
|
28
27
|
from sqlmesh.core.engine_adapter import EngineAdapter
|
|
29
28
|
from sqlmesh.core.environment import Environment, EnvironmentStatements, EnvironmentSummary
|
|
30
29
|
from sqlmesh.core.snapshot import (
|
|
31
30
|
Snapshot,
|
|
31
|
+
SnapshotIdAndVersion,
|
|
32
32
|
SnapshotId,
|
|
33
33
|
SnapshotIdLike,
|
|
34
|
+
SnapshotIdAndVersionLike,
|
|
34
35
|
SnapshotInfoLike,
|
|
35
36
|
SnapshotIntervals,
|
|
36
37
|
SnapshotNameVersion,
|
|
37
|
-
SnapshotTableCleanupTask,
|
|
38
38
|
SnapshotTableInfo,
|
|
39
39
|
start_date,
|
|
40
40
|
)
|
|
@@ -42,7 +42,6 @@ from sqlmesh.core.snapshot.definition import (
|
|
|
42
42
|
Interval,
|
|
43
43
|
)
|
|
44
44
|
from sqlmesh.core.state_sync.base import (
|
|
45
|
-
PromotionResult,
|
|
46
45
|
StateSync,
|
|
47
46
|
Versions,
|
|
48
47
|
)
|
|
@@ -54,6 +53,9 @@ from sqlmesh.core.state_sync.common import (
|
|
|
54
53
|
StateStream,
|
|
55
54
|
chunk_iterable,
|
|
56
55
|
EnvironmentWithStatements,
|
|
56
|
+
ExpiredSnapshotBatch,
|
|
57
|
+
PromotionResult,
|
|
58
|
+
ExpiredBatchRange,
|
|
57
59
|
)
|
|
58
60
|
from sqlmesh.core.state_sync.db.interval import IntervalState
|
|
59
61
|
from sqlmesh.core.state_sync.db.environment import EnvironmentState
|
|
@@ -89,7 +91,6 @@ class EngineAdapterStateSync(StateSync):
|
|
|
89
91
|
console: t.Optional[Console] = None,
|
|
90
92
|
cache_dir: Path = Path(),
|
|
91
93
|
):
|
|
92
|
-
self.plan_dags_table = exp.table_("_plan_dags", db=schema)
|
|
93
94
|
self.interval_state = IntervalState(engine_adapter, schema=schema)
|
|
94
95
|
self.environment_state = EnvironmentState(engine_adapter, schema=schema)
|
|
95
96
|
self.snapshot_state = SnapshotState(engine_adapter, schema=schema, cache_dir=cache_dir)
|
|
@@ -100,7 +101,6 @@ class EngineAdapterStateSync(StateSync):
|
|
|
100
101
|
snapshot_state=self.snapshot_state,
|
|
101
102
|
environment_state=self.environment_state,
|
|
102
103
|
interval_state=self.interval_state,
|
|
103
|
-
plan_dags_table=self.plan_dags_table,
|
|
104
104
|
console=console,
|
|
105
105
|
)
|
|
106
106
|
# Make sure that if an empty string is provided that we treat it as None
|
|
@@ -262,10 +262,18 @@ class EngineAdapterStateSync(StateSync):
|
|
|
262
262
|
self.environment_state.invalidate_environment(name, protect_prod)
|
|
263
263
|
|
|
264
264
|
def get_expired_snapshots(
|
|
265
|
-
self,
|
|
266
|
-
|
|
265
|
+
self,
|
|
266
|
+
*,
|
|
267
|
+
batch_range: ExpiredBatchRange,
|
|
268
|
+
current_ts: t.Optional[int] = None,
|
|
269
|
+
ignore_ttl: bool = False,
|
|
270
|
+
) -> t.Optional[ExpiredSnapshotBatch]:
|
|
271
|
+
current_ts = current_ts or now_timestamp()
|
|
267
272
|
return self.snapshot_state.get_expired_snapshots(
|
|
268
|
-
self.environment_state.get_environments(),
|
|
273
|
+
environments=self.environment_state.get_environments(),
|
|
274
|
+
current_ts=current_ts,
|
|
275
|
+
ignore_ttl=ignore_ttl,
|
|
276
|
+
batch_range=batch_range,
|
|
269
277
|
)
|
|
270
278
|
|
|
271
279
|
def get_expired_environments(self, current_ts: int) -> t.List[EnvironmentSummary]:
|
|
@@ -273,17 +281,19 @@ class EngineAdapterStateSync(StateSync):
|
|
|
273
281
|
|
|
274
282
|
@transactional()
|
|
275
283
|
def delete_expired_snapshots(
|
|
276
|
-
self,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
284
|
+
self,
|
|
285
|
+
batch_range: ExpiredBatchRange,
|
|
286
|
+
ignore_ttl: bool = False,
|
|
287
|
+
current_ts: t.Optional[int] = None,
|
|
288
|
+
) -> None:
|
|
289
|
+
batch = self.get_expired_snapshots(
|
|
290
|
+
ignore_ttl=ignore_ttl,
|
|
291
|
+
current_ts=current_ts,
|
|
292
|
+
batch_range=batch_range,
|
|
281
293
|
)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return cleanup_targets
|
|
294
|
+
if batch and batch.expired_snapshot_ids:
|
|
295
|
+
self.snapshot_state.delete_snapshots(batch.expired_snapshot_ids)
|
|
296
|
+
self.interval_state.cleanup_intervals(batch.cleanup_tasks, batch.expired_snapshot_ids)
|
|
287
297
|
|
|
288
298
|
@transactional()
|
|
289
299
|
def delete_expired_environments(
|
|
@@ -309,7 +319,6 @@ class EngineAdapterStateSync(StateSync):
|
|
|
309
319
|
self.environment_state.environments_table,
|
|
310
320
|
self.environment_state.environment_statements_table,
|
|
311
321
|
self.interval_state.intervals_table,
|
|
312
|
-
self.plan_dags_table,
|
|
313
322
|
self.version_state.versions_table,
|
|
314
323
|
):
|
|
315
324
|
self.engine_adapter.drop_table(table)
|
|
@@ -368,6 +377,16 @@ class EngineAdapterStateSync(StateSync):
|
|
|
368
377
|
Snapshot.hydrate_with_intervals_by_version(snapshots.values(), intervals)
|
|
369
378
|
return snapshots
|
|
370
379
|
|
|
380
|
+
def get_snapshots_by_names(
|
|
381
|
+
self,
|
|
382
|
+
snapshot_names: t.Iterable[str],
|
|
383
|
+
current_ts: t.Optional[int] = None,
|
|
384
|
+
exclude_expired: bool = True,
|
|
385
|
+
) -> t.Set[SnapshotIdAndVersion]:
|
|
386
|
+
return self.snapshot_state.get_snapshots_by_names(
|
|
387
|
+
snapshot_names=snapshot_names, current_ts=current_ts, exclude_expired=exclude_expired
|
|
388
|
+
)
|
|
389
|
+
|
|
371
390
|
@transactional()
|
|
372
391
|
def add_interval(
|
|
373
392
|
self,
|
|
@@ -375,8 +394,9 @@ class EngineAdapterStateSync(StateSync):
|
|
|
375
394
|
start: TimeLike,
|
|
376
395
|
end: TimeLike,
|
|
377
396
|
is_dev: bool = False,
|
|
397
|
+
last_altered_ts: t.Optional[int] = None,
|
|
378
398
|
) -> None:
|
|
379
|
-
super().add_interval(snapshot, start, end, is_dev)
|
|
399
|
+
super().add_interval(snapshot, start, end, is_dev, last_altered_ts)
|
|
380
400
|
|
|
381
401
|
@transactional()
|
|
382
402
|
def add_snapshots_intervals(self, snapshots_intervals: t.Sequence[SnapshotIntervals]) -> None:
|
|
@@ -402,7 +422,7 @@ class EngineAdapterStateSync(StateSync):
|
|
|
402
422
|
@transactional()
|
|
403
423
|
def remove_intervals(
|
|
404
424
|
self,
|
|
405
|
-
snapshot_intervals: t.Sequence[t.Tuple[
|
|
425
|
+
snapshot_intervals: t.Sequence[t.Tuple[SnapshotIdAndVersionLike, Interval]],
|
|
406
426
|
remove_shared_versions: bool = False,
|
|
407
427
|
) -> None:
|
|
408
428
|
self.interval_state.remove_intervals(snapshot_intervals, remove_shared_versions)
|
|
@@ -444,14 +464,12 @@ class EngineAdapterStateSync(StateSync):
|
|
|
444
464
|
@transactional()
|
|
445
465
|
def migrate(
|
|
446
466
|
self,
|
|
447
|
-
default_catalog: t.Optional[str],
|
|
448
467
|
skip_backup: bool = False,
|
|
449
468
|
promoted_snapshots_only: bool = True,
|
|
450
469
|
) -> None:
|
|
451
470
|
"""Migrate the state sync to the latest SQLMesh / SQLGlot version."""
|
|
452
471
|
self.migrator.migrate(
|
|
453
|
-
self,
|
|
454
|
-
default_catalog,
|
|
472
|
+
self.schema,
|
|
455
473
|
skip_backup=skip_backup,
|
|
456
474
|
promoted_snapshots_only=promoted_snapshots_only,
|
|
457
475
|
)
|
|
@@ -15,10 +15,10 @@ from sqlmesh.core.state_sync.db.utils import (
|
|
|
15
15
|
from sqlmesh.core.snapshot import (
|
|
16
16
|
SnapshotIntervals,
|
|
17
17
|
SnapshotIdLike,
|
|
18
|
+
SnapshotIdAndVersionLike,
|
|
18
19
|
SnapshotNameVersionLike,
|
|
19
20
|
SnapshotTableCleanupTask,
|
|
20
21
|
SnapshotNameVersion,
|
|
21
|
-
SnapshotInfoLike,
|
|
22
22
|
Snapshot,
|
|
23
23
|
)
|
|
24
24
|
from sqlmesh.core.snapshot.definition import Interval
|
|
@@ -60,6 +60,7 @@ class IntervalState:
|
|
|
60
60
|
"is_removed": exp.DataType.build("boolean"),
|
|
61
61
|
"is_compacted": exp.DataType.build("boolean"),
|
|
62
62
|
"is_pending_restatement": exp.DataType.build("boolean"),
|
|
63
|
+
"last_altered_ts": exp.DataType.build("bigint"),
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
def add_snapshots_intervals(self, snapshots_intervals: t.Sequence[SnapshotIntervals]) -> None:
|
|
@@ -68,11 +69,11 @@ class IntervalState:
|
|
|
68
69
|
|
|
69
70
|
def remove_intervals(
|
|
70
71
|
self,
|
|
71
|
-
snapshot_intervals: t.Sequence[t.Tuple[
|
|
72
|
+
snapshot_intervals: t.Sequence[t.Tuple[SnapshotIdAndVersionLike, Interval]],
|
|
72
73
|
remove_shared_versions: bool = False,
|
|
73
74
|
) -> None:
|
|
74
75
|
intervals_to_remove: t.Sequence[
|
|
75
|
-
t.Tuple[t.Union[
|
|
76
|
+
t.Tuple[t.Union[SnapshotIdAndVersionLike, SnapshotIntervals], Interval]
|
|
76
77
|
] = snapshot_intervals
|
|
77
78
|
if remove_shared_versions:
|
|
78
79
|
name_version_mapping = {s.name_version: interval for s, interval in snapshot_intervals}
|
|
@@ -215,13 +216,23 @@ class IntervalState:
|
|
|
215
216
|
for start_ts, end_ts in snapshot.intervals:
|
|
216
217
|
new_intervals.append(
|
|
217
218
|
_interval_to_df(
|
|
218
|
-
snapshot,
|
|
219
|
+
snapshot,
|
|
220
|
+
start_ts,
|
|
221
|
+
end_ts,
|
|
222
|
+
is_dev=False,
|
|
223
|
+
is_compacted=is_compacted,
|
|
224
|
+
last_altered_ts=snapshot.last_altered_ts,
|
|
219
225
|
)
|
|
220
226
|
)
|
|
221
227
|
for start_ts, end_ts in snapshot.dev_intervals:
|
|
222
228
|
new_intervals.append(
|
|
223
229
|
_interval_to_df(
|
|
224
|
-
snapshot,
|
|
230
|
+
snapshot,
|
|
231
|
+
start_ts,
|
|
232
|
+
end_ts,
|
|
233
|
+
is_dev=True,
|
|
234
|
+
is_compacted=is_compacted,
|
|
235
|
+
last_altered_ts=snapshot.dev_last_altered_ts,
|
|
225
236
|
)
|
|
226
237
|
)
|
|
227
238
|
|
|
@@ -236,6 +247,7 @@ class IntervalState:
|
|
|
236
247
|
is_dev=False,
|
|
237
248
|
is_compacted=is_compacted,
|
|
238
249
|
is_pending_restatement=True,
|
|
250
|
+
last_altered_ts=snapshot.last_altered_ts,
|
|
239
251
|
)
|
|
240
252
|
)
|
|
241
253
|
|
|
@@ -284,6 +296,7 @@ class IntervalState:
|
|
|
284
296
|
is_dev,
|
|
285
297
|
is_removed,
|
|
286
298
|
is_pending_restatement,
|
|
299
|
+
last_altered_ts,
|
|
287
300
|
) in rows:
|
|
288
301
|
interval_ids.add(interval_id)
|
|
289
302
|
merge_key = (name, version, dev_version, identifier)
|
|
@@ -318,8 +331,10 @@ class IntervalState:
|
|
|
318
331
|
else:
|
|
319
332
|
if is_dev:
|
|
320
333
|
intervals[merge_key].add_dev_interval(start, end)
|
|
334
|
+
intervals[merge_key].update_dev_last_altered_ts(last_altered_ts)
|
|
321
335
|
else:
|
|
322
336
|
intervals[merge_key].add_interval(start, end)
|
|
337
|
+
intervals[merge_key].update_last_altered_ts(last_altered_ts)
|
|
323
338
|
# Remove all pending restatement intervals recorded before the current interval has been added
|
|
324
339
|
intervals[
|
|
325
340
|
pending_restatement_interval_merge_key
|
|
@@ -340,6 +355,7 @@ class IntervalState:
|
|
|
340
355
|
"is_dev",
|
|
341
356
|
"is_removed",
|
|
342
357
|
"is_pending_restatement",
|
|
358
|
+
"last_altered_ts",
|
|
343
359
|
)
|
|
344
360
|
.from_(exp.to_table(self.intervals_table).as_("intervals"))
|
|
345
361
|
.order_by(
|
|
@@ -431,7 +447,9 @@ class IntervalState:
|
|
|
431
447
|
|
|
432
448
|
|
|
433
449
|
def _intervals_to_df(
|
|
434
|
-
snapshot_intervals: t.Sequence[
|
|
450
|
+
snapshot_intervals: t.Sequence[
|
|
451
|
+
t.Tuple[t.Union[SnapshotIdAndVersionLike, SnapshotIntervals], Interval]
|
|
452
|
+
],
|
|
435
453
|
is_dev: bool,
|
|
436
454
|
is_removed: bool,
|
|
437
455
|
) -> pd.DataFrame:
|
|
@@ -451,13 +469,14 @@ def _intervals_to_df(
|
|
|
451
469
|
|
|
452
470
|
|
|
453
471
|
def _interval_to_df(
|
|
454
|
-
snapshot: t.Union[
|
|
472
|
+
snapshot: t.Union[SnapshotIdAndVersionLike, SnapshotIntervals],
|
|
455
473
|
start_ts: int,
|
|
456
474
|
end_ts: int,
|
|
457
475
|
is_dev: bool = False,
|
|
458
476
|
is_removed: bool = False,
|
|
459
477
|
is_compacted: bool = False,
|
|
460
478
|
is_pending_restatement: bool = False,
|
|
479
|
+
last_altered_ts: t.Optional[int] = None,
|
|
461
480
|
) -> t.Dict[str, t.Any]:
|
|
462
481
|
return {
|
|
463
482
|
"id": random_id(),
|
|
@@ -472,4 +491,5 @@ def _interval_to_df(
|
|
|
472
491
|
"is_removed": is_removed,
|
|
473
492
|
"is_compacted": is_compacted,
|
|
474
493
|
"is_pending_restatement": is_pending_restatement,
|
|
494
|
+
"last_altered_ts": last_altered_ts,
|
|
475
495
|
}
|
|
@@ -27,8 +27,9 @@ from sqlmesh.core.snapshot.definition import (
|
|
|
27
27
|
)
|
|
28
28
|
from sqlmesh.core.state_sync.base import (
|
|
29
29
|
MIGRATIONS,
|
|
30
|
+
MIN_SCHEMA_VERSION,
|
|
31
|
+
MIN_SQLMESH_VERSION,
|
|
30
32
|
)
|
|
31
|
-
from sqlmesh.core.state_sync.base import StateSync
|
|
32
33
|
from sqlmesh.core.state_sync.db.environment import EnvironmentState
|
|
33
34
|
from sqlmesh.core.state_sync.db.interval import IntervalState
|
|
34
35
|
from sqlmesh.core.state_sync.db.snapshot import SnapshotState
|
|
@@ -41,7 +42,7 @@ from sqlmesh.core.state_sync.db.utils import (
|
|
|
41
42
|
from sqlmesh.utils import major_minor
|
|
42
43
|
from sqlmesh.utils.dag import DAG
|
|
43
44
|
from sqlmesh.utils.date import now_timestamp
|
|
44
|
-
from sqlmesh.utils.errors import SQLMeshError
|
|
45
|
+
from sqlmesh.utils.errors import SQLMeshError, StateMigrationError
|
|
45
46
|
|
|
46
47
|
logger = logging.getLogger(__name__)
|
|
47
48
|
|
|
@@ -61,7 +62,6 @@ class StateMigrator:
|
|
|
61
62
|
snapshot_state: SnapshotState,
|
|
62
63
|
environment_state: EnvironmentState,
|
|
63
64
|
interval_state: IntervalState,
|
|
64
|
-
plan_dags_table: TableName,
|
|
65
65
|
console: t.Optional[Console] = None,
|
|
66
66
|
):
|
|
67
67
|
self.engine_adapter = engine_adapter
|
|
@@ -70,7 +70,6 @@ class StateMigrator:
|
|
|
70
70
|
self.snapshot_state = snapshot_state
|
|
71
71
|
self.environment_state = environment_state
|
|
72
72
|
self.interval_state = interval_state
|
|
73
|
-
self.plan_dags_table = plan_dags_table
|
|
74
73
|
|
|
75
74
|
self._state_tables = [
|
|
76
75
|
self.snapshot_state.snapshots_table,
|
|
@@ -79,15 +78,13 @@ class StateMigrator:
|
|
|
79
78
|
]
|
|
80
79
|
self._optional_state_tables = [
|
|
81
80
|
self.interval_state.intervals_table,
|
|
82
|
-
self.plan_dags_table,
|
|
83
81
|
self.snapshot_state.auto_restatements_table,
|
|
84
82
|
self.environment_state.environment_statements_table,
|
|
85
83
|
]
|
|
86
84
|
|
|
87
85
|
def migrate(
|
|
88
86
|
self,
|
|
89
|
-
|
|
90
|
-
default_catalog: t.Optional[str],
|
|
87
|
+
schema: t.Optional[str],
|
|
91
88
|
skip_backup: bool = False,
|
|
92
89
|
promoted_snapshots_only: bool = True,
|
|
93
90
|
) -> None:
|
|
@@ -96,15 +93,13 @@ class StateMigrator:
|
|
|
96
93
|
migration_start_ts = time.perf_counter()
|
|
97
94
|
|
|
98
95
|
try:
|
|
99
|
-
migrate_rows = self._apply_migrations(
|
|
96
|
+
migrate_rows = self._apply_migrations(schema, skip_backup)
|
|
100
97
|
|
|
101
98
|
if not migrate_rows and major_minor(SQLMESH_VERSION) == versions.minor_sqlmesh_version:
|
|
102
99
|
return
|
|
103
100
|
|
|
104
101
|
if migrate_rows:
|
|
105
102
|
self._migrate_rows(promoted_snapshots_only)
|
|
106
|
-
# Cleanup plan DAGs since we currently don't migrate snapshot records that are in there.
|
|
107
|
-
self.engine_adapter.delete_from(self.plan_dags_table, "TRUE")
|
|
108
103
|
self.version_state.update_versions()
|
|
109
104
|
|
|
110
105
|
analytics.collector.on_migration_end(
|
|
@@ -126,6 +121,8 @@ class StateMigrator:
|
|
|
126
121
|
)
|
|
127
122
|
|
|
128
123
|
self.console.log_migration_status(success=False)
|
|
124
|
+
if isinstance(e, StateMigrationError):
|
|
125
|
+
raise
|
|
129
126
|
raise SQLMeshError("SQLMesh migration failed.") from e
|
|
130
127
|
|
|
131
128
|
self.console.log_migration_status()
|
|
@@ -155,12 +152,21 @@ class StateMigrator:
|
|
|
155
152
|
|
|
156
153
|
def _apply_migrations(
|
|
157
154
|
self,
|
|
158
|
-
|
|
159
|
-
default_catalog: t.Optional[str],
|
|
155
|
+
schema: t.Optional[str],
|
|
160
156
|
skip_backup: bool,
|
|
161
157
|
) -> bool:
|
|
162
158
|
versions = self.version_state.get_versions()
|
|
163
|
-
|
|
159
|
+
first_script_index = 0
|
|
160
|
+
if versions.schema_version and versions.schema_version < MIN_SCHEMA_VERSION:
|
|
161
|
+
raise StateMigrationError(
|
|
162
|
+
"The current state belongs to an old version of SQLMesh that is no longer supported. "
|
|
163
|
+
f"Please upgrade to {MIN_SQLMESH_VERSION} first before upgrading to {SQLMESH_VERSION}."
|
|
164
|
+
)
|
|
165
|
+
elif versions.schema_version > 0:
|
|
166
|
+
# -1 to skip the baseline migration script
|
|
167
|
+
first_script_index = versions.schema_version - (MIN_SCHEMA_VERSION - 1)
|
|
168
|
+
|
|
169
|
+
migrations = MIGRATIONS[first_script_index:]
|
|
164
170
|
should_backup = any(
|
|
165
171
|
[
|
|
166
172
|
migrations,
|
|
@@ -173,9 +179,14 @@ class StateMigrator:
|
|
|
173
179
|
|
|
174
180
|
snapshot_count_before = self.snapshot_state.count() if versions.schema_version else None
|
|
175
181
|
|
|
182
|
+
state_table_exist = any(self.engine_adapter.table_exists(t) for t in self._state_tables)
|
|
183
|
+
|
|
176
184
|
for migration in migrations:
|
|
177
185
|
logger.info(f"Applying migration {migration}")
|
|
178
|
-
migration.
|
|
186
|
+
migration.migrate_schemas(engine_adapter=self.engine_adapter, schema=schema)
|
|
187
|
+
if state_table_exist:
|
|
188
|
+
# No need to run DML for the initial migration since all tables are empty
|
|
189
|
+
migration.migrate_rows(engine_adapter=self.engine_adapter, schema=schema)
|
|
179
190
|
|
|
180
191
|
snapshot_count_after = self.snapshot_state.count()
|
|
181
192
|
|
|
@@ -217,6 +228,7 @@ class StateMigrator:
|
|
|
217
228
|
"updated_ts": updated_ts,
|
|
218
229
|
"unpaused_ts": unpaused_ts,
|
|
219
230
|
"unrestorable": unrestorable,
|
|
231
|
+
"forward_only": forward_only,
|
|
220
232
|
}
|
|
221
233
|
for where in (
|
|
222
234
|
snapshot_id_filter(
|
|
@@ -225,10 +237,16 @@ class StateMigrator:
|
|
|
225
237
|
if snapshots is not None
|
|
226
238
|
else [None]
|
|
227
239
|
)
|
|
228
|
-
for name, identifier, raw_snapshot, updated_ts, unpaused_ts, unrestorable in fetchall(
|
|
240
|
+
for name, identifier, raw_snapshot, updated_ts, unpaused_ts, unrestorable, forward_only in fetchall(
|
|
229
241
|
self.engine_adapter,
|
|
230
242
|
exp.select(
|
|
231
|
-
"name",
|
|
243
|
+
"name",
|
|
244
|
+
"identifier",
|
|
245
|
+
"snapshot",
|
|
246
|
+
"updated_ts",
|
|
247
|
+
"unpaused_ts",
|
|
248
|
+
"unrestorable",
|
|
249
|
+
"forward_only",
|
|
232
250
|
)
|
|
233
251
|
.from_(self.snapshot_state.snapshots_table)
|
|
234
252
|
.where(where)
|