Skip to content

Commit 5921278

Browse files
committed
Add support for funky column names
1 parent fd0e824 commit 5921278

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

duckdb/polars_io.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ def _pl_tree_to_sql(tree: dict) -> str:
9595
)
9696
if node_type == "Column":
9797
# A reference to a column name
98-
return subtree
98+
# Wrap in quotes to handle special characters
99+
return f'"{subtree}"'
99100

100101
if node_type in ("Literal", "Dyn"):
101102
# Recursively process dynamic or literal values
@@ -196,7 +197,7 @@ def source_generator(
196197
duck_predicate = None
197198
relation_final = relation
198199
if with_columns is not None:
199-
cols = ",".join(with_columns)
200+
cols = ",".join(f'"{col}"' for col in with_columns)
200201
relation_final = relation_final.project(cols)
201202
if n_rows is not None:
202203
relation_final = relation_final.limit(n_rows)
@@ -213,7 +214,6 @@ def source_generator(
213214
while True:
214215
try:
215216
record_batch = results.read_next_batch()
216-
df = pl.from_arrow(record_batch)
217217
if predicate is not None and duck_predicate is None:
218218
# We have a predicate, but did not manage to push it down, we fallback here
219219
yield pl.from_arrow(record_batch).filter(predicate)

tests/fast/arrow/test_polars.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,29 @@ def test_polars_lazy(self, duckdb_cursor):
131131
]
132132
assert lazy_df.filter(pl.col("b") < 32).select('a').collect().to_dicts() == [{'a': 'Mark'}, {'a': 'Thijs'}]
133133

134+
def test_polars_column_with_tricky_name(self, duckdb_cursor):
135+
# Test that a polars DataFrame with a column name that is non standard still works
136+
df_colon = pl.DataFrame({"x:y": [1, 2]})
137+
lf = duckdb_cursor.sql("from df_colon").pl(lazy=True)
138+
result = lf.select(pl.all()).collect()
139+
assert result.to_dicts() == [{"x:y": 1}, {"x:y": 2}]
140+
result = lf.select(pl.all()).filter(pl.col("x:y") == 1).collect()
141+
assert result.to_dicts() == [{"x:y": 1}]
142+
143+
df_space = pl.DataFrame({"x y": [1, 2]})
144+
lf = duckdb_cursor.sql("from df_space").pl(lazy=True)
145+
result = lf.select(pl.all()).collect()
146+
assert result.to_dicts() == [{"x y": 1}, {"x y": 2}]
147+
result = lf.select(pl.all()).filter(pl.col("x y") == 1).collect()
148+
assert result.to_dicts() == [{"x y": 1}]
149+
150+
df_dot = pl.DataFrame({"x.y": [1, 2]})
151+
lf = duckdb_cursor.sql("from df_dot").pl(lazy=True)
152+
result = lf.select(pl.all()).collect()
153+
assert result.to_dicts() == [{"x.y": 1}, {"x.y": 2}]
154+
result = lf.select(pl.all()).filter(pl.col("x.y") == 1).collect()
155+
assert result.to_dicts() == [{"x.y": 1}]
156+
134157
@pytest.mark.parametrize(
135158
'data_type',
136159
[

0 commit comments

Comments
 (0)