|
1 | 1 | import typing as t |
| 2 | +from datetime import datetime, timezone |
2 | 3 |
|
3 | 4 | import pandas as pd # noqa: TID253 |
4 | 5 | import pytest |
|
14 | 15 | from sqlmesh.core.model import load_sql_based_model |
15 | 16 | from sqlmesh.core.model.definition import SqlModel |
16 | 17 | from sqlmesh.core.node import IntervalUnit |
| 18 | +from sqlmesh.utils.date import to_timestamp |
17 | 19 | from sqlmesh.utils.errors import SQLMeshError |
18 | 20 | from sqlmesh.utils import optional_import |
19 | 21 | from tests.core.engine_adapter import to_sql_calls |
@@ -73,6 +75,38 @@ def test_get_data_objects_lowercases_columns( |
73 | 75 | assert data_object.clustering_key == "ID" |
74 | 76 |
|
75 | 77 |
|
| 78 | +def test_get_table_last_modified_ts_multiple_catalogs( |
| 79 | + snowflake_mocked_engine_adapter: SnowflakeEngineAdapter, |
| 80 | +) -> None: |
| 81 | + adapter = snowflake_mocked_engine_adapter |
| 82 | + adapter.cursor.fetchall.side_effect = [ |
| 83 | + [ |
| 84 | + (datetime(2025, 1, 1, tzinfo=timezone.utc),), |
| 85 | + (datetime(2025, 1, 2, tzinfo=timezone.utc),), |
| 86 | + ], |
| 87 | + [(datetime(2025, 1, 3, tzinfo=timezone.utc),)], |
| 88 | + ] |
| 89 | + |
| 90 | + result = adapter.get_table_last_modified_ts( |
| 91 | + [ |
| 92 | + '"ANALYTICS"."STAGING"."ORDERS"', |
| 93 | + '"RAW"."SHOPIFY"."ORDERS"', |
| 94 | + '"ANALYTICS"."STAGING"."CUSTOMERS"', |
| 95 | + ] |
| 96 | + ) |
| 97 | + |
| 98 | + # INFORMATION_SCHEMA only covers the database it belongs to, so each database is queried separately |
| 99 | + assert to_sql_calls(adapter) == [ |
| 100 | + """SELECT LAST_ALTERED FROM "ANALYTICS".INFORMATION_SCHEMA.TABLES WHERE (TABLE_NAME = 'ORDERS' AND TABLE_SCHEMA = 'STAGING') OR (TABLE_NAME = 'CUSTOMERS' AND TABLE_SCHEMA = 'STAGING')""", |
| 101 | + """SELECT LAST_ALTERED FROM "RAW".INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ORDERS' AND TABLE_SCHEMA = 'SHOPIFY'""", |
| 102 | + ] |
| 103 | + assert result == [ |
| 104 | + to_timestamp("2025-01-01"), |
| 105 | + to_timestamp("2025-01-02"), |
| 106 | + to_timestamp("2025-01-03"), |
| 107 | + ] |
| 108 | + |
| 109 | + |
76 | 110 | @pytest.mark.parametrize( |
77 | 111 | "current_warehouse, current_warehouse_exp, configured_warehouse, configured_warehouse_exp, should_change", |
78 | 112 | [ |
@@ -183,6 +217,29 @@ def test_alter_session_parameters_are_not_quoted(make_mocked_engine_adapter: t.C |
183 | 217 | ] |
184 | 218 |
|
185 | 219 |
|
| 220 | +def test_get_table_last_modified_ts_quoted_and_unquoted_catalogs( |
| 221 | + snowflake_mocked_engine_adapter: SnowflakeEngineAdapter, |
| 222 | +) -> None: |
| 223 | + # unquoted raw resolves to the database RAW, quoted "raw" is a different database, |
| 224 | + # so the two must be looked up in two different information schemas |
| 225 | + adapter = snowflake_mocked_engine_adapter |
| 226 | + adapter.cursor.fetchall.side_effect = [ |
| 227 | + [(datetime(2025, 1, 1, tzinfo=timezone.utc),)], |
| 228 | + [(datetime(2025, 1, 2, tzinfo=timezone.utc),)], |
| 229 | + ] |
| 230 | + |
| 231 | + result = adapter.get_table_last_modified_ts(['"raw".shopify.orders', "raw.shopify.customers"]) |
| 232 | + |
| 233 | + assert result == [ |
| 234 | + to_timestamp(datetime(2025, 1, 1, tzinfo=timezone.utc)), |
| 235 | + to_timestamp(datetime(2025, 1, 2, tzinfo=timezone.utc)), |
| 236 | + ] |
| 237 | + assert to_sql_calls(adapter) == [ |
| 238 | + """SELECT LAST_ALTERED FROM "raw".INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'orders' AND TABLE_SCHEMA = 'shopify'""", |
| 239 | + """SELECT LAST_ALTERED FROM raw.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'customers' AND TABLE_SCHEMA = 'shopify'""", |
| 240 | + ] |
| 241 | + |
| 242 | + |
186 | 243 | def test_comments(make_mocked_engine_adapter: t.Callable, mocker: MockerFixture): |
187 | 244 | adapter = make_mocked_engine_adapter(SnowflakeEngineAdapter) |
188 | 245 |
|
|
0 commit comments