sqlmesh 0.194.2.dev2__py3-none-any.whl → 0.194.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/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.194.2.dev2'
21
- __version_tuple__ = version_tuple = (0, 194, 2, 'dev2')
20
+ __version__ = version = '0.194.2.dev4'
21
+ __version_tuple__ = version_tuple = (0, 194, 2, 'dev4')
@@ -10,9 +10,22 @@ from sqlmesh.utils.pydantic import field_validator
10
10
 
11
11
 
12
12
  class EnvironmentSuffixTarget(str, Enum):
13
+ # Intended to create virtual environments in their own schemas, with names like "<model_schema_name>__<env name>". The view name is untouched.
14
+ # For example, a model named 'sqlmesh_example.full_model' created in an environment called 'dev'
15
+ # would have its virtual layer view created as 'sqlmesh_example__dev.full_model'
13
16
  SCHEMA = "schema"
17
+
18
+ # Intended to create virtual environments in the same schema as their production counterparts by adjusting the table name.
19
+ # For example, a model named 'sqlmesh_example.full_model' created in an environment called 'dev'
20
+ # would have its virtual layer view created as "sqlmesh_example.full_model__dev"
14
21
  TABLE = "table"
15
22
 
23
+ # Intended to create virtual environments in their own catalogs to preserve the schema and view name of the models
24
+ # For example, a model named 'sqlmesh_example.full_model' created in an environment called 'dev'
25
+ # with a default catalog of "warehouse" would have its virtual layer view created as "warehouse__dev.sqlmesh_example.full_model"
26
+ # note: this only works for engines that can query across catalogs
27
+ CATALOG = "catalog"
28
+
16
29
  @property
17
30
  def is_schema(self) -> bool:
18
31
  return self == EnvironmentSuffixTarget.SCHEMA
@@ -21,6 +34,10 @@ class EnvironmentSuffixTarget(str, Enum):
21
34
  def is_table(self) -> bool:
22
35
  return self == EnvironmentSuffixTarget.TABLE
23
36
 
37
+ @property
38
+ def is_catalog(self) -> bool:
39
+ return self == EnvironmentSuffixTarget.CATALOG
40
+
24
41
  @classproperty
25
42
  def default(cls) -> EnvironmentSuffixTarget:
26
43
  return EnvironmentSuffixTarget.SCHEMA
@@ -242,6 +242,15 @@ class Config(BaseConfig):
242
242
  },
243
243
  )
244
244
 
245
+ if (
246
+ self.environment_suffix_target == EnvironmentSuffixTarget.CATALOG
247
+ and self.environment_catalog_mapping
248
+ ):
249
+ raise ConfigError(
250
+ f"'environment_suffix_target: catalog' is mutually exclusive with 'environment_catalog_mapping'.\n"
251
+ "Please specify one or the other"
252
+ )
253
+
245
254
  if self.environment_catalog_mapping:
246
255
  _normalize_identifiers("environment_catalog_mapping")
247
256
  if self.physical_schema_mapping:
sqlmesh/core/constants.py CHANGED
@@ -7,6 +7,7 @@ import typing as t
7
7
  from pathlib import Path
8
8
 
9
9
  SQLMESH = "sqlmesh"
10
+ SQLMESH_MANAGED = "sqlmesh_managed"
10
11
  SQLMESH_PATH = Path.home() / ".sqlmesh"
11
12
 
12
13
  PROD = "prod"
@@ -101,6 +101,7 @@ class EngineAdapter:
101
101
  SUPPORTS_VIEW_SCHEMA = True
102
102
  SUPPORTS_CLONING = False
103
103
  SUPPORTS_MANAGED_MODELS = False
104
+ SUPPORTS_CREATE_DROP_CATALOG = False
104
105
  SCHEMA_DIFFER = SchemaDiffer()
105
106
  SUPPORTS_TUPLE_IN = True
106
107
  HAS_VIEW_BINDING = False
@@ -1217,6 +1218,22 @@ class EngineAdapter:
1217
1218
  **kwargs,
1218
1219
  )
1219
1220
 
1221
+ def create_catalog(self, catalog_name: str | exp.Identifier) -> None:
1222
+ return self._create_catalog(exp.parse_identifier(catalog_name, dialect=self.dialect))
1223
+
1224
+ def _create_catalog(self, catalog_name: exp.Identifier) -> None:
1225
+ raise SQLMeshError(
1226
+ f"Unable to create catalog '{catalog_name.sql(dialect=self.dialect)}' as automatic catalog management is not implemented in the {self.dialect} engine."
1227
+ )
1228
+
1229
+ def drop_catalog(self, catalog_name: str | exp.Identifier) -> None:
1230
+ return self._drop_catalog(exp.parse_identifier(catalog_name, dialect=self.dialect))
1231
+
1232
+ def _drop_catalog(self, catalog_name: exp.Identifier) -> None:
1233
+ raise SQLMeshError(
1234
+ f"Unable to drop catalog '{catalog_name.sql(dialect=self.dialect)}' as automatic catalog management is not implemented in the {self.dialect} engine."
1235
+ )
1236
+
1220
1237
  def columns(
1221
1238
  self, table_name: TableName, include_pseudo_columns: bool = False
1222
1239
  ) -> t.Dict[str, exp.DataType]:
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import typing as t
4
4
  from sqlglot import exp
5
+ from pathlib import Path
5
6
 
6
7
  from sqlmesh.core.engine_adapter.mixins import (
7
8
  GetCurrentCatalogFromFunctionMixin,
@@ -35,6 +36,7 @@ class DuckDBEngineAdapter(LogicalMergeMixin, GetCurrentCatalogFromFunctionMixin,
35
36
  )
36
37
  COMMENT_CREATION_TABLE = CommentCreationTable.COMMENT_COMMAND_ONLY
37
38
  COMMENT_CREATION_VIEW = CommentCreationView.COMMENT_COMMAND_ONLY
39
+ SUPPORTS_CREATE_DROP_CATALOG = True
38
40
 
39
41
  @property
40
42
  def catalog_support(self) -> CatalogSupport:
@@ -44,6 +46,18 @@ class DuckDBEngineAdapter(LogicalMergeMixin, GetCurrentCatalogFromFunctionMixin,
44
46
  """Sets the catalog name of the current connection."""
45
47
  self.execute(exp.Use(this=exp.to_identifier(catalog)))
46
48
 
49
+ def _create_catalog(self, catalog_name: exp.Identifier) -> None:
50
+ db_filename = f"{catalog_name.output_name}.db"
51
+ self.execute(
52
+ exp.Attach(this=exp.alias_(exp.Literal.string(db_filename), catalog_name), exists=True)
53
+ )
54
+
55
+ def _drop_catalog(self, catalog_name: exp.Identifier) -> None:
56
+ db_file_path = Path(f"{catalog_name.output_name}.db")
57
+ self.execute(exp.Detach(this=catalog_name, exists=True))
58
+ if db_file_path.exists():
59
+ db_file_path.unlink()
60
+
47
61
  def _df_to_source_queries(
48
62
  self,
49
63
  df: DF,
@@ -173,9 +173,16 @@ class DataObject(PydanticModel):
173
173
 
174
174
 
175
175
  class CatalogSupport(Enum):
176
+ # The engine has no concept of catalogs
176
177
  UNSUPPORTED = 1
178
+
179
+ # The engine has a concept of catalogs, but they are isolated from each other and cannot reference each others tables
177
180
  SINGLE_CATALOG_ONLY = 2
181
+
182
+ # The engine supports multiple catalogs but some operations require a SET CATALOG query to set the active catalog before proceeding
178
183
  REQUIRES_SET_CATALOG = 3
184
+
185
+ # The engine supports multiple catalogs and can unambiguously target a specific catalog when performing operations (without running SET CATALOG first)
179
186
  FULL_SUPPORT = 4
180
187
 
181
188
  @property
@@ -9,6 +9,7 @@ from sqlglot.helper import ensure_list
9
9
  from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
10
10
  from sqlglot.optimizer.qualify_columns import quote_identifiers
11
11
 
12
+ import sqlmesh.core.constants as c
12
13
  from sqlmesh.core.dialect import to_schema
13
14
  from sqlmesh.core.engine_adapter.mixins import (
14
15
  GetCurrentCatalogFromFunctionMixin,
@@ -43,6 +44,7 @@ if t.TYPE_CHECKING:
43
44
  "_get_data_objects": CatalogSupport.REQUIRES_SET_CATALOG,
44
45
  "create_schema": CatalogSupport.REQUIRES_SET_CATALOG,
45
46
  "drop_schema": CatalogSupport.REQUIRES_SET_CATALOG,
47
+ "drop_catalog": CatalogSupport.REQUIRES_SET_CATALOG, # needs a catalog to issue a query to information_schema.databases even though the result is global
46
48
  }
47
49
  )
48
50
  class SnowflakeEngineAdapter(GetCurrentCatalogFromFunctionMixin, ClusteredByMixin, RowDiffMixin):
@@ -52,6 +54,7 @@ class SnowflakeEngineAdapter(GetCurrentCatalogFromFunctionMixin, ClusteredByMixi
52
54
  SUPPORTS_CLONING = True
53
55
  SUPPORTS_MANAGED_MODELS = True
54
56
  CURRENT_CATALOG_EXPRESSION = exp.func("current_database")
57
+ SUPPORTS_CREATE_DROP_CATALOG = True
55
58
  SCHEMA_DIFFER = SchemaDiffer(
56
59
  parameterized_type_defaults={
57
60
  exp.DataType.build("BINARY", dialect=DIALECT).this: [(8388608,)],
@@ -123,6 +126,36 @@ class SnowflakeEngineAdapter(GetCurrentCatalogFromFunctionMixin, ClusteredByMixi
123
126
  def catalog_support(self) -> CatalogSupport:
124
127
  return CatalogSupport.FULL_SUPPORT
125
128
 
129
+ def _create_catalog(self, catalog_name: exp.Identifier) -> None:
130
+ props = exp.Properties(
131
+ expressions=[exp.SchemaCommentProperty(this=exp.Literal.string(c.SQLMESH_MANAGED))]
132
+ )
133
+ self.execute(
134
+ exp.Create(
135
+ this=exp.Table(this=catalog_name), kind="DATABASE", exists=True, properties=props
136
+ )
137
+ )
138
+
139
+ def _drop_catalog(self, catalog_name: exp.Identifier) -> None:
140
+ # only drop the catalog if it was created by SQLMesh, which is indicated by its comment matching {c.SQLMESH_MANAGED}
141
+ exists_check = (
142
+ exp.select(exp.Literal.number(1))
143
+ .from_(exp.to_table("information_schema.databases"))
144
+ .where(
145
+ exp.and_(
146
+ exp.column("database_name").eq(exp.Literal.string(catalog_name)),
147
+ exp.column("comment").eq(exp.Literal.string(c.SQLMESH_MANAGED)),
148
+ )
149
+ )
150
+ )
151
+ normalize_identifiers(exists_check, dialect=self.dialect)
152
+ if self.fetchone(exists_check, quote_identifiers=True) is not None:
153
+ self.execute(exp.Drop(this=exp.Table(this=catalog_name), kind="DATABASE", exists=True))
154
+ else:
155
+ logger.warning(
156
+ f"Not dropping database {catalog_name.sql(dialect=self.dialect)} because there is no indication it is '{c.SQLMESH_MANAGED}'"
157
+ )
158
+
126
159
  def _create_table(
127
160
  self,
128
161
  table_name_or_schema: t.Union[exp.Schema, TableName],
@@ -43,6 +43,10 @@ class EnvironmentNamingInfo(PydanticModel):
43
43
  normalize_name: bool = True
44
44
  gateway_managed: bool = False
45
45
 
46
+ @property
47
+ def is_dev(self) -> bool:
48
+ return self.name.lower() != c.PROD
49
+
46
50
  @field_validator("name", mode="before")
47
51
  @classmethod
48
52
  def _sanitize_name(cls, v: str) -> str:
@@ -274,13 +274,19 @@ class QualifiedViewName(PydanticModel, frozen=True):
274
274
  def catalog_for_environment(
275
275
  self, environment_naming_info: EnvironmentNamingInfo, dialect: DialectType = None
276
276
  ) -> t.Optional[str]:
277
- if environment_naming_info.catalog_name_override:
277
+ catalog_name: t.Optional[str] = None
278
+ if environment_naming_info.is_dev and environment_naming_info.suffix_target.is_catalog:
279
+ catalog_name = f"{self.catalog}__{environment_naming_info.name}"
280
+ elif environment_naming_info.catalog_name_override:
278
281
  catalog_name = environment_naming_info.catalog_name_override
282
+
283
+ if catalog_name:
279
284
  return (
280
285
  normalize_identifiers(catalog_name, dialect=dialect).name
281
286
  if environment_naming_info.normalize_name
282
287
  else catalog_name
283
288
  )
289
+
284
290
  return self.catalog
285
291
 
286
292
  def schema_for_environment(
@@ -295,10 +301,7 @@ class QualifiedViewName(PydanticModel, frozen=True):
295
301
  if normalize:
296
302
  schema = normalize_identifiers(schema, dialect=dialect).name
297
303
 
298
- if (
299
- environment_naming_info.name.lower() != c.PROD
300
- and environment_naming_info.suffix_target.is_schema
301
- ):
304
+ if environment_naming_info.is_dev and environment_naming_info.suffix_target.is_schema:
302
305
  env_name = environment_naming_info.name
303
306
  if normalize:
304
307
  env_name = normalize_identifiers(env_name, dialect=dialect).name
@@ -311,10 +314,7 @@ class QualifiedViewName(PydanticModel, frozen=True):
311
314
  self, environment_naming_info: EnvironmentNamingInfo, dialect: DialectType = None
312
315
  ) -> str:
313
316
  table = self.table
314
- if (
315
- environment_naming_info.name.lower() != c.PROD
316
- and environment_naming_info.suffix_target.is_table
317
- ):
317
+ if environment_naming_info.is_dev and environment_naming_info.suffix_target.is_table:
318
318
  env_name = environment_naming_info.name
319
319
  if environment_naming_info.normalize_name:
320
320
  env_name = normalize_identifiers(env_name, dialect=dialect).name
@@ -251,6 +251,8 @@ class SnapshotEvaluator:
251
251
 
252
252
  # A schema can be shared across multiple engines, so we need to group by gateway
253
253
  for gateway, tables in tables_by_gateway.items():
254
+ if environment_naming_info.suffix_target.is_catalog:
255
+ self._create_catalogs(tables=tables, gateway=gateway)
254
256
  self._create_schemas(tables=tables, gateway=gateway)
255
257
 
256
258
  deployability_index = deployability_index or DeployabilityIndex.all_deployable()
@@ -1114,6 +1116,18 @@ class SnapshotEvaluator:
1114
1116
  blocking=blocking,
1115
1117
  )
1116
1118
 
1119
+ def _create_catalogs(
1120
+ self,
1121
+ tables: t.Iterable[t.Union[exp.Table, str]],
1122
+ gateway: t.Optional[str] = None,
1123
+ ) -> None:
1124
+ # attempt to create catalogs for the virtual layer if possible
1125
+ adapter = self.get_adapter(gateway)
1126
+ if adapter.SUPPORTS_CREATE_DROP_CATALOG:
1127
+ unique_catalogs = {t.catalog for t in [exp.to_table(maybe_t) for maybe_t in tables]}
1128
+ for catalog_name in unique_catalogs:
1129
+ adapter.create_catalog(catalog_name)
1130
+
1117
1131
  def _create_schemas(
1118
1132
  self,
1119
1133
  tables: t.Iterable[t.Union[exp.Table, str]],
@@ -30,7 +30,9 @@ def cleanup_expired_views(
30
30
  console: t.Optional[Console] = None,
31
31
  ) -> None:
32
32
  expired_schema_environments = [
33
- environment for environment in environments if environment.suffix_target.is_schema
33
+ environment
34
+ for environment in environments
35
+ if environment.suffix_target.is_schema or environment.suffix_target.is_catalog
34
36
  ]
35
37
  expired_table_environments = [
36
38
  environment for environment in environments if environment.suffix_target.is_table
@@ -42,8 +44,10 @@ def cleanup_expired_views(
42
44
  return engine_adapters.get(gateway, default_adapter)
43
45
  return default_adapter
44
46
 
47
+ catalogs_to_drop: t.Set[t.Tuple[EngineAdapter, str]] = set()
48
+
45
49
  # Drop the schemas for the expired environments
46
- for engine_adapter, expired_catalog, expired_schema in {
50
+ for engine_adapter, expired_catalog, expired_schema, suffix_target in {
47
51
  (
48
52
  (engine_adapter := get_adapter(environment.gateway_managed, snapshot.model_gateway)),
49
53
  snapshot.qualified_view_name.catalog_for_environment(
@@ -52,6 +56,7 @@ def cleanup_expired_views(
52
56
  snapshot.qualified_view_name.schema_for_environment(
53
57
  environment.naming_info, dialect=engine_adapter.dialect
54
58
  ),
59
+ environment.suffix_target,
55
60
  )
56
61
  for environment in expired_schema_environments
57
62
  for snapshot in environment.snapshots
@@ -64,6 +69,10 @@ def cleanup_expired_views(
64
69
  ignore_if_not_exists=True,
65
70
  cascade=True,
66
71
  )
72
+
73
+ if suffix_target.is_catalog and expired_catalog:
74
+ catalogs_to_drop.add((engine_adapter, expired_catalog))
75
+
67
76
  if console:
68
77
  console.update_cleanup_progress(schema.sql(dialect=engine_adapter.dialect))
69
78
  except Exception as e:
@@ -96,6 +105,21 @@ def cleanup_expired_views(
96
105
  else:
97
106
  raise SQLMeshError(message) from e
98
107
 
108
+ # Drop any catalogs that were associated with a snapshot where the engine adapter supports dropping catalogs
109
+ # catalogs_to_drop is only populated when environment_suffix_target is set to 'catalog'
110
+ for engine_adapter, catalog in catalogs_to_drop:
111
+ if engine_adapter.SUPPORTS_CREATE_DROP_CATALOG:
112
+ try:
113
+ engine_adapter.drop_catalog(catalog)
114
+ if console:
115
+ console.update_cleanup_progress(catalog)
116
+ except Exception as e:
117
+ message = f"Failed to drop the expired environment catalog '{catalog}': {e}"
118
+ if warn_on_delete_failure:
119
+ logger.warning(message)
120
+ else:
121
+ raise SQLMeshError(message) from e
122
+
99
123
 
100
124
  def transactional() -> t.Callable[[t.Callable], t.Callable]:
101
125
  def decorator(func: t.Callable) -> t.Callable:
sqlmesh/lsp/reference.py CHANGED
@@ -208,6 +208,17 @@ def get_model_definitions_for_a_path(
208
208
  target_range=target_range,
209
209
  )
210
210
  )
211
+
212
+ column_references = _process_column_references(
213
+ scope=scope,
214
+ reference_name=table.name,
215
+ read_file=read_file,
216
+ referenced_model_uri=document_uri,
217
+ description="",
218
+ reference_type="cte",
219
+ cte_target_range=target_range,
220
+ )
221
+ references.extend(column_references)
211
222
  continue
212
223
 
213
224
  # For non-CTE tables, process as before (external model references)
@@ -276,6 +287,19 @@ def get_model_definitions_for_a_path(
276
287
  target_range=yaml_target_range,
277
288
  )
278
289
  )
290
+
291
+ column_references = _process_column_references(
292
+ scope=scope,
293
+ reference_name=normalized_reference_name,
294
+ read_file=read_file,
295
+ referenced_model_uri=referenced_model_uri,
296
+ description=description,
297
+ yaml_target_range=yaml_target_range,
298
+ reference_type="external_model",
299
+ default_catalog=lint_context.context.default_catalog,
300
+ dialect=dialect,
301
+ )
302
+ references.extend(column_references)
279
303
  else:
280
304
  references.append(
281
305
  LSPModelReference(
@@ -288,6 +312,18 @@ def get_model_definitions_for_a_path(
288
312
  )
289
313
  )
290
314
 
315
+ column_references = _process_column_references(
316
+ scope=scope,
317
+ reference_name=normalized_reference_name,
318
+ read_file=read_file,
319
+ referenced_model_uri=referenced_model_uri,
320
+ description=description,
321
+ reference_type="model",
322
+ default_catalog=lint_context.context.default_catalog,
323
+ dialect=dialect,
324
+ )
325
+ references.extend(column_references)
326
+
291
327
  return references
292
328
 
293
329
 
@@ -735,6 +771,104 @@ def _position_within_range(position: Position, range: Range) -> bool:
735
771
  )
736
772
 
737
773
 
774
+ def _get_column_table_range(column: exp.Column, read_file: t.List[str]) -> Range:
775
+ """
776
+ Get the range for a column's table reference, handling both simple and qualified table names.
777
+
778
+ Args:
779
+ column: The column expression
780
+ read_file: The file content as list of lines
781
+
782
+ Returns:
783
+ The Range covering the table reference in the column
784
+ """
785
+
786
+ table_parts = column.parts[:-1]
787
+
788
+ start_range = TokenPositionDetails.from_meta(table_parts[0].meta).to_range(read_file)
789
+ end_range = TokenPositionDetails.from_meta(table_parts[-1].meta).to_range(read_file)
790
+
791
+ return Range(
792
+ start=to_lsp_position(start_range.start),
793
+ end=to_lsp_position(end_range.end),
794
+ )
795
+
796
+
797
+ def _process_column_references(
798
+ scope: t.Any,
799
+ reference_name: str,
800
+ read_file: t.List[str],
801
+ referenced_model_uri: URI,
802
+ description: t.Optional[str] = None,
803
+ yaml_target_range: t.Optional[Range] = None,
804
+ reference_type: t.Literal["model", "external_model", "cte"] = "model",
805
+ default_catalog: t.Optional[str] = None,
806
+ dialect: t.Optional[str] = None,
807
+ cte_target_range: t.Optional[Range] = None,
808
+ ) -> t.List[Reference]:
809
+ """
810
+ Process column references for a given table and create appropriate reference objects.
811
+
812
+ Args:
813
+ scope: The SQL scope to search for columns
814
+ reference_name: The full reference name (may include database/catalog)
815
+ read_file: The file content as list of lines
816
+ referenced_model_uri: URI of the referenced model
817
+ description: Markdown description for the reference
818
+ yaml_target_range: Target range for external models (YAML files)
819
+ reference_type: Type of reference - "model", "external_model", or "cte"
820
+ default_catalog: Default catalog for normalization
821
+ dialect: SQL dialect for normalization
822
+ cte_target_range: Target range for CTE references
823
+
824
+ Returns:
825
+ List of table references for column usages
826
+ """
827
+
828
+ references: t.List[Reference] = []
829
+ for column in scope.find_all(exp.Column):
830
+ if column.table:
831
+ if reference_type == "cte":
832
+ if column.table == reference_name:
833
+ table_range = _get_column_table_range(column, read_file)
834
+ references.append(
835
+ LSPCteReference(
836
+ uri=referenced_model_uri.value,
837
+ range=table_range,
838
+ target_range=cte_target_range,
839
+ )
840
+ )
841
+ else:
842
+ table_parts = [part.sql(dialect) for part in column.parts[:-1]]
843
+ table_ref = ".".join(table_parts)
844
+ normalized_reference_name = normalize_model_name(
845
+ table_ref,
846
+ default_catalog=default_catalog,
847
+ dialect=dialect,
848
+ )
849
+ if normalized_reference_name == reference_name:
850
+ table_range = _get_column_table_range(column, read_file)
851
+ if reference_type == "external_model":
852
+ references.append(
853
+ LSPExternalModelReference(
854
+ uri=referenced_model_uri.value,
855
+ range=table_range,
856
+ markdown_description=description,
857
+ target_range=yaml_target_range,
858
+ )
859
+ )
860
+ else:
861
+ references.append(
862
+ LSPModelReference(
863
+ uri=referenced_model_uri.value,
864
+ range=table_range,
865
+ markdown_description=description,
866
+ )
867
+ )
868
+
869
+ return references
870
+
871
+
738
872
  def _get_yaml_model_range(path: Path, model_name: str) -> t.Optional[Range]:
739
873
  """
740
874
  Find the range of a specific model block in a YAML file.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.194.2.dev2
3
+ Version: 0.194.2.dev4
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=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
2
- sqlmesh/_version.py,sha256=X9WhNXw_d4LxsrbPqqa8GOR2MyOQDT1Kor9UJSnv-fo,528
2
+ sqlmesh/_version.py,sha256=4AXoTdklMBMT8Jjx_8JGYvr6SI6W51xe_eIQYgKEEdg,528
3
3
  sqlmesh/magics.py,sha256=ysPC5ohXpgQ8IHQPwtQtwGoVypmVq_YBlm1noUueDIw,40448
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -12,11 +12,11 @@ sqlmesh/cli/options.py,sha256=aC_L5WnMScKzMU55BD1Y-8R-QzqCkPSYrlCI-payHRA,1333
12
12
  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=pMIkBjaigneVqGkoGxOKVmT423RPfbDKX8TQ8D1SzpU,153466
15
- sqlmesh/core/constants.py,sha256=pnQXs5cS61zqjS8szbA1IRYTZ_G5jIt8Qrw-gneQoqE,2594
15
+ sqlmesh/core/constants.py,sha256=gUABXWYgH_XOSbaZAJsR5o1dmA61JDCvBDyxqqXX3LM,2630
16
16
  sqlmesh/core/context.py,sha256=LyPmWyUjHhW415_yoH4IQ5KLEV8cY6gF2znjMewx4yY,118131
17
17
  sqlmesh/core/context_diff.py,sha256=TCzM8egBE35DskpouOB-GQM2Qf5iUHWbRgiB5yZ6tzg,21552
18
18
  sqlmesh/core/dialect.py,sha256=93cXYVuNoZ9CvJNTVn2Yz7WDOdHINwVXflbn0eZ-p14,49764
19
- sqlmesh/core/environment.py,sha256=bNj-JCG_l13dwrp--YPIuGNsuWLTMLcFA5sY8IazVK8,12917
19
+ sqlmesh/core/environment.py,sha256=7DbJX0r5nZRU3LhcgIxbSV-JosQYDjAt3V5Wc2Fpns8,13005
20
20
  sqlmesh/core/lineage.py,sha256=zjB0Zfamo2Fja2r5SSZPMbrEKTXr1WjozZPVqvxdybI,3143
21
21
  sqlmesh/core/loader.py,sha256=XVUd1UwK8jlJUaZdFBghSslipH2L80YVykjFzdGMCYA,40474
22
22
  sqlmesh/core/macros.py,sha256=L_UlI4kysfDiYYpv78kODZw8kYbC9-FdBx7nHm1hBjs,60584
@@ -40,7 +40,7 @@ sqlmesh/core/audit/definition.py,sha256=QXXObhR_jHgjWLu0qXxPuIXm0GlFQq33rhp11m_x
40
40
  sqlmesh/core/config/__init__.py,sha256=b4gFb04tpeZpowqJD-7h3U3TLgxrpQhZahVEAo6VW2Y,2009
41
41
  sqlmesh/core/config/base.py,sha256=t8NQmsgQoZSc-k0dlDiCb8t1jj0AMYdGZ-6se9q_Pks,4898
42
42
  sqlmesh/core/config/categorizer.py,sha256=6vzUoNLjR6GOEb_2mYVz2TwmMv2BfldgHX2u-Le5HZs,1975
43
- sqlmesh/core/config/common.py,sha256=-o_HoRFtR4u84frg_TLno7z7vS9II6ASiOayb59MKHo,2806
43
+ sqlmesh/core/config/common.py,sha256=rsb2uVFqPEX3DMsWG_hApwztCuRJP-FAmaQ_5L3-S8g,4006
44
44
  sqlmesh/core/config/connection.py,sha256=sxRPhP0q088kInXtZinEK2FbkQHkzJZrGMDF-VnWmtA,82137
45
45
  sqlmesh/core/config/feature_flag.py,sha256=JRcD31OG_t2cYc24meKbHDGB0iVID0P07V2oOeB_mgA,203
46
46
  sqlmesh/core/config/format.py,sha256=6CXFbvnor56xbldKE-Vrm9k_ABRoY4v6vgIb3mCihiQ,1355
@@ -52,27 +52,27 @@ sqlmesh/core/config/migration.py,sha256=3lZIlmIcQH3_hIEm3Y3jFtvpw0YXzRzAnk4Odikl
52
52
  sqlmesh/core/config/model.py,sha256=GIz9kAfKD2NEXNzCZCQ17-CK2OtqN6WgeG1fvibcChM,3650
53
53
  sqlmesh/core/config/naming.py,sha256=KVGaxUgswoQajXR_cHFJvgkmEFcU1V182GkOH1SJxuE,326
54
54
  sqlmesh/core/config/plan.py,sha256=wJEDfocMcKSMN0-5gVojjIcmJZ0376LJU3tkGMTm-Zc,1558
55
- sqlmesh/core/config/root.py,sha256=9jeIIwJjxGsuTCCwa90M2ZREk6pCIempxY2PhN7Q0Jo,15166
55
+ sqlmesh/core/config/root.py,sha256=tZxArC4kjPqrt43R9uErH_awwwNQVaNIaTAb-ot9WiU,15529
56
56
  sqlmesh/core/config/run.py,sha256=rIK0QnN_vArrwps2TXGVEbvao2AnGZgzXo7EliJa42E,852
57
57
  sqlmesh/core/config/scheduler.py,sha256=k3BVMpy5ZrC05ZlyE3vec8ZGfTjUjWyfsKZtYgflbyA,7029
58
58
  sqlmesh/core/config/ui.py,sha256=jsO-S6_d9NkLZGG5pT4mgKgxMF34KzkDociZAMvCX3U,278
59
59
  sqlmesh/core/engine_adapter/__init__.py,sha256=two_WTs4UnSNp-fscJh8vOunJq0Xi37EuDuMjKsKuNE,2281
60
60
  sqlmesh/core/engine_adapter/_typing.py,sha256=_63pYCThfC39UtPVHY3N0H6qJ1YBT32OqwwR3swolGM,1037
61
61
  sqlmesh/core/engine_adapter/athena.py,sha256=WBVAB_YzBJXdiqq51LTd2jmYoMtGrLmtsA8IrIFVnQ0,26199
62
- sqlmesh/core/engine_adapter/base.py,sha256=2W3dPeO7iqaA3byEDziB3lBh7pjgaq4_J8IKkcX4urg,101348
62
+ sqlmesh/core/engine_adapter/base.py,sha256=R90ZhxpVb58Vl-zVse9fkNVbm3eD3lqi1PhW_WBOtAQ,102263
63
63
  sqlmesh/core/engine_adapter/base_postgres.py,sha256=DOsOdCJyQAVfA9S0GznuH0J1bonMqYVP_yJLDYcxFYM,6772
64
64
  sqlmesh/core/engine_adapter/bigquery.py,sha256=qJE8vHLKKAeWMvltmYaUvWS95jM_UEZ6UzYLlr58sGo,50424
65
65
  sqlmesh/core/engine_adapter/clickhouse.py,sha256=LoPdm_s_s-ZxS1XJPA3Et0iOHeJ1LgqTAFbwBdiqE7A,34912
66
66
  sqlmesh/core/engine_adapter/databricks.py,sha256=8ZExPIeT3dDh9MTJW8udvmh9LiY-f9HkRAN1Q5Qebhs,14541
67
- sqlmesh/core/engine_adapter/duckdb.py,sha256=rFv27sF1KXhJcrIuM9Zdfl2cyZNRXEF9qQczgODdK0M,4614
67
+ sqlmesh/core/engine_adapter/duckdb.py,sha256=TlSFSWNzUfjGdhuMyCi1CLwhBaEKyNKtasub9OsYwrc,5199
68
68
  sqlmesh/core/engine_adapter/mixins.py,sha256=HMB0Z9O3p5jaTZMolKiWKqpVDZokf5GoI99YXwEJ8bc,22470
69
69
  sqlmesh/core/engine_adapter/mssql.py,sha256=e-PElz8RAUwD-fGCx-2oleg3UGxFH-f0AzXODR3hpm0,14140
70
70
  sqlmesh/core/engine_adapter/mysql.py,sha256=lVC-siXZK3iSfqCmBjZNw8uy09Z8la8v8_oUZ-E2OwI,6966
71
71
  sqlmesh/core/engine_adapter/postgres.py,sha256=fdQrsBodfGlNf8lZYkS99U_gjoDyaYKEVKLgScduv3I,4601
72
72
  sqlmesh/core/engine_adapter/redshift.py,sha256=B4GsPggz-xyvBpx5qubvVwEeKF3vk7n5SMExL-Q5Ysw,16754
73
73
  sqlmesh/core/engine_adapter/risingwave.py,sha256=YYCQ0EJaSrR9_P1_2_LmElQ6zSxqkZzhvhdm-2WtWWg,969
74
- sqlmesh/core/engine_adapter/shared.py,sha256=NyF2osSJDWPp7KlJUBR4GZcS_cJFr4daUPvhGyp4XcQ,12909
75
- sqlmesh/core/engine_adapter/snowflake.py,sha256=oaZxKPmPXxmr46NQfw6OI5vPwvaYJ3Ym8OnnhDiUXNw,27234
74
+ sqlmesh/core/engine_adapter/shared.py,sha256=zL2W2t9af9mo80aSO0fz5TqV6mY8_kI5VYLswbKdZyk,13369
75
+ sqlmesh/core/engine_adapter/snowflake.py,sha256=IEEzepxNpfqBIMe4ziz2k8fjOcJPeQPZyM3XljymAj0,28874
76
76
  sqlmesh/core/engine_adapter/spark.py,sha256=sYkVOPS0X43UPbI0z7Hh_EpKlI36qkOcr4NNFOTQlLs,21045
77
77
  sqlmesh/core/engine_adapter/trino.py,sha256=7WdLFlT0AyD5NF0EDP7GqX0SHF8sTm7cafBZxk84cmY,15798
78
78
  sqlmesh/core/linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -102,12 +102,12 @@ sqlmesh/core/plan/stages.py,sha256=9BtcCgHYSvELrAkrOEhTuR1POAJNknLn_n4CmkqAC-4,2
102
102
  sqlmesh/core/snapshot/__init__.py,sha256=Z5HTetNCZGoKF1WAKXk4LWL9dc8EC8lwS2O4TtoBmt4,1317
103
103
  sqlmesh/core/snapshot/cache.py,sha256=bgqCR2hyf6r2A_8QP1EnXFK25gDX37-Zg0YeMuETWxg,3934
104
104
  sqlmesh/core/snapshot/categorizer.py,sha256=qGG5870mu1jR2whKisSBH_GFbsyh96RnzJDgkN7DV9g,2482
105
- sqlmesh/core/snapshot/definition.py,sha256=-cMc1jkJQox3BCoW6bk8qtSgMivr6nuKcGpKKkx4x8A,84216
106
- sqlmesh/core/snapshot/evaluator.py,sha256=QqFcvXcr3NMHJtWy2wBRfDIph9EKPGpHaPg-36YjbDs,89484
105
+ sqlmesh/core/snapshot/definition.py,sha256=mjGZBpzhKI9gYLmuYhSAs0IBKEo_JdfX66EcR9yRcig,84359
106
+ sqlmesh/core/snapshot/evaluator.py,sha256=zuxNnEKCyImFIT_hWLNc7xtKv4uflkKXOLprkD_hCJE,90132
107
107
  sqlmesh/core/state_sync/__init__.py,sha256=B60xj-_Xk-4jas3UphLvwkuf04G-9AyGckcblXE0aRg,869
108
108
  sqlmesh/core/state_sync/base.py,sha256=WLlwcbF53BHsX1jCsVjWewO9Ht7QUsn2ktJ3-q5iK8g,18346
109
109
  sqlmesh/core/state_sync/cache.py,sha256=0AsYdQyBqbLdJvkBQ-hDAipsvnn_jSps-nya-Q4XeL0,5337
110
- sqlmesh/core/state_sync/common.py,sha256=THK-6AGHFBAuLXydD8QhzmzCdyl0BMrz2rB2xpmC99Y,6532
110
+ sqlmesh/core/state_sync/common.py,sha256=x8Nkox6VmkD-lYZkjRcNe3iVsChR1HBroTorf1kATpQ,7609
111
111
  sqlmesh/core/state_sync/export_import.py,sha256=WJ7sFX2b_RPAFE4yspJRi_4JQnaO23xpJgRxwXD0agA,8709
112
112
  sqlmesh/core/state_sync/db/__init__.py,sha256=jGCqKYB7npq4eh6H2LyfBAJWdOP-IFu0DC4CMiQgYvw,107
113
113
  sqlmesh/core/state_sync/db/environment.py,sha256=RKaP71CDI7YFhLYuyYVbtyBEWfwvNd2_XsDvjtrQq2Q,13645
@@ -173,7 +173,7 @@ sqlmesh/lsp/description.py,sha256=PjguwyVw5YeYSgT0JMhkf5U1Jry-sDPLvQ2caIR9JPQ,85
173
173
  sqlmesh/lsp/helpers.py,sha256=EFc1u3-b7kSv5-tNwmKUDxId72RCLDBnN2lLTgRSzzQ,1020
174
174
  sqlmesh/lsp/hints.py,sha256=j-blccBUil94yRoDjWfkSM0HqMmsKD6hP2TaWdWWVk4,3734
175
175
  sqlmesh/lsp/main.py,sha256=EanNAS5ArBRc2oYsS3jhL46pfzXLn78xwSW-9R4RQ3o,33731
176
- sqlmesh/lsp/reference.py,sha256=8hZT3wH8zmWiFEySS1_nVhhLg-CKCGncf9wG3LGBef8,26432
176
+ sqlmesh/lsp/reference.py,sha256=NyfpK12TouDuy5-G7KOhvifkJItMfrakKwnMoU6SiVk,32088
177
177
  sqlmesh/lsp/uri.py,sha256=mvSLbZGmMTHPpliThOtVWiFcHnfJzp1w39q9l-xD2SI,802
178
178
  sqlmesh/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
179
179
  sqlmesh/migrations/v0001_init.py,sha256=h8FwMYJj9_O8yGpk12guaSaGwX5A3we2GiKeHrXi15o,2048
@@ -282,7 +282,7 @@ sqlmesh/utils/pydantic.py,sha256=I898jAFqa3qU6lG2uPpRebVFncOUo8ZrLWM_R3K3DHU,116
282
282
  sqlmesh/utils/rich.py,sha256=BpB47G0-JcU41LkGkeGKroexj4NOV5fox4-GOIXPgIc,3545
283
283
  sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
284
284
  sqlmesh/utils/yaml.py,sha256=np-WVcwmwsKghCgAj1OBBMsK1SXSRn4wR-H37cGiFr8,2282
285
- sqlmesh-0.194.2.dev2.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
285
+ sqlmesh-0.194.2.dev4.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
286
286
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
287
  web/client/dist/index.html,sha256=w71qWSLmp-xwmVJO8m41k8Rtni3iZlF0hmhiTr-NeCI,5472
288
288
  web/client/dist/assets/Audits-sYYNn2gO.js,sha256=zSAKkif2kU0JuPH05xjNYITNPmsbDlvLKUc2-orr8AY,1041
@@ -400,8 +400,8 @@ web/server/api/endpoints/models.py,sha256=ud-lRwriyI_OYg9tZchrBgeiXELiRTLNEodraf
400
400
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
401
401
  web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
402
402
  web/server/api/endpoints/table_diff.py,sha256=SCy3-pr5x6bEEiOaZGCDbiHQhpgxwmnz3Acqa2Ie6jI,2090
403
- sqlmesh-0.194.2.dev2.dist-info/METADATA,sha256=W1n4Liu5KBzaudz0SU2PhmXUGSURfsCHfw5YhnO2Iek,26690
404
- sqlmesh-0.194.2.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
405
- sqlmesh-0.194.2.dev2.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
406
- sqlmesh-0.194.2.dev2.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
407
- sqlmesh-0.194.2.dev2.dist-info/RECORD,,
403
+ sqlmesh-0.194.2.dev4.dist-info/METADATA,sha256=pevBdvNfo9E_J4tgKi3OEpgwh1snIDvFiV1molPT_04,26690
404
+ sqlmesh-0.194.2.dev4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
405
+ sqlmesh-0.194.2.dev4.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
406
+ sqlmesh-0.194.2.dev4.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
407
+ sqlmesh-0.194.2.dev4.dist-info/RECORD,,