diff --git a/sqlmesh/core/dialect.py b/sqlmesh/core/dialect.py index 2ac15c2a5c..add30d1189 100644 --- a/sqlmesh/core/dialect.py +++ b/sqlmesh/core/dialect.py @@ -774,7 +774,8 @@ def format_model_expressions( if rewrite_casts: def cast_to_colon(node: exp.Expr) -> exp.Expr: - if isinstance(node, exp.Cast) and not any( + # Directly check type instead of isinstance to avoid rewriting subclasses of CAST, e.g. JSONCast + if type(node) is exp.Cast and not any( # Only convert CAST into :: if it doesn't have additional args set, otherwise this # conversion could alter the semantics (eg. changing SAFE_CAST in BigQuery to CAST) arg diff --git a/tests/core/test_dialect.py b/tests/core/test_dialect.py index 02068b1c59..3b8df28f8b 100644 --- a/tests/core/test_dialect.py +++ b/tests/core/test_dialect.py @@ -207,6 +207,29 @@ def test_format_model_expressions(): SAFE_CAST('bla' AS INT64) AS FOO""" ) + x = format_model_expressions( + parse( + """ + MODEL(name a.b, kind FULL, dialect clickhouse); + SELECT data.:String AS foo, CAST(1 AS INT) AS bar + """ + ), + dialect="clickhouse", + ) + # JSONCast (e.g. `.:` syntax in ClickHouse) must not be written to `::` + assert ( + x + == """MODEL ( + name a.b, + kind FULL, + dialect clickhouse +); + +SELECT + data.:String AS foo, + 1::Int32 AS bar""" + ) + x = format_model_expressions( parse( """