From a2d483b9b126c720cd30a3087022338a7b645155 Mon Sep 17 00:00:00 2001 From: neatninja Date: Sun, 4 Oct 2026 18:52:36 +0530 Subject: [PATCH] fix(dialect): don't parse @@ system variables as macros The macro parser treated the second @ in @@DATEFIRST as the start of a macro variable, so T-SQL configuration functions like @@DATEFIRST and BigQuery's @@query_label became a MacroVar and the model failed to render with "Unsupported expression type MacroVar". @@name is now parsed as a system variable, the same way the dialect parses it. Signed-off-by: neatninja --- sqlmesh/core/dialect.py | 5 +++++ tests/core/test_dialect.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/sqlmesh/core/dialect.py b/sqlmesh/core/dialect.py index bcfb300ba1..5484da4efa 100644 --- a/sqlmesh/core/dialect.py +++ b/sqlmesh/core/dialect.py @@ -218,6 +218,11 @@ def _parse_macro(self: Parser, keyword_macro: str = "") -> t.Optional[exp.Expr]: if self._prev.text != SQLMESH_MACRO_PREFIX: return self._parse_parameter() + # @@name is a system variable, e.g. T-SQL's @@DATEFIRST or BigQuery's @@query_label, + # and can't be a macro reference, so parse it like the dialect would + if self._curr and self._curr.text == SQLMESH_MACRO_PREFIX and self._match(TokenType.PARAMETER): + return self.expression(exp.Parameter(this=self._parse_parameter())) + comments = self._prev.comments index = self._index field = self._parse_primary() or self._parse_function(functions={}) or self._parse_id_var() diff --git a/tests/core/test_dialect.py b/tests/core/test_dialect.py index 8d19ffee36..8a14863b84 100644 --- a/tests/core/test_dialect.py +++ b/tests/core/test_dialect.py @@ -1324,6 +1324,38 @@ def test_macro_parse(): ) +@pytest.mark.parametrize( + "dialect, sql", + [ + ("tsql", "SELECT @@DATEFIRST AS x"), + ("bigquery", "SELECT @@query_label AS x"), + ("mysql", "SELECT @@session.time_zone AS x"), + ], +) +def test_double_at_system_variable_is_not_a_macro(dialect: str, sql: str): + query = parse_one(sql, read=dialect) + assert not list(query.find_all(d.MacroVar)) + assert query.sql(dialect) == sql + + +def test_double_at_system_variable_in_model(): + model = load_sql_based_model( + parse( + """ + MODEL (name db.m, dialect tsql); + SELECT (DATEPART(WEEKDAY, d) + @@DATEFIRST - 2) % 7 + 1 AS iso_weekday, @x AS x FROM t + """, + default_dialect="tsql", + ), + dialect="tsql", + variables={"x": 1}, + ) + assert model.render_query_or_raise().sql("tsql") == ( + "SELECT (DATEPART(WEEKDAY, [d]) + @@DATEFIRST - 2) % 7 + 1 AS [iso_weekday], 1 AS [x] " + "FROM [t] AS [t]" + ) + + def test_conditional_statement(): q = parse_one( """