Skip to content

Commit a4d5034

Browse files
authored
Fix: avoid parsing column names into qualified columns in InsertOverwriteWithMergeMixin (#3211)
1 parent eda0085 commit a4d5034

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

sqlmesh/core/engine_adapter/mixins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def _insert_overwrite_by_condition(
8989
for source_query in source_queries:
9090
with source_query as query:
9191
query = self._order_projections_and_filter(query, columns_to_types, where=where)
92-
columns = [exp.to_column(col) for col in columns_to_types]
92+
columns = [exp.column(col) for col in columns_to_types]
9393
when_not_matched_by_source = exp.When(
9494
matched=False,
9595
source=True,

tests/core/engine_adapter/test_base.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from sqlmesh.core import dialect as d
1414
from sqlmesh.core.dialect import normalize_model_name
1515
from sqlmesh.core.engine_adapter import EngineAdapter, EngineAdapterWithIndexSupport
16+
from sqlmesh.core.engine_adapter.mixins import InsertOverwriteWithMergeMixin
1617
from sqlmesh.core.engine_adapter.shared import InsertOverwriteStrategy
1718
from sqlmesh.core.schema_diff import SchemaDiffer, TableAlterOperation
1819
from sqlmesh.utils import columns_to_types_to_struct
@@ -322,6 +323,30 @@ def test_insert_overwrite_no_where(make_mocked_engine_adapter: t.Callable):
322323
]
323324

324325

326+
def test_insert_overwrite_by_condition_column_contains_unsafe_characters(
327+
make_mocked_engine_adapter: t.Callable, mocker: MockerFixture
328+
):
329+
adapter = make_mocked_engine_adapter(InsertOverwriteWithMergeMixin)
330+
331+
source_queries, columns_to_types = adapter._get_source_queries_and_columns_to_types(
332+
parse_one("SELECT 1 AS c"), None, target_table="test_table"
333+
)
334+
335+
columns_mock = mocker.patch.object(adapter, "columns")
336+
columns_mock.return_value = {"foo.bar.baz": exp.DataType.build("INT")}
337+
338+
adapter._insert_overwrite_by_condition(
339+
"test_table",
340+
source_queries,
341+
columns_to_types=None,
342+
)
343+
344+
# The goal here is to assert that we don't parse `foo.bar.baz` into a qualified column
345+
assert to_sql_calls(adapter) == [
346+
'MERGE INTO "test_table" AS "__MERGE_TARGET__" USING (SELECT "foo.bar.baz" FROM (SELECT 1 AS "c") AS "_subquery") AS "__MERGE_SOURCE__" ON FALSE WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED THEN INSERT ("foo.bar.baz") VALUES ("foo.bar.baz")'
347+
]
348+
349+
325350
def test_insert_append_query(make_mocked_engine_adapter: t.Callable):
326351
adapter = make_mocked_engine_adapter(EngineAdapter)
327352

0 commit comments

Comments
 (0)