Skip to content

Commit 97e9db2

Browse files
committed
fix: Swap parser override order for macro IF under T-SQL (Issue #5823)
Signed-off-by: Jagan Nalla <jagannalla1@gmail.com>
1 parent d15203b commit 97e9db2

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

sqlmesh/core/dialect.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,10 @@ def _parse_if(self: Parser) -> t.Optional[exp.Expr]:
556556
# to parse a statement / command to support the macro @IF(condition, statement)
557557
index = self._index
558558
try:
559+
if self.dialect == "tsql":
560+
if not (self._index >= 2 and self._tokens[self._index - 2].text == "@"):
561+
return self.__parse_if() # type: ignore
562+
return Parser.__parse_if(self) # type: ignore
559563
return self.__parse_if() # type: ignore
560564
except ParseError:
561565
self._retreat(index)
@@ -1123,8 +1127,8 @@ def extend_sqlglot() -> None:
11231127
_override(Parser, _parse_value)
11241128
_override(Parser, _parse_lambda)
11251129
_override(Parser, _parse_types)
1126-
_override(TSQL.Parser, Parser._parse_if)
11271130
_override(Parser, _parse_if)
1131+
_override(TSQL.Parser, Parser._parse_if)
11281132
_override(Parser, _parse_id_var)
11291133
_override(Parser, _warn_unsupported)
11301134
_override(Snowflake.Parser, _parse_table_parts)

tests/core/test_dialect.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,20 @@ def test_conditional_statement():
707707
q = parse_one("@IF(cond, VACUUM ANALYZE);", read="postgres")
708708
assert q.sql(dialect="postgres") == "@IF(cond, VACUUM ANALYZE)"
709709

710+
# Verify that the original error case from issue #5823 (Required keyword: 'true' missing) is resolved.
711+
# It must be parsed as a macro function containing an Anonymous expression rather than exp.If.
712+
q = parse_one("@IF(1 = 1, ALTER TABLE x ADD y INT);", read="tsql")
713+
assert q.sql(dialect="tsql") == "@IF(1 = 1, ALTER TABLE x ADD y INTEGER)"
714+
assert isinstance(q.this, exp.Anonymous)
715+
assert q.this.name == "IF"
716+
717+
# Note: SQLGlot's fallback Command parser strips quotes from string literal tokens when parsing unparsed commands
718+
q = parse_one("@IF(cond, PRINT 'hello');", read="tsql")
719+
assert q.sql(dialect="tsql") == "@IF(cond, PRINT hello)"
720+
721+
q = parse_one("@IF(@runtime_stage = 'evaluating', SELECT 1);", read="tsql")
722+
assert q.sql(dialect="tsql") == "@IF(@runtime_stage = 'evaluating', SELECT 1)"
723+
710724

711725
def test_model_name_cannot_be_string():
712726
with pytest.raises(ParseError) as parse_error:

0 commit comments

Comments
 (0)