Skip to content

Commit b0862ae

Browse files
authored
fix(dialect): make extend_sqlglot idempotent (#5921)
Signed-off-by: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com>
1 parent f72a858 commit b0862ae

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

sqlmesh/core/dialect.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,10 @@ def _parse_interval_span(self: Parser, this: exp.Expr) -> exp.Interval:
812812

813813
def _override(klass: t.Type[Tokenizer | Parser | Generator], func: t.Callable) -> None:
814814
name = func.__name__
815+
if getattr(klass, name, None) is func:
816+
# Already overridden. Re-applying would save the override itself as the
817+
# "original", making the wrapper call itself and recurse infinitely.
818+
return
815819
setattr(klass, f"_{name}", getattr(klass, name))
816820
setattr(klass, name, func)
817821

@@ -1200,11 +1204,12 @@ def extend_sqlglot() -> None:
12001204
MacroDef,
12011205
)
12021206

1203-
generator.UNWRAPPED_INTERVAL_VALUES = (
1204-
*generator.UNWRAPPED_INTERVAL_VALUES,
1205-
MacroStrReplace,
1206-
MacroVar,
1207-
)
1207+
if MacroVar not in generator.UNWRAPPED_INTERVAL_VALUES:
1208+
generator.UNWRAPPED_INTERVAL_VALUES = (
1209+
*generator.UNWRAPPED_INTERVAL_VALUES,
1210+
MacroStrReplace,
1211+
MacroVar,
1212+
)
12081213

12091214
_override(Parser, _parse_select)
12101215
_override(Parser, _parse_statement)

tests/core/test_dialect.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,3 +1217,17 @@ def test_pipe_syntax():
12171217
ast.sql("bigquery")
12181218
== "SELECT * FROM (WITH __tmp1 AS (SELECT id FROM t2) SELECT * FROM __tmp1)"
12191219
)
1220+
1221+
1222+
def test_extend_sqlglot_is_idempotent():
1223+
# extend_sqlglot() runs at import time; calling it again must not re-wrap the
1224+
# already-installed overrides, otherwise they call themselves (RecursionError).
1225+
from sqlglot.generator import Generator
1226+
1227+
before = Generator.UNWRAPPED_INTERVAL_VALUES
1228+
1229+
d.extend_sqlglot()
1230+
1231+
assert parse_one("SELECT CAST(1 AS INT)").sql() == "SELECT CAST(1 AS INT)"
1232+
# The class-level registries must not grow on repeated calls.
1233+
assert Generator.UNWRAPPED_INTERVAL_VALUES == before

0 commit comments

Comments
 (0)