Skip to content

fix(snowflake): do not quote parameter names in ALTER SESSION - #6122

Open
DG47 wants to merge 5 commits into
SQLMesh:mainfrom
DG47:fix/snowflake-alter-session-quoting
Open

DG47 wants to merge 5 commits into
SQLMesh:mainfrom
DG47:fix/snowflake-alter-session-quoting

Conversation

@DG47

@DG47 DG47 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #5666.

Snowflake session parameters (TIMEZONE, QUERY_TAG, ...) are keywords, not identifiers, so ALTER SESSION SET "TIMEZONE" = 'UTC' is a syntax error. sqlglot parses the parameter names in ALTER SESSION SET/UNSET as identifiers (Column(Identifier) / Identifier), so a model pre/post statement such as

ALTER SESSION SET TIMEZONE = 'UTC';

was quoted twice: once by the renderer's normalize-and-quote step and again by EngineAdapter._to_sql. It reached Snowflake as ALTER SESSION SET "TIMEZONE" = 'UTC'.

This adds a small parser override in sqlmesh/core/dialect.py, following the same pattern as the existing T-SQL ALTER COLUMN override. After sqlglot parses ALTER SESSION, unquoted parameter names become exp.Var, so they are neither normalized nor quoted. Values are left alone (literals, macros such as @tag, etc.), and so are parameter names the user quoted explicitly.

The SQL produced for the unrendered statement doesn't change (TIMEZONE = 'UTC' both before and after), so model data and metadata hashes stay the same and existing snapshots aren't affected. I checked this on a sample model.

An earlier attempt (#5670) turned quoting off for every Alter/Set statement in the Snowflake adapter and also special-cased the renderer. Its author closed it. This change only touches ALTER SESSION parameter names and lives at the parse level, so the renderer and the engine adapter both pick it up without engine-specific code in either.

Test Plan

  • tests/core/test_dialect.py::test_snowflake_alter_session_parameters_are_not_quoted: parse/generate with identify=True for SET (with a macro value), UNSET, and an explicitly quoted name, plus rendered model pre/post statements.
  • tests/core/engine_adapter/test_snowflake.py::test_alter_session_parameters_are_not_quoted: SQL executed by the mocked Snowflake adapter.
  • Both tests fail on main (ALTER SESSION SET "TIMEZONE" = 'UTC') and pass with the fix.
  • pytest -n 8 -m "fast and not web and not github and not dbt and not jupyter and not cicdonly and not isolated": 2436 passed. 6 failures in tests/core/test_connection_config.py (pyodbc) are unrelated and come from a missing local unixODBC library; they fail the same way on main.
  • pytest -m "dbt and fast" tests/dbt: 88 passed.
  • SKIP=prettier,eslint pre-commit run --all-files (ruff, ruff-format, mypy, migrations): passed. The prettier/eslint hooks were skipped because no frontend files changed.

Checklist

  • I have run make style and fixed any issues
  • I have added tests for my changes (if applicable)
  • All existing tests pass (make fast-test) (I ran the core fast and dbt fast subsets listed above, not the whole target)
  • My commits are signed off (git commit -s) per the DCO

DG47 and others added 3 commits October 8, 2026 06:39
Session parameters such as TIMEZONE or QUERY_TAG are keywords, not
identifiers, so Snowflake rejects them when quoted. sqlglot parses them
as identifiers, which means model pre/post statements like
ALTER SESSION SET TIMEZONE = 'UTC' were rendered and executed as
ALTER SESSION SET "TIMEZONE" = 'UTC', a syntax error.

Parse unquoted parameter names in ALTER SESSION SET/UNSET as vars so
they are neither normalized nor quoted.

Fixes SQLMesh#5666

Signed-off-by: Dhruv Gupta <dg@usesparx.com>
…ession-quoting

# Conflicts:
#	tests/core/engine_adapter/test_snowflake.py

@Vamsi-klu Vamsi-klu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, doing this at parse time is a lot cleaner than the adapter + renderer route from #5670. I double checked the hash claim: a Snowflake model with ALTER SESSION SET TIMEZONE = 'UTC', query_tag = 'x' as a pre statement has the same data and metadata hash on main and on this branch, only the rendered SQL changes. One scoping nit inline, looks good otherwise.

Comment thread sqlmesh/core/dialect.py Outdated
_override(Parser, _parse_interval_span)
_override(Parser, _warn_unsupported)
_override(Snowflake.Parser, _parse_table_parts)
_override(Parser, _parse_alter_session)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On sqlglot 30.8 only the Snowflake parser sends ALTER SESSION to _parse_alter_session, Oracle and Databricks still end up as Command. So it's Snowflake only in practice, but overriding the base Parser makes it read as global. Could this be _override(Snowflake.Parser, _parse_alter_session) like the _parse_table_parts one above? Keeps the scope obvious and won't quietly pick up other dialects if sqlglot routes them here later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, done in 637af55: the override is now registered on Snowflake.Parser next to _parse_table_parts, and the function is annotated accordingly. I checked that Databricks and Oracle still come out as Command with the original text untouched.

Comment thread sqlmesh/core/dialect.py
if isinstance(name, exp.Column) and not name.table:
name = name.this
if isinstance(name, exp.Identifier) and not name.quoted:
name.replace(exp.var(name.name))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, no change needed: since these are Vars now they don't get normalized, so query_tag stays lowercase where main uppercased it. Snowflake doesn't care about case for parameter names so it's harmless, but maybe worth a line in the comment above so nobody "fixes" it later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a sentence to the comment in the same commit explaining that vars skip case normalization, that query_tag therefore stays lowercase, and that Snowflake treats parameter names case-insensitively so this is intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

quoting parameters in ALTER SESSION SET for Snowflake is illegal syntax.

2 participants