Feature request
Problem
When querying DuckDB parquet files via the Python duckdb client, the path must be
interpolated into the SQL string as a literal (DuckDB resolves the schema at planning
time, so it cannot be a bind parameter). This forces f-string SQL construction, which
triggers linter rule S608 (possible SQL injection via string-based query construction).
Proposed solution
Add a read_parquet SQLAlchemy FunctionElement to duckdb_engine that:
- Accepts the path through SQLAlchemy's API (not a raw f-string in caller code)
- Compiles to a SQL literal with single-quote escaping in the dialect compiler
- Supports
.table_valued(...) so the rest of the query can use proper bind parameters
Before (current workaround)
con.execute(
f"SELECT col FROM read_parquet('{tmp_path}/*.parquet') WHERE x = ?",
[value]
)
After (proposed)
from duckdb_engine.functions import read_parquet
rp = read_parquet(str(tmp_path / "*.parquet")).table_valued("col", "x")
stmt = select(rp.c.col).where(rp.c.x == bindparam("x"))
Question
Would you accept a PR for this? Any preferences on placement (e.g. a new
duckdb_engine/functions.py) or API shape?
Feature request
Problem
When querying DuckDB parquet files via the Python duckdb client, the path must be
interpolated into the SQL string as a literal (DuckDB resolves the schema at planning
time, so it cannot be a bind parameter). This forces f-string SQL construction, which
triggers linter rule S608 (possible SQL injection via string-based query construction).
Proposed solution
Add a
read_parquetSQLAlchemyFunctionElementtoduckdb_enginethat:.table_valued(...)so the rest of the query can use proper bind parametersBefore (current workaround)
After (proposed)
Question
Would you accept a PR for this? Any preferences on placement (e.g. a new
duckdb_engine/functions.py) or API shape?