sqlmesh 0.189.3.dev3__py3-none-any.whl → 0.189.3.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.189.3.dev3'
21
- __version_tuple__ = version_tuple = (0, 189, 3, 'dev3')
20
+ __version__ = version = '0.189.3.dev4'
21
+ __version_tuple__ = version_tuple = (0, 189, 3, 'dev4')
sqlmesh/cli/main.py CHANGED
@@ -938,6 +938,11 @@ def create_external_models(obj: Context, **kwargs: t.Any) -> None:
938
938
  multiple=True,
939
939
  help="Specify one or more models to data diff. Use wildcards to diff multiple models. Ex: '*' (all models with applied plan diffs), 'demo.model+' (this and downstream models), 'git:feature_branch' (models with direct modifications in this branch only)",
940
940
  )
941
+ @click.option(
942
+ "--schema-diff-ignore-case",
943
+ is_flag=True,
944
+ help="If set, when performing a schema diff the case of column names is ignored when matching between the two schemas. For example, 'col_a' in the source schema and 'COL_A' in the target schema will be treated as the same column.",
945
+ )
941
946
  @click.pass_obj
942
947
  @error_handler
943
948
  @cli_analytics
sqlmesh/core/context.py CHANGED
@@ -1673,6 +1673,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1673
1673
  skip_grain_check: bool = False,
1674
1674
  warn_grain_check: bool = False,
1675
1675
  temp_schema: t.Optional[str] = None,
1676
+ schema_diff_ignore_case: bool = False,
1676
1677
  ) -> t.List[TableDiff]:
1677
1678
  """Show a diff between two tables.
1678
1679
 
@@ -1796,6 +1797,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1796
1797
  show=show,
1797
1798
  temp_schema=temp_schema,
1798
1799
  skip_grain_check=skip_grain_check,
1800
+ schema_diff_ignore_case=schema_diff_ignore_case,
1799
1801
  ),
1800
1802
  tasks_num=tasks_num,
1801
1803
  )
@@ -1821,6 +1823,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1821
1823
  on=on,
1822
1824
  skip_columns=skip_columns,
1823
1825
  where=where,
1826
+ schema_diff_ignore_case=schema_diff_ignore_case,
1824
1827
  )
1825
1828
  ]
1826
1829
 
@@ -1845,6 +1848,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1845
1848
  show: bool = True,
1846
1849
  temp_schema: t.Optional[str] = None,
1847
1850
  skip_grain_check: bool = False,
1851
+ schema_diff_ignore_case: bool = False,
1848
1852
  ) -> TableDiff:
1849
1853
  self.console.start_table_diff_model_progress(model.name)
1850
1854
 
@@ -1860,6 +1864,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1860
1864
  target=target,
1861
1865
  source_alias=source_alias,
1862
1866
  target_alias=target_alias,
1867
+ schema_diff_ignore_case=schema_diff_ignore_case,
1863
1868
  )
1864
1869
 
1865
1870
  if show:
@@ -1883,6 +1888,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1883
1888
  model: t.Optional[Model] = None,
1884
1889
  skip_columns: t.Optional[t.List[str]] = None,
1885
1890
  where: t.Optional[str | exp.Condition] = None,
1891
+ schema_diff_ignore_case: bool = False,
1886
1892
  ) -> TableDiff:
1887
1893
  if not on:
1888
1894
  raise SQLMeshError(
@@ -1902,6 +1908,7 @@ class GenericContext(BaseContext, t.Generic[C]):
1902
1908
  decimals=decimals,
1903
1909
  model_name=model.name if model else None,
1904
1910
  model_dialect=model.dialect if model else None,
1911
+ schema_diff_ignore_case=schema_diff_ignore_case,
1905
1912
  )
1906
1913
 
1907
1914
  @python_api_analytics
@@ -36,29 +36,78 @@ class SchemaDiff(PydanticModel, frozen=True):
36
36
  source_alias: t.Optional[str] = None
37
37
  target_alias: t.Optional[str] = None
38
38
  model_name: t.Optional[str] = None
39
+ ignore_case: bool = False
40
+
41
+ @property
42
+ def _comparable_source_schema(self) -> t.Dict[str, exp.DataType]:
43
+ return (
44
+ self._lowercase_schema_names(self.source_schema)
45
+ if self.ignore_case
46
+ else self.source_schema
47
+ )
48
+
49
+ @property
50
+ def _comparable_target_schema(self) -> t.Dict[str, exp.DataType]:
51
+ return (
52
+ self._lowercase_schema_names(self.target_schema)
53
+ if self.ignore_case
54
+ else self.target_schema
55
+ )
56
+
57
+ def _lowercase_schema_names(
58
+ self, schema: t.Dict[str, exp.DataType]
59
+ ) -> t.Dict[str, exp.DataType]:
60
+ return {c.lower(): t for c, t in schema.items()}
61
+
62
+ def _original_column_name(
63
+ self, maybe_lowercased_column_name: str, schema: t.Dict[str, exp.DataType]
64
+ ) -> str:
65
+ if not self.ignore_case:
66
+ return maybe_lowercased_column_name
67
+
68
+ return next(c for c in schema if c.lower() == maybe_lowercased_column_name)
39
69
 
40
70
  @property
41
71
  def added(self) -> t.List[t.Tuple[str, exp.DataType]]:
42
72
  """Added columns."""
43
- return [(c, t) for c, t in self.target_schema.items() if c not in self.source_schema]
73
+ return [
74
+ (self._original_column_name(c, self.target_schema), t)
75
+ for c, t in self._comparable_target_schema.items()
76
+ if c not in self._comparable_source_schema
77
+ ]
44
78
 
45
79
  @property
46
80
  def removed(self) -> t.List[t.Tuple[str, exp.DataType]]:
47
81
  """Removed columns."""
48
- return [(c, t) for c, t in self.source_schema.items() if c not in self.target_schema]
82
+ return [
83
+ (self._original_column_name(c, self.source_schema), t)
84
+ for c, t in self._comparable_source_schema.items()
85
+ if c not in self._comparable_target_schema
86
+ ]
49
87
 
50
88
  @property
51
89
  def modified(self) -> t.Dict[str, t.Tuple[exp.DataType, exp.DataType]]:
52
90
  """Columns with modified types."""
53
91
  modified = {}
54
- for column in self.source_schema.keys() & self.target_schema.keys():
55
- source_type = self.source_schema[column]
56
- target_type = self.target_schema[column]
92
+ for column in self._comparable_source_schema.keys() & self._comparable_target_schema.keys():
93
+ source_type = self._comparable_source_schema[column]
94
+ target_type = self._comparable_target_schema[column]
57
95
 
58
96
  if source_type != target_type:
59
97
  modified[column] = (source_type, target_type)
98
+
99
+ if self.ignore_case:
100
+ modified = {
101
+ self._original_column_name(c, self.source_schema): dt for c, dt in modified.items()
102
+ }
103
+
60
104
  return modified
61
105
 
106
+ @property
107
+ def has_changes(self) -> bool:
108
+ """Does the schema contain any changes at all between source and target"""
109
+ return bool(self.added or self.removed or self.modified)
110
+
62
111
 
63
112
  class RowDiff(PydanticModel, frozen=True):
64
113
  """Summary statistics and a sample dataframe."""
@@ -183,6 +232,7 @@ class TableDiff:
183
232
  model_name: t.Optional[str] = None,
184
233
  model_dialect: t.Optional[str] = None,
185
234
  decimals: int = 3,
235
+ schema_diff_ignore_case: bool = False,
186
236
  ):
187
237
  if not isinstance(adapter, RowDiffMixin):
188
238
  raise ValueError(f"Engine {adapter} doesnt support RowDiff")
@@ -198,6 +248,7 @@ class TableDiff:
198
248
  self.model_name = model_name
199
249
  self.model_dialect = model_dialect
200
250
  self.decimals = decimals
251
+ self.schema_diff_ignore_case = schema_diff_ignore_case
201
252
 
202
253
  # Support environment aliases for diff output improvement in certain cases
203
254
  self.source_alias = source_alias
@@ -282,6 +333,7 @@ class TableDiff:
282
333
  source_alias=self.source_alias,
283
334
  target_alias=self.target_alias,
284
335
  model_name=self.model_name,
336
+ ignore_case=self.schema_diff_ignore_case,
285
337
  )
286
338
 
287
339
  def row_diff(
sqlmesh/magics.py CHANGED
@@ -719,6 +719,11 @@ class SQLMeshMagics(Magics):
719
719
  action="store_true",
720
720
  help="Warn if any selected model is missing a grain, and compute diffs for the remaining models.",
721
721
  )
722
+ @argument(
723
+ "--schema-diff-ignore-case",
724
+ action="store_true",
725
+ help="If set, when performing a schema diff the case of column names is ignored when matching between the two schemas. For example, 'col_a' in the source schema and 'COL_A' in the target schema will be treated as the same column.",
726
+ )
722
727
  @line_magic
723
728
  @pass_sqlmesh_context
724
729
  def table_diff(self, context: Context, line: str) -> None:
@@ -741,6 +746,7 @@ class SQLMeshMagics(Magics):
741
746
  decimals=args.decimals,
742
747
  skip_grain_check=args.skip_grain_check,
743
748
  warn_grain_check=args.warn_grain_check,
749
+ schema_diff_ignore_case=args.schema_diff_ignore_case,
744
750
  )
745
751
 
746
752
  @magic_arguments()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.189.3.dev3
3
+ Version: 0.189.3.dev4
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -1,19 +1,19 @@
1
1
  sqlmesh/__init__.py,sha256=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
2
- sqlmesh/_version.py,sha256=pKzjm3VrnB9PVklIfaWHyg684XT3mBrsuVHsWPmteKs,528
3
- sqlmesh/magics.py,sha256=fu7-OeT_0_TAkWZOLoiioE3-3iFpvTRxFCbQUlRnfuw,39944
2
+ sqlmesh/_version.py,sha256=fNcv8X4icZbzzufuP98drtnhKQUu7Aja4LbO_pX80YQ,528
3
+ sqlmesh/magics.py,sha256=gjzoxREb1XT8Yho_PQMlMqhhkLq_sEfBM8S3PTgxvWE,40337
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  sqlmesh/cicd/bot.py,sha256=2zlbn-DXkqQzr3lA0__IGU4XaIfXBXBKLWXNI2DRJX8,759
7
7
  sqlmesh/cicd/config.py,sha256=mpgkisSBBovlNrNZir2unT8Wes6b38RW2UsU_o4e8vY,109
8
8
  sqlmesh/cli/__init__.py,sha256=MAXAyO7isbyM-PaSdFjkJNcjn32WjOl0XzxT5gvp_vo,1690
9
9
  sqlmesh/cli/example_project.py,sha256=QAFQbw_kzqn30GLTthqsuWXbFDBpX8W6RsCgQ-jx65M,9308
10
- sqlmesh/cli/main.py,sha256=gk2iNJ3trprWtVpqGafbaCubYR3U6ByoacwZGFubRPM,32434
10
+ sqlmesh/cli/main.py,sha256=7gTwG_atQFhb211oH3JNoMfrm1UU0XXTPSOXWyzDIDE,32738
11
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=x7qWETjHgu8ZpMtfW8V3bGKByT4nZXDjgtO6xmvAb-I,151143
15
15
  sqlmesh/core/constants.py,sha256=oqt6zjepUhQoWlgapKn_HpG7Pu9mrFwepdX5caNfJUI,2499
16
- sqlmesh/core/context.py,sha256=4ybOWvPPN05FDlBIVjSL8_uPNvlHT-tfrvGbvIGlziI,117323
16
+ sqlmesh/core/context.py,sha256=u05rMOVPd8LvpTRrs6W5IiyT7cdjtHDIXBGqIthwFRI,117732
17
17
  sqlmesh/core/context_diff.py,sha256=I7luvY2za30E5ynVaFPaEQQEmNViJpWAmW48PGSyDCU,21135
18
18
  sqlmesh/core/dialect.py,sha256=93cXYVuNoZ9CvJNTVn2Yz7WDOdHINwVXflbn0eZ-p14,49764
19
19
  sqlmesh/core/environment.py,sha256=bNj-JCG_l13dwrp--YPIuGNsuWLTMLcFA5sY8IazVK8,12917
@@ -29,7 +29,7 @@ sqlmesh/core/schema_diff.py,sha256=Sp2MoqAngp-yTYevkLaf9jb26SuAdGXoZ54g5MjWowU,3
29
29
  sqlmesh/core/schema_loader.py,sha256=lvrI9k7hr1P4X4E6t3U-KrcuvdQuw0UdNlN90P2s52w,3563
30
30
  sqlmesh/core/selector.py,sha256=_hcktUQiKXCPE-mOqXClHUVWBfEZKMPVVNDtpSSRhbI,12660
31
31
  sqlmesh/core/signal.py,sha256=yVLXewYP6eH0vt-EwaIaI2WwHz6hWsVr-Kb2m4kP1FU,1353
32
- sqlmesh/core/table_diff.py,sha256=Bf2rqDuxqU-7Z4T_YhKT2RG7CU7DsGbOTE4aglCLJ74,25335
32
+ sqlmesh/core/table_diff.py,sha256=6J-C3Vr2Aw02t3VXJwFPjazao-yv92jHgYZ31Iok_6A,27133
33
33
  sqlmesh/core/user.py,sha256=EJ6R4R1iK67n80vBoCCsidF56IR7xEYqiCEO-nrVMso,1660
34
34
  sqlmesh/core/analytics/__init__.py,sha256=ou3ZXAJfQOXEifj-PzaXwMDSvJzsVaqaMkUopiI00kM,3247
35
35
  sqlmesh/core/analytics/collector.py,sha256=sggJvER16Jrg5triTC27E2KwaQvfkVDv4D6R1lVPH5I,13058
@@ -274,7 +274,7 @@ sqlmesh/utils/pydantic.py,sha256=I898jAFqa3qU6lG2uPpRebVFncOUo8ZrLWM_R3K3DHU,116
274
274
  sqlmesh/utils/rich.py,sha256=xNZyPCqEc4TAlJlsEthg-5eYUWpaizz0QjBzO7a1Yv4,1509
275
275
  sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
276
276
  sqlmesh/utils/yaml.py,sha256=np-WVcwmwsKghCgAj1OBBMsK1SXSRn4wR-H37cGiFr8,2282
277
- sqlmesh-0.189.3.dev3.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
277
+ sqlmesh-0.189.3.dev4.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
278
278
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
279
279
  web/client/dist/index.html,sha256=LbR9XrOXE77otBPoDnaomssYz6h2TBwLANs6hUJ0p2M,5472
280
280
  web/client/dist/assets/Audits-DB1HcP9M.js,sha256=eGI_Soj69Jntsixw1NqQpdwG94N5jipQZv7T1Y7WUSs,1041
@@ -392,8 +392,8 @@ web/server/api/endpoints/models.py,sha256=ud-lRwriyI_OYg9tZchrBgeiXELiRTLNEodraf
392
392
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
393
393
  web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
394
394
  web/server/api/endpoints/table_diff.py,sha256=SCy3-pr5x6bEEiOaZGCDbiHQhpgxwmnz3Acqa2Ie6jI,2090
395
- sqlmesh-0.189.3.dev3.dist-info/METADATA,sha256=XKqwa4k6Rj_1_aONy7NCKKXeiu8jf58mwwASUKOLZXk,26540
396
- sqlmesh-0.189.3.dev3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
397
- sqlmesh-0.189.3.dev3.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
398
- sqlmesh-0.189.3.dev3.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
399
- sqlmesh-0.189.3.dev3.dist-info/RECORD,,
395
+ sqlmesh-0.189.3.dev4.dist-info/METADATA,sha256=ucewPywn7voeI8iiYmkUoBYsF-IZwlYFlT-EeUoK7kU,26540
396
+ sqlmesh-0.189.3.dev4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
397
+ sqlmesh-0.189.3.dev4.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
398
+ sqlmesh-0.189.3.dev4.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
399
+ sqlmesh-0.189.3.dev4.dist-info/RECORD,,