|
67 | 67 | SnapshotInfoLike, |
68 | 68 | SnapshotTableInfo, |
69 | 69 | ) |
| 70 | +from sqlmesh.core.state_sync.base import Versions, SCHEMA_VERSION |
70 | 71 | from sqlmesh.utils import CorrelationId |
71 | 72 | from sqlmesh.utils.date import TimeLike, now, to_date, to_datetime, to_timestamp |
72 | 73 | from sqlmesh.utils.errors import NoChangesPlanError, SQLMeshError, PlanError, ConfigError |
@@ -6291,6 +6292,92 @@ def test_destroy(copy_to_temp_path): |
6291 | 6292 | assert not cache_path.exists() |
6292 | 6293 |
|
6293 | 6294 |
|
| 6295 | +@use_terminal_console |
| 6296 | +def test_destroy_with_version_mismatch(copy_to_temp_path): |
| 6297 | + paths = copy_to_temp_path("tests/fixtures/multi_virtual_layer") |
| 6298 | + path = Path(paths[0]) |
| 6299 | + first_db_path = str(path / "db_1.db") |
| 6300 | + second_db_path = str(path / "db_2.db") |
| 6301 | + |
| 6302 | + config = Config( |
| 6303 | + gateways={ |
| 6304 | + "first": GatewayConfig( |
| 6305 | + connection=DuckDBConnectionConfig(database=first_db_path), |
| 6306 | + variables={"overriden_var": "gateway_1"}, |
| 6307 | + ), |
| 6308 | + "second": GatewayConfig( |
| 6309 | + connection=DuckDBConnectionConfig(database=second_db_path), |
| 6310 | + variables={"overriden_var": "gateway_2"}, |
| 6311 | + ), |
| 6312 | + }, |
| 6313 | + model_defaults=ModelDefaultsConfig(dialect="duckdb"), |
| 6314 | + model_naming=NameInferenceConfig(infer_names=True), |
| 6315 | + default_gateway="first", |
| 6316 | + gateway_managed_virtual_layer=True, |
| 6317 | + variables={"overriden_var": "global", "global_one": 88}, |
| 6318 | + ) |
| 6319 | + |
| 6320 | + context = Context(paths=paths, config=config) |
| 6321 | + plan = context.plan_builder().build() |
| 6322 | + assert len(plan.new_snapshots) == 4 |
| 6323 | + context.apply(plan) |
| 6324 | + |
| 6325 | + # Create dev environment with a change |
| 6326 | + model = context.get_model("db_1.first_schema.model_one") |
| 6327 | + context.upsert_model(model.copy(update={"query": model.query.select("'c' AS extra")})) |
| 6328 | + plan = context.plan_builder("dev").build() |
| 6329 | + context.apply(plan) |
| 6330 | + |
| 6331 | + # Mock get_versions to raise an error by bumping the version |
| 6332 | + def mock_get_versions(validate=True): |
| 6333 | + if validate: |
| 6334 | + raise SQLMeshError( |
| 6335 | + f"SQLMesh (local) is using version '{SCHEMA_VERSION}' which is behind '{SCHEMA_VERSION + 1}' (remote). " |
| 6336 | + f"Please upgrade SQLMesh." |
| 6337 | + ) |
| 6338 | + return Versions( |
| 6339 | + schema_version=SCHEMA_VERSION + 1, |
| 6340 | + sqlglot_version="1.0.0", |
| 6341 | + sqlmesh_version="1.0.0", |
| 6342 | + ) |
| 6343 | + |
| 6344 | + # Clearstate sync and patch to return a state sync with mocked get_versions |
| 6345 | + context._state_sync = None |
| 6346 | + original_new_state_sync = context._new_state_sync |
| 6347 | + |
| 6348 | + def patched_new_state_sync(): |
| 6349 | + state_sync = original_new_state_sync() |
| 6350 | + state_sync.get_versions = mock_get_versions |
| 6351 | + return state_sync |
| 6352 | + |
| 6353 | + with patch.object(context, "_new_state_sync", side_effect=patched_new_state_sync): |
| 6354 | + # Ensure accessing state_sync property would fail due to get_versions validation |
| 6355 | + with pytest.raises(SQLMeshError): |
| 6356 | + _ = context.state_sync |
| 6357 | + |
| 6358 | + context._state_sync = None |
| 6359 | + |
| 6360 | + # This should not raise an error even though there is a version mismatch |
| 6361 | + context._destroy() |
| 6362 | + |
| 6363 | + # Verify the state tables have been removed though |
| 6364 | + state_tables = { |
| 6365 | + "_environments", |
| 6366 | + "_snapshots", |
| 6367 | + "_intervals", |
| 6368 | + "_auto_restatements", |
| 6369 | + "_environment_statements", |
| 6370 | + "_intervals", |
| 6371 | + "_plan_dags", |
| 6372 | + "_versions", |
| 6373 | + } |
| 6374 | + for table_name in state_tables: |
| 6375 | + with pytest.raises( |
| 6376 | + Exception, match=f"Catalog Error: Table with name {table_name} does not exist!" |
| 6377 | + ): |
| 6378 | + context.fetchdf(f"SELECT * FROM db_1.sqlmesh.{table_name}") |
| 6379 | + |
| 6380 | + |
6294 | 6381 | @use_terminal_console |
6295 | 6382 | def test_audits_running_on_metadata_changes(tmp_path: Path): |
6296 | 6383 | def setup_senario(model_before: str, model_after: str): |
|
0 commit comments