6262
6363if t .TYPE_CHECKING :
6464 from sqlglot .dialects .dialect import DialectType
65+ from sqlmesh .core .node import _Node
6566 from sqlmesh .core ._typing import Self , TableName , SessionProperties
6667 from sqlmesh .core .context import ExecutionContext
6768 from sqlmesh .core .engine_adapter import EngineAdapter
@@ -1278,6 +1279,7 @@ class SqlModel(_Model):
12781279 source_type : t .Literal ["sql" ] = "sql"
12791280
12801281 _columns_to_types : t .Optional [t .Dict [str , exp .DataType ]] = None
1282+ _is_metadata_only_change_cache : t .Dict [int , bool ] = {}
12811283
12821284 def __getstate__ (self ) -> t .Dict [t .Any , t .Any ]:
12831285 state = super ().__getstate__ ()
@@ -1500,6 +1502,27 @@ def is_breaking_change(self, previous: Model) -> t.Optional[bool]:
15001502
15011503 return False
15021504
1505+ def is_metadata_only_change (self , previous : _Node ) -> bool :
1506+ if self ._is_metadata_only_change_cache .get (id (previous ), None ) is not None :
1507+ return self ._is_metadata_only_change_cache [id (previous )]
1508+
1509+ if (
1510+ not isinstance (previous , SqlModel )
1511+ or self .metadata_hash == previous .metadata_hash
1512+ or self ._data_hash_values_no_query != previous ._data_hash_values_no_query
1513+ ):
1514+ is_metadata_change = False
1515+ else :
1516+ # If the rendered queries are the same, then this is a metadata only change
1517+ this_rendered_query = self .render_query ()
1518+ previous_rendered_query = previous .render_query ()
1519+ is_metadata_change = (
1520+ this_rendered_query is not None and this_rendered_query == previous_rendered_query
1521+ )
1522+
1523+ self ._is_metadata_only_change_cache [id (previous )] = is_metadata_change
1524+ return is_metadata_change
1525+
15031526 @cached_property
15041527 def _query_renderer (self ) -> QueryRenderer :
15051528 no_quote_identifiers = self .kind .is_view and self .dialect in ("trino" , "spark" )
@@ -1519,17 +1542,22 @@ def _query_renderer(self) -> QueryRenderer:
15191542 )
15201543
15211544 @property
1522- def _data_hash_values (self ) -> t .List [str ]:
1523- data = super ()._data_hash_values
1545+ def _data_hash_values_no_query (self ) -> t .List [str ]:
1546+ return [
1547+ * super ()._data_hash_values ,
1548+ * self .jinja_macros .data_hash_values ,
1549+ ]
15241550
1525- query = self .render_query () or self .query
1526- data .append (gen (query ))
1527- data .extend (self .jinja_macros .data_hash_values )
1528- return data
1551+ @property
1552+ def _data_hash_values (self ) -> t .List [str ]:
1553+ return [
1554+ * self ._data_hash_values_no_query ,
1555+ gen (self .query , comments = False ),
1556+ ]
15291557
15301558 @property
15311559 def _additional_metadata (self ) -> t .List [str ]:
1532- return [* super ()._additional_metadata , gen (self .query )]
1560+ return [* super ()._additional_metadata , gen (self .query , comments = True )]
15331561
15341562 @property
15351563 def violated_rules_for_query (self ) -> t .Dict [type [Rule ], t .Any ]:
0 commit comments