sqlmesh 0.228.1.dev1__py3-none-any.whl → 0.228.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 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.228.1.dev1'
32
- __version_tuple__ = version_tuple = (0, 228, 1, 'dev1')
31
+ __version__ = version = '0.228.1.dev2'
32
+ __version_tuple__ = version_tuple = (0, 228, 1, 'dev2')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -17,6 +17,7 @@ from pydantic_core import from_json
17
17
  from packaging import version
18
18
  from sqlglot import exp
19
19
  from sqlglot.helper import subclasses
20
+ from sqlglot.errors import ParseError
20
21
 
21
22
  from sqlmesh.core import engine_adapter
22
23
  from sqlmesh.core.config.base import BaseConfig
@@ -1890,6 +1891,7 @@ class TrinoConnectionConfig(ConnectionConfig):
1890
1891
 
1891
1892
  # SQLMesh options
1892
1893
  schema_location_mapping: t.Optional[dict[re.Pattern, str]] = None
1894
+ timestamp_mapping: t.Optional[dict[exp.DataType, exp.DataType]] = None
1893
1895
  concurrent_tasks: int = 4
1894
1896
  register_comments: bool = True
1895
1897
  pre_ping: t.Literal[False] = False
@@ -1914,6 +1916,34 @@ class TrinoConnectionConfig(ConnectionConfig):
1914
1916
  )
1915
1917
  return compiled
1916
1918
 
1919
+ @field_validator("timestamp_mapping", mode="before")
1920
+ @classmethod
1921
+ def _validate_timestamp_mapping(
1922
+ cls, value: t.Optional[dict[str, str]]
1923
+ ) -> t.Optional[dict[exp.DataType, exp.DataType]]:
1924
+ if value is None:
1925
+ return value
1926
+
1927
+ result: dict[exp.DataType, exp.DataType] = {}
1928
+ for source_type, target_type in value.items():
1929
+ try:
1930
+ source_datatype = exp.DataType.build(source_type)
1931
+ except ParseError:
1932
+ raise ConfigError(
1933
+ f"Invalid SQL type string in timestamp_mapping: "
1934
+ f"'{source_type}' is not a valid SQL data type."
1935
+ )
1936
+ try:
1937
+ target_datatype = exp.DataType.build(target_type)
1938
+ except ParseError:
1939
+ raise ConfigError(
1940
+ f"Invalid SQL type string in timestamp_mapping: "
1941
+ f"'{target_type}' is not a valid SQL data type."
1942
+ )
1943
+ result[source_datatype] = target_datatype
1944
+
1945
+ return result
1946
+
1917
1947
  @model_validator(mode="after")
1918
1948
  def _root_validator(self) -> Self:
1919
1949
  port = self.port
@@ -2016,7 +2046,10 @@ class TrinoConnectionConfig(ConnectionConfig):
2016
2046
 
2017
2047
  @property
2018
2048
  def _extra_engine_config(self) -> t.Dict[str, t.Any]:
2019
- return {"schema_location_mapping": self.schema_location_mapping}
2049
+ return {
2050
+ "schema_location_mapping": self.schema_location_mapping,
2051
+ "timestamp_mapping": self.timestamp_mapping,
2052
+ }
2020
2053
 
2021
2054
 
2022
2055
  class ClickhouseConnectionConfig(ConnectionConfig):
@@ -74,6 +74,32 @@ class TrinoEngineAdapter(
74
74
  def schema_location_mapping(self) -> t.Optional[t.Dict[re.Pattern, str]]:
75
75
  return self._extra_config.get("schema_location_mapping")
76
76
 
77
+ @property
78
+ def timestamp_mapping(self) -> t.Optional[t.Dict[exp.DataType, exp.DataType]]:
79
+ return self._extra_config.get("timestamp_mapping")
80
+
81
+ def _apply_timestamp_mapping(
82
+ self, columns_to_types: t.Dict[str, exp.DataType]
83
+ ) -> t.Tuple[t.Dict[str, exp.DataType], t.Set[str]]:
84
+ """Apply custom timestamp mapping to column types.
85
+
86
+ Returns:
87
+ A tuple of (mapped_columns_to_types, mapped_column_names) where mapped_column_names
88
+ contains the names of columns that were found in the mapping.
89
+ """
90
+ if not self.timestamp_mapping:
91
+ return columns_to_types, set()
92
+
93
+ result = {}
94
+ mapped_columns: t.Set[str] = set()
95
+ for column, column_type in columns_to_types.items():
96
+ if column_type in self.timestamp_mapping:
97
+ result[column] = self.timestamp_mapping[column_type]
98
+ mapped_columns.add(column)
99
+ else:
100
+ result[column] = column_type
101
+ return result, mapped_columns
102
+
77
103
  @property
78
104
  def catalog_support(self) -> CatalogSupport:
79
105
  return CatalogSupport.FULL_SUPPORT
@@ -117,7 +143,7 @@ class TrinoEngineAdapter(
117
143
  try:
118
144
  yield
119
145
  finally:
120
- self.execute(f"RESET SESSION AUTHORIZATION")
146
+ self.execute("RESET SESSION AUTHORIZATION")
121
147
 
122
148
  def replace_query(
123
149
  self,
@@ -286,8 +312,11 @@ class TrinoEngineAdapter(
286
312
  is_view: bool = False,
287
313
  materialized: bool = False,
288
314
  ) -> exp.Schema:
315
+ target_columns_to_types, mapped_columns = self._apply_timestamp_mapping(
316
+ target_columns_to_types
317
+ )
289
318
  if "delta_lake" in self.get_catalog_type_from_table(table):
290
- target_columns_to_types = self._to_delta_ts(target_columns_to_types)
319
+ target_columns_to_types = self._to_delta_ts(target_columns_to_types, mapped_columns)
291
320
 
292
321
  return super()._build_schema_exp(
293
322
  table, target_columns_to_types, column_descriptions, expressions, is_view
@@ -313,10 +342,15 @@ class TrinoEngineAdapter(
313
342
  source_columns: t.Optional[t.List[str]] = None,
314
343
  **kwargs: t.Any,
315
344
  ) -> None:
345
+ mapped_columns: t.Set[str] = set()
346
+ if target_columns_to_types:
347
+ target_columns_to_types, mapped_columns = self._apply_timestamp_mapping(
348
+ target_columns_to_types
349
+ )
316
350
  if target_columns_to_types and "delta_lake" in self.get_catalog_type_from_table(
317
351
  target_table
318
352
  ):
319
- target_columns_to_types = self._to_delta_ts(target_columns_to_types)
353
+ target_columns_to_types = self._to_delta_ts(target_columns_to_types, mapped_columns)
320
354
 
321
355
  return super()._scd_type_2(
322
356
  target_table,
@@ -346,18 +380,21 @@ class TrinoEngineAdapter(
346
380
  # - `timestamp(3) with time zone` for timezone-aware
347
381
  # https://trino.io/docs/current/connector/delta-lake.html#delta-lake-to-trino-type-mapping
348
382
  def _to_delta_ts(
349
- self, columns_to_types: t.Dict[str, exp.DataType]
383
+ self,
384
+ columns_to_types: t.Dict[str, exp.DataType],
385
+ skip_columns: t.Optional[t.Set[str]] = None,
350
386
  ) -> t.Dict[str, exp.DataType]:
351
387
  ts6 = exp.DataType.build("timestamp(6)")
352
388
  ts3_tz = exp.DataType.build("timestamp(3) with time zone")
389
+ skip = skip_columns or set()
353
390
 
354
391
  delta_columns_to_types = {
355
- k: ts6 if v.is_type(exp.DataType.Type.TIMESTAMP) else v
392
+ k: ts6 if k not in skip and v.is_type(exp.DataType.Type.TIMESTAMP) else v
356
393
  for k, v in columns_to_types.items()
357
394
  }
358
395
 
359
396
  delta_columns_to_types = {
360
- k: ts3_tz if v.is_type(exp.DataType.Type.TIMESTAMPTZ) else v
397
+ k: ts3_tz if k not in skip and v.is_type(exp.DataType.Type.TIMESTAMPTZ) else v
361
398
  for k, v in delta_columns_to_types.items()
362
399
  }
363
400
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.228.1.dev1
3
+ Version: 0.228.1.dev2
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=v_spqQEhcnGaahp1yPvMqUIa6mhH3cs3Bc1CznxvCEA,7965
2
- sqlmesh/_version.py,sha256=G0EnPfaObCiXxYjW9mQvEf7Bpf-ACOLqs4xEIF8Z_hg,721
2
+ sqlmesh/_version.py,sha256=-UbxvaOsHNt41ClgzojQDAjyZAdfbkbOj_p0-3b_vJw,721
3
3
  sqlmesh/magics.py,sha256=7Q1_lXSD_PgYH40Hsx6-OkfSQC3UJZgF043RVFRnw1s,42082
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -42,7 +42,7 @@ sqlmesh/core/config/__init__.py,sha256=tnEakbd8FAgSLYmjzuYAAgHIpJ00lwMKAhD_Cfs2O
42
42
  sqlmesh/core/config/base.py,sha256=t8NQmsgQoZSc-k0dlDiCb8t1jj0AMYdGZ-6se9q_Pks,4898
43
43
  sqlmesh/core/config/categorizer.py,sha256=6vzUoNLjR6GOEb_2mYVz2TwmMv2BfldgHX2u-Le5HZs,1975
44
44
  sqlmesh/core/config/common.py,sha256=9V6PltBAjYeWLOU5dAbqL55BSFfpg8z8t2Op1x_PLhU,6418
45
- sqlmesh/core/config/connection.py,sha256=qynbsjRT_KOI6InKdCIXdqGXExF43EuawQp0NxTHPG4,91168
45
+ sqlmesh/core/config/connection.py,sha256=l2GUpZtCJyVk94JiTcvZbrrH9dpOfZChCwyM6Z20Efs,92425
46
46
  sqlmesh/core/config/dbt.py,sha256=xSQ4NEVWhZj_aRYpyy4MWcRJ8Qa0o28w2ZBLI4bs3_I,468
47
47
  sqlmesh/core/config/format.py,sha256=6CXFbvnor56xbldKE-Vrm9k_ABRoY4v6vgIb3mCihiQ,1355
48
48
  sqlmesh/core/config/gateway.py,sha256=tYngyqwd_4Qr9lhcv2hlvLvb_2pgYYtKu6hdGsTr-4I,1931
@@ -76,7 +76,7 @@ sqlmesh/core/engine_adapter/risingwave.py,sha256=d_1MxpXNONyyLnuELa7bILkJlLquf4j
76
76
  sqlmesh/core/engine_adapter/shared.py,sha256=bM4GJSAR0dU3wCqsTl2SIcy2j_8BGusQvnme99l6wnE,13701
77
77
  sqlmesh/core/engine_adapter/snowflake.py,sha256=6rMuhuhp2K-UH8dVnmiieucfOevxmK8vR3N5-dj4MDA,33453
78
78
  sqlmesh/core/engine_adapter/spark.py,sha256=ZDEg4rx_cvPcLG83PSWu5nkXzChaCbmb7ka2J2ngEEU,23068
79
- sqlmesh/core/engine_adapter/trino.py,sha256=dy5DXCbhPB9nuTDytiNuDXe-wGgxv5b9CjhEVpbQCq4,18180
79
+ sqlmesh/core/engine_adapter/trino.py,sha256=F6Cs0RxbMnk5tOYxp3GdMNhK3nnBrtnU8gldMD3POh0,19731
80
80
  sqlmesh/core/linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  sqlmesh/core/linter/definition.py,sha256=1EOhKdF16jmeqISfcrR-8fzMdgXuxpB7wb3QaepBPeU,5564
82
82
  sqlmesh/core/linter/helpers.py,sha256=cwKXP4sL6azRtNVGbMfJ5_6Hqq5Xx2M2rRLCgH3Y3ag,10743
@@ -238,7 +238,7 @@ sqlmesh/utils/pydantic.py,sha256=-yppkVlw6iSBaSiKjbe7OChxL-u3urOS4-KCjJEgsRU,120
238
238
  sqlmesh/utils/rich.py,sha256=cwQ5nJ6sgz64xHtoh6_ec7ReV5YpsOGhMtUJnwoRfEI,3549
239
239
  sqlmesh/utils/windows.py,sha256=0F9RdpuuCoG5NiEDXvWlAGCiJ-59OjSAmgFF5wW05aY,1133
240
240
  sqlmesh/utils/yaml.py,sha256=KFBd7hsKNRTtRudGR7d410qUYffQv0EWRcDM8hVNNZg,3025
241
- sqlmesh-0.228.1.dev1.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
241
+ sqlmesh-0.228.1.dev2.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
242
242
  sqlmesh_dbt/__init__.py,sha256=awYS5y5mz-1NUmx6i5h5NSTJ7tidRl9NC0FAnFWSF6U,350
243
243
  sqlmesh_dbt/cli.py,sha256=p9foHjAW9ni7BTOJ2loynk47M0Sf43QIJZRggOzF5tc,6351
244
244
  sqlmesh_dbt/console.py,sha256=RwWLYnEZHzn9Xp-e2gbZvkdKbWbBLN146geI84mJitg,1132
@@ -363,8 +363,8 @@ web/server/api/endpoints/models.py,sha256=kwj0s7uve3iZSMfmjkoPVMFMeY1sD0peTeyrWf
363
363
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
364
364
  web/server/api/endpoints/plan.py,sha256=bbbY50W_2MsZSTxOHWMKz0tbIm75nsRSlPy8GI2fg9Q,9306
365
365
  web/server/api/endpoints/table_diff.py,sha256=8XTwgOh6QBbNy_hTM1JuHgRjbnie-pGPrphiW-FNLjQ,6058
366
- sqlmesh-0.228.1.dev1.dist-info/METADATA,sha256=62st3YlLnXg9N1lEeRS4cqt0ctsYq4Qv8LMHbBmq9q8,26685
367
- sqlmesh-0.228.1.dev1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
368
- sqlmesh-0.228.1.dev1.dist-info/entry_points.txt,sha256=sHAf6tQczIM8xZoduN4qaUjV7QEPVUUW_LCT8EDUMv4,155
369
- sqlmesh-0.228.1.dev1.dist-info/top_level.txt,sha256=RQ-33FPe2IgL0rgossAfJkCRtqslz9b7wFARqiWLC5Q,24
370
- sqlmesh-0.228.1.dev1.dist-info/RECORD,,
366
+ sqlmesh-0.228.1.dev2.dist-info/METADATA,sha256=WTvsWqQryymDjFJv6vkk_r_XuidAGuO8X6K5guIFP4A,26685
367
+ sqlmesh-0.228.1.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
368
+ sqlmesh-0.228.1.dev2.dist-info/entry_points.txt,sha256=sHAf6tQczIM8xZoduN4qaUjV7QEPVUUW_LCT8EDUMv4,155
369
+ sqlmesh-0.228.1.dev2.dist-info/top_level.txt,sha256=RQ-33FPe2IgL0rgossAfJkCRtqslz9b7wFARqiWLC5Q,24
370
+ sqlmesh-0.228.1.dev2.dist-info/RECORD,,