Skip to content

Commit 0e9c8a0

Browse files
authored
Fix!: don't consume connected tokens when parsing quoted identifiers (#5357)
1 parent 26ebace commit 0e9c8a0

File tree

6 files changed

+18
-9
lines changed

6 files changed

+18
-9
lines changed

sqlmesh/core/dialect.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def _parse_id_var(
174174

175175
while (
176176
identifier
177+
and not identifier.args.get("quoted")
177178
and self._is_connected()
178179
and (
179180
self._match_texts(("{", SQLMESH_MACRO_PREFIX))

sqlmesh/core/macros.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ def haversine_distance(
11281128
def pivot(
11291129
evaluator: MacroEvaluator,
11301130
column: SQL,
1131-
values: t.List[SQL],
1131+
values: t.List[exp.Expression],
11321132
alias: bool = True,
11331133
agg: exp.Expression = exp.Literal.string("SUM"),
11341134
cmp: exp.Expression = exp.Literal.string("="),
@@ -1146,23 +1146,23 @@ def pivot(
11461146
>>> from sqlmesh.core.macros import MacroEvaluator
11471147
>>> sql = "SELECT date_day, @PIVOT(status, ['cancelled', 'completed']) FROM rides GROUP BY 1"
11481148
>>> MacroEvaluator().transform(parse_one(sql)).sql()
1149-
'SELECT date_day, SUM(CASE WHEN status = \\'cancelled\\' THEN 1 ELSE 0 END) AS "\\'cancelled\\'", SUM(CASE WHEN status = \\'completed\\' THEN 1 ELSE 0 END) AS "\\'completed\\'" FROM rides GROUP BY 1'
1149+
'SELECT date_day, SUM(CASE WHEN status = \\'cancelled\\' THEN 1 ELSE 0 END) AS "cancelled", SUM(CASE WHEN status = \\'completed\\' THEN 1 ELSE 0 END) AS "completed" FROM rides GROUP BY 1'
11501150
>>> sql = "SELECT @PIVOT(a, ['v'], then_value := tv, suffix := '_sfx', quote := FALSE)"
11511151
>>> MacroEvaluator(dialect="bigquery").transform(parse_one(sql)).sql("bigquery")
1152-
"SELECT SUM(CASE WHEN a = 'v' THEN tv ELSE 0 END) AS `v_sfx`"
1152+
"SELECT SUM(CASE WHEN a = 'v' THEN tv ELSE 0 END) AS v_sfx"
11531153
"""
11541154
aggregates: t.List[exp.Expression] = []
11551155
for value in values:
11561156
proj = f"{agg.name}("
11571157
if distinct:
11581158
proj += "DISTINCT "
11591159

1160-
proj += f"CASE WHEN {column} {cmp.name} {value} THEN {then_value} ELSE {else_value} END) "
1160+
proj += f"CASE WHEN {column} {cmp.name} {value.sql(evaluator.dialect)} THEN {then_value} ELSE {else_value} END) "
11611161
node = evaluator.parse_one(proj)
11621162

11631163
if alias:
11641164
node = node.as_(
1165-
f"{prefix.name}{value}{suffix.name}",
1165+
f"{prefix.name}{value.name}{suffix.name}",
11661166
quoted=quote,
11671167
copy=False,
11681168
dialect=evaluator.dialect,

sqlmesh/core/snapshot/evaluator.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,10 @@ def _migrate_target_table(
11101110
) -> None:
11111111
adapter = self.get_adapter(snapshot.model.gateway)
11121112

1113-
tmp_table_name = f"{target_table_name}_schema_tmp"
1113+
target_table = exp.to_table(target_table_name)
1114+
target_table.this.set("this", f"{target_table.name}_schema_tmp")
1115+
1116+
tmp_table_name = target_table.sql()
11141117
if snapshot.is_materialized:
11151118
self._execute_create(
11161119
snapshot=snapshot,

tests/core/engine_adapter/test_clickhouse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ def test_scd_type_2_by_time(
640640
"test_valid_from",
641641
"test_valid_to",
642642
TRUE AS "_exists"
643-
FROM ""__temp_target_efgh""
643+
FROM "__temp_target_efgh"
644644
WHERE
645645
NOT "test_valid_to" IS NULL
646646
), "latest" AS (
@@ -652,7 +652,7 @@ def test_scd_type_2_by_time(
652652
"test_valid_from",
653653
"test_valid_to",
654654
TRUE AS "_exists"
655-
FROM ""__temp_target_efgh""
655+
FROM "__temp_target_efgh"
656656
WHERE
657657
"test_valid_to" IS NULL
658658
), "deleted" AS (

tests/core/test_dialect.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,3 +717,8 @@ def test_sqlglot_extended_correctly(dialect: str) -> None:
717717
assert isinstance(value, exp.Table)
718718
assert value.sql() == "foo"
719719
assert ast.sql(dialect=dialect) == "MODEL (\nname foo\n)"
720+
721+
722+
def test_connected_identifier():
723+
ast = d.parse_one("""SELECT ("x"at time zone 'utc')::timestamp as x""", "redshift")
724+
assert ast.sql("redshift") == """SELECT CAST(("x" AT TIME ZONE 'utc') AS TIMESTAMP) AS x"""

tests/core/test_format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_format_files(tmp_path: pathlib.Path, mocker: MockerFixture):
2828
f3 = create_temp_file(
2929
tmp_path,
3030
pathlib.Path(audits_dir, "audit_1.sql"),
31-
"AUDIT(name assert_positive_id, dialect 'duckdb'); SELECT * FROM @this_model WHERE \"CaseSensitive\"_item_id < 0;",
31+
"AUDIT(name assert_positive_id, dialect 'duckdb'); SELECT * FROM @this_model WHERE \"CaseSensitive_item_id\" < 0;",
3232
)
3333
f4 = create_temp_file(
3434
tmp_path,

0 commit comments

Comments
 (0)