Skip to content

Commit 6fcbf0d

Browse files
committed
Improve CompiledSql ergonomics and docstrings
1 parent 477aa71 commit 6fcbf0d

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

duckdb/template.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,29 @@
1515
"IntoInterpolation",
1616
"Param",
1717
"SupportsDuckdbTemplate",
18+
"compile",
1819
"param",
1920
"template",
2021
]
2122

2223

2324
@dataclasses.dataclass(frozen=True, slots=True)
2425
class CompiledSql:
25-
"""Represents a compiled SQL statement, with the final SQL string and a list of Params to be passed to duckdb."""
26+
"""Represents a compiled SQL statement, with the final SQL string and a dict of params to be passed to duckdb.
27+
28+
You will typically not create this directly, but will get it as the result
29+
of calling .compile() on a SqlTemplate or ResolvedSqlTemplate.
30+
31+
Example:
32+
>>> age = 37
33+
>>> c = compile(t"SELECT * FROM users WHERE age >= {age}")
34+
>>> c
35+
>>> CompiledSql(sql="SELECT * FROM users WHERE age >= $p0_age", params={"p0_age": 37})
36+
duckdb.query(c.sql, c.params)
37+
"""
2638

2739
sql: str
28-
params: dict[str, object]
40+
params: dict[str, object] = dataclasses.field(default_factory=dict)
2941

3042

3143
@runtime_checkable
@@ -114,7 +126,7 @@ def template(*part: str | IntoInterpolation | Param | SupportsDuckdbTemplate | o
114126
This is very useful for versions of python before 3.14 that don't have tstrings,
115127
since it allows you to build up a template from smaller pieces:
116128
117-
>>> t = template(["SELECT * FROM (", all_people, ") WHERE age >= ", age])
129+
>>> t = template("SELECT * FROM (", all_people, ") WHERE age >= ", age)
118130
>>> t.compile()
119131
CompiledSql(sql='SELECT * FROM (SELECT * FROM people) WHERE age >= $p0_age', params={'p0_age': 18})
120132
@@ -138,6 +150,17 @@ def template(*part: str | IntoInterpolation | Param | SupportsDuckdbTemplate | o
138150
return SqlTemplate(*expanded)
139151

140152

153+
def compile(*part: str | IntoInterpolation | Param | SupportsDuckdbTemplate | object) -> CompiledSql:
154+
"""Compile a sequence of things into a final SQL string with named parameter placeholders, and a list of Params.
155+
156+
This is a convenience function that combines template() and .compile() into one step.
157+
158+
For more details and examples, see template().
159+
"""
160+
t = template(*part)
161+
return t.compile()
162+
163+
141164
def _expand_part(part: object) -> Iterable[str | IntoInterpolation]:
142165
if isinstance(part, SupportsDuckdbTemplate):
143166
raw = part.__duckdb_template__()
@@ -164,7 +187,7 @@ def _expand_part(part: object) -> Iterable[str | IntoInterpolation]:
164187

165188

166189
class ParamInterpolation:
167-
"""A simple wrapper that implements the IntoInterpolation protocol for a given IntoParam."""
190+
"""A simple wrapper that implements the IntoInterpolation protocol for a given Param."""
168191

169192
def __init__(self, param: Param): # noqa: ANN204
170193
self.value = param

tests/fast/test_template.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,16 @@ def test_basic(self):
745745
assert c.sql == "SELECT $p0"
746746
assert c.params == {"p0": 42}
747747

748+
def test_empty_params(self):
749+
c = CompiledSql(sql="SELECT 1", params={})
750+
assert c.sql == "SELECT 1"
751+
assert c.params == {}
752+
753+
def test_optional_params(self):
754+
c = CompiledSql(sql="SELECT 1")
755+
assert c.sql == "SELECT 1"
756+
assert c.params == {}
757+
748758
def test_frozen(self):
749759
c = CompiledSql(sql="SELECT 1", params={})
750760
with pytest.raises(AttributeError):
@@ -757,7 +767,8 @@ def test_equality(self):
757767

758768
def test_repr(self):
759769
c = CompiledSql(sql="SELECT 1", params={})
760-
assert "SELECT 1" in repr(c)
770+
expected = "CompiledSql(sql='SELECT 1', params={})"
771+
assert repr(c) == expected
761772

762773

763774
# ═══════════════════════════════════════════════════════════════════════════════

0 commit comments

Comments
 (0)