diff --git a/sqlmesh/core/engine_adapter/snowflake.py b/sqlmesh/core/engine_adapter/snowflake.py index a8eabe070d..09fa06aa26 100644 --- a/sqlmesh/core/engine_adapter/snowflake.py +++ b/sqlmesh/core/engine_adapter/snowflake.py @@ -622,6 +622,12 @@ def catalog_rewriter(node: exp.Expression) -> exp.Expression: return expression def _to_sql(self, expression: exp.Expression, quote: bool = True, **kwargs: t.Any) -> str: + # Snowflake doesn't accept quoted identifiers in ALTER SESSION SET statements + # e.g., ALTER SESSION SET "TIMEZONE" = 'UTC' is invalid + # We need to disable quoting for these statements + if isinstance(expression, (exp.Set, exp.Alter)): + quote = False + return super()._to_sql( expression=self._normalize_catalog(expression), quote=quote, **kwargs ) diff --git a/sqlmesh/core/renderer.py b/sqlmesh/core/renderer.py index 0cbf9b6e94..26ad90ab98 100644 --- a/sqlmesh/core/renderer.py +++ b/sqlmesh/core/renderer.py @@ -419,7 +419,14 @@ def _expand(node: exp.Expression) -> exp.Expression: @contextmanager def _normalize_and_quote(self, query: E) -> t.Iterator[E]: - if self._normalize_identifiers: + # Snowflake doesn't accept quoted identifiers in ALTER SESSION SET statements + # e.g., ALTER SESSION SET "TIMEZONE" = 'UTC' is invalid + # SQLGlot parses "ALTER SESSION SET" as exp.Alter, not exp.Set + # We need to skip both normalization and quoting for these statements + # because quote_identifiers() modifies the AST directly and quotes persist + if self._dialect == "snowflake" and isinstance(query, (exp.Set, exp.Alter)): + yield query + elif self._normalize_identifiers: with d.normalize_and_quote( query, self._dialect, self._default_catalog, quote=self._quote_identifiers ) as query: