1515 "Param" ,
1616 "SupportsDuckdbTemplate" ,
1717 "compile" ,
18+ "resolve" ,
1819 "template" ,
1920]
2021
@@ -26,10 +27,6 @@ class CompiledSql:
2627 sql : str
2728 params : tuple [Param , ...]
2829
29- # def __init__(self, sql: str, params: Iterable[Param]) -> None:
30- # self.sql = sql
31- # self.params = tuple(params)
32-
3330
3431@dataclasses .dataclass (frozen = True )
3532class Param :
@@ -94,21 +91,17 @@ def param(value: object, name: str | None = None) -> ParamInterpolation:
9491 return ParamInterpolation (value = value , expression = name )
9592
9693
97- def template (thing : object , / , ** ignored_kwargs ) -> SqlTemplate :
98- """Convert something to a Template-ish .
94+ def template (thing : object , / ) -> SqlTemplate :
95+ """Convert something to a SqlTemplate .
9996
10097 The rules are:
101- - If the thing has a __duckdb_template__ method, call it and convert the
98+ - If the thing has a `. __duckdb_template__()` method, call it and convert the
10299 resuling strings and IntoParams into a SqlTemplate.
103100 - If the thing is a `str`, treat it as raw SQL and return a SqlTemplate with that string.
104- - If the thing is an IntoTemplate, resolve it into a SqlTemplate by recursively resolving
105- any inner IntoInterpolations and flattening any nested templates.
106- - If the thing is an IntoInterpolation, resolve it into a SqlTemplate by recursively resolving
107- its value, and if it has a conversion specified (!s, !r, !a), treat it as raw SQL.
108101 - Otherwise, treat the thing as a param.
109102 """
110103 if isinstance (thing , SupportsDuckdbTemplate ):
111- raw = thing .__duckdb_template__ (** ignored_kwargs )
104+ raw = thing .__duckdb_template__ ()
112105 parts = [raw ] if isinstance (raw , str ) or is_into_interpolation (raw ) else list (raw )
113106 return SqlTemplate (* parts )
114107 if isinstance (thing , str ):
@@ -120,15 +113,8 @@ def template(thing: object, /, **ignored_kwargs) -> SqlTemplate:
120113 return SqlTemplate (param (value = thing ))
121114
122115
123- def compile (thing : object ) -> CompiledSql :
124- """Compile a thing into a final SQL string with named parameter placeholders, and a list of Params."""
125- t = template (thing )
126- resolved = resolve (t )
127- return compile_parts (resolved )
128-
129-
130- def resolve (parts : Iterable [str | IntoInterpolation ]) -> SqlTemplate [str | IntoInterpolation ]:
131- """Resolve an OurTemplate by recursively resolving any inner templates and interpolations."""
116+ def resolve (parts : Iterable [str | IntoInterpolation ]) -> SqlTemplate :
117+ """Resolve a stream of strings and Interpolations, recursively resolving inner interpolations."""
132118 resolved : list [str | IntoInterpolation ] = []
133119 for part in parts :
134120 if isinstance (part , str ):
@@ -138,6 +124,13 @@ def resolve(parts: Iterable[str | IntoInterpolation]) -> SqlTemplate[str | IntoI
138124 return SqlTemplate (* resolved )
139125
140126
127+ def compile (thing : object ) -> CompiledSql :
128+ """Compile a thing into a final SQL string with named parameter placeholders, and a list of Params."""
129+ t = template (thing )
130+ resolved = resolve (t )
131+ return compile_parts (resolved )
132+
133+
141134def resolve_interpolation (interp : IntoInterpolation ) -> Iterable [str | IntoInterpolation ]:
142135 value = interp .value
143136 # if conversion specified (!s, !r, !a), treat as raw sql, eg
@@ -188,7 +181,7 @@ def resolve_interpolation(interp: IntoInterpolation) -> Iterable[str | IntoInter
188181
189182
190183def compile_parts (parts : Iterable [str | IntoInterpolation ], / ) -> CompiledSql :
191- """Compile a resolved SqlTemplate into a final SQL string with named parameter placeholders, and a list of Params."""
184+ """Compile parts into a final SQL string with named parameter placeholders, and a list of Params."""
192185 sql_parts : list [str ] = []
193186 params : list [Param ] = []
194187 for part in parts :
@@ -242,13 +235,13 @@ def __init__(self, value: object, expression: str | None = None) -> None:
242235
243236
244237class SqlTemplate :
245- """A simple implementation of IntoTemplate, for testing purposes ."""
238+ """A sequence of strings and Interpolations ."""
246239
247240 def __init__ (
248241 self ,
249242 * parts : str | IntoInterpolation ,
250243 ) -> None :
251- self .strings , self .interpolations = parse_strings_and_params (parts )
244+ self .strings , self .interpolations = parse_parts (parts )
252245
253246 def __iter__ (self ) -> Iterator [str | IntoInterpolation ]:
254247 """Iterate over the strings and interpolations in order."""
@@ -270,7 +263,7 @@ def compile(self) -> CompiledSql:
270263T = TypeVar ("T" )
271264
272265
273- def parse_strings_and_params (
266+ def parse_parts (
274267 parts : Iterable [str | T ],
275268) -> tuple [tuple [str , ...], tuple [T , ...]]:
276269 """Parse an iterable of strings and params into separate tuples of strings and params, merging adjacent strings and ensuring that the number of strings is one more than the number of params."""
0 commit comments