@@ -36,29 +36,78 @@ class SchemaDiff(PydanticModel, frozen=True):
3636 source_alias : t .Optional [str ] = None
3737 target_alias : t .Optional [str ] = None
3838 model_name : t .Optional [str ] = None
39+ ignore_case : bool = False
40+
41+ @property
42+ def _normalized_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 _normalized_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 )
3969
4070 @property
4171 def added (self ) -> t .List [t .Tuple [str , exp .DataType ]]:
4272 """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 ._normalized_target_schema .items ()
76+ if c not in self ._normalized_source_schema
77+ ]
4478
4579 @property
4680 def removed (self ) -> t .List [t .Tuple [str , exp .DataType ]]:
4781 """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 ._normalized_source_schema .items ()
85+ if c not in self ._normalized_target_schema
86+ ]
4987
5088 @property
5189 def modified (self ) -> t .Dict [str , t .Tuple [exp .DataType , exp .DataType ]]:
5290 """Columns with modified types."""
5391 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 ._normalized_source_schema .keys () & self ._normalized_target_schema .keys ():
93+ source_type = self ._normalized_source_schema [column ]
94+ target_type = self ._normalized_target_schema [column ]
5795
5896 if source_type != target_type :
5997 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+
60104 return modified
61105
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+
62111
63112class RowDiff (PydanticModel , frozen = True ):
64113 """Summary statistics and a sample dataframe."""
@@ -183,6 +232,7 @@ def __init__(
183232 model_name : t .Optional [str ] = None ,
184233 model_dialect : t .Optional [str ] = None ,
185234 decimals : int = 3 ,
235+ schema_diff_ignore_case : bool = False ,
186236 ):
187237 if not isinstance (adapter , RowDiffMixin ):
188238 raise ValueError (f"Engine { adapter } doesnt support RowDiff" )
@@ -198,6 +248,7 @@ def __init__(
198248 self .model_name = model_name
199249 self .model_dialect = model_dialect
200250 self .decimals = decimals
251+ self .schema_diff_ignore_case = schema_diff_ignore_case
201252
202253 # Support environment aliases for diff output improvement in certain cases
203254 self .source_alias = source_alias
@@ -282,6 +333,7 @@ def schema_diff(self) -> SchemaDiff:
282333 source_alias = self .source_alias ,
283334 target_alias = self .target_alias ,
284335 model_name = self .model_name ,
336+ ignore_case = self .schema_diff_ignore_case ,
285337 )
286338
287339 def row_diff (
0 commit comments