diff --git a/sqlmesh/core/dialect.py b/sqlmesh/core/dialect.py index ac34f6b1be..ac31df4196 100644 --- a/sqlmesh/core/dialect.py +++ b/sqlmesh/core/dialect.py @@ -12,6 +12,7 @@ from sqlglot import Dialect, Generator, ParseError, Parser, Tokenizer, TokenType, exp from sqlglot.dialects.dialect import DialectType from sqlglot.dialects.snowflake import Snowflake +from sqlglot.helper import seq_get from sqlglot.optimizer.normalize_identifiers import normalize_identifiers from sqlglot.optimizer.qualify_columns import quote_identifiers from sqlglot.optimizer.qualify_tables import qualify_tables @@ -449,14 +450,22 @@ def _create_parser(parser_type: t.Type[exp.Expression], table_keys: t.List[str]) def parse(self: Parser) -> t.Optional[exp.Expression]: from sqlmesh.core.model.kind import ModelKindName - expressions = [] + expressions: t.List[exp.Expression] = [] while True: - key_expression = self._parse_id_var(any_token=True) + prev_property = seq_get(expressions, -1) + if not self._match(TokenType.COMMA, expression=prev_property) and expressions: + break + key_expression = self._parse_id_var(any_token=True) if not key_expression: break + # This allows macro functions that programmaticaly generate the property key-value pair + if isinstance(key_expression, MacroFunc): + expressions.append(key_expression) + continue + key = key_expression.name.lower() start = self._curr @@ -501,9 +510,6 @@ def parse(self: Parser) -> t.Optional[exp.Expression]: expressions.append(self.expression(exp.Property, this=key, value=value)) - if not self._match(TokenType.COMMA, expression=expressions[-1]): - break - return self.expression(parser_type, expressions=expressions) return parse diff --git a/tests/core/test_model.py b/tests/core/test_model.py index 99609e22c3..e4b087f297 100644 --- a/tests/core/test_model.py +++ b/tests/core/test_model.py @@ -3952,6 +3952,13 @@ def test_this_model() -> None: def test_macros_in_model_statement(sushi_context, assert_exp_eq): + @macro() + def session_properties(evaluator, value): + return exp.Property( + this=exp.var("session_properties"), + value=exp.convert([exp.convert("foo").eq(exp.var(f"bar_{value}"))]), + ) + expressions = d.parse( """ MODEL ( @@ -3960,7 +3967,8 @@ def test_macros_in_model_statement(sushi_context, assert_exp_eq): time_column @{time_column} ), - start @IF(@gateway = 'test_gateway', '2023-01-01', '2024-01-02') + start @IF(@gateway = 'test_gateway', '2023-01-01', '2024-01-02'), + @session_properties(baz) ); SELECT a, b UNION SELECT c, c @@ -3974,6 +3982,7 @@ def test_macros_in_model_statement(sushi_context, assert_exp_eq): assert model.time_column assert model.time_column.column == exp.column("a", quoted=True) assert model.start == "2023-01-01" + assert model.session_properties == {"foo": exp.column("bar_baz", quoted=False)} def test_python_model_dialect():