1use std::{marker::PhantomData, rc::Rc};
2
3use crate::{Expr, lower, value::DbTyp};
4
5pub(crate) struct Cacher {
7 pub(crate) columns: Vec<Rc<lower::Expr>>,
8}
9
10impl Cacher {
11 pub(crate) fn new() -> Self {
12 Self {
13 columns: Vec::new(),
14 }
15 }
16}
17
18pub struct Cached<T> {
19 pub(crate) idx: usize,
20 _p: PhantomData<T>,
21}
22
23impl<T> Clone for Cached<T> {
24 fn clone(&self) -> Self {
25 *self
26 }
27}
28impl<T> Copy for Cached<T> {}
29
30impl Cacher {
31 pub(crate) fn cache_erased(&mut self, val: Rc<lower::Expr>) -> usize {
32 let idx = self.columns.len();
33 self.columns.push(val);
34 idx
35 }
36}
37
38#[derive(Clone, Copy)]
39pub(crate) struct Row<'x> {
40 pub(crate) row: &'x rusqlite::Row<'x>,
41 pub(crate) fields: &'x [String],
42}
43
44impl<'x> Row<'x> {
45 pub(crate) fn new(row: &'x rusqlite::Row<'x>, fields: &'x [String]) -> Self {
46 Self { row, fields }
47 }
48
49 pub fn get<T: DbTyp>(&self, val: Cached<T>) -> T {
50 let idx = &self.fields[val.idx];
51 T::from_sql(self.row.get_ref_unwrap(idx.as_str())).unwrap()
52 }
53}
54
55pub(crate) trait Prepared {
56 type Out;
57
58 fn call(&mut self, row: Row<'_>) -> Self::Out;
59}
60
61pub struct Select<'columns, S, Out> {
67 pub(crate) inner: DynSelectImpl<Out>,
68 pub(crate) _p: PhantomData<&'columns ()>,
69 pub(crate) _p2: PhantomData<S>,
70}
71
72impl<'columns, S, Out: 'static> Select<'columns, S, Out> {
73 pub fn map<T>(self, f: impl 'static + FnMut(Out) -> T) -> Select<'columns, S, T> {
77 Select::new(MapImpl {
78 dummy: self.inner,
79 func: f,
80 })
81 }
82}
83
84pub struct DynSelectImpl<Out> {
85 inner: Box<dyn FnOnce(&mut Cacher) -> DynPrepared<Out>>,
86}
87
88impl<Out> SelectImpl for DynSelectImpl<Out> {
89 type Out = Out;
90 type Prepared = DynPrepared<Out>;
91
92 fn prepare(self, cacher: &mut Cacher) -> Self::Prepared {
93 (self.inner)(cacher)
94 }
95}
96
97pub struct DynPrepared<Out> {
98 inner: Box<dyn Prepared<Out = Out>>,
99}
100
101impl<Out> Prepared for DynPrepared<Out> {
102 type Out = Out;
103 fn call(&mut self, row: Row<'_>) -> Self::Out {
104 self.inner.call(row)
105 }
106}
107
108impl<S, Out> Select<'_, S, Out> {
109 pub(crate) fn new(val: impl 'static + SelectImpl<Out = Out>) -> Self {
110 Self {
111 inner: DynSelectImpl {
112 inner: Box::new(|cacher| DynPrepared {
113 inner: Box::new(val.prepare(cacher)),
114 }),
115 },
116 _p: PhantomData,
117 _p2: PhantomData,
118 }
119 }
120}
121
122impl<'columns, S, Out: 'static> IntoSelect<'columns, S> for Select<'columns, S, Out> {
123 type Out = Out;
124
125 fn into_select(self) -> Select<'columns, S, Self::Out> {
126 self
127 }
128}
129
130pub trait SelectImpl {
131 type Out;
132 #[doc(hidden)]
133 type Prepared: Prepared<Out = Self::Out>;
134 #[doc(hidden)]
135 fn prepare(self, cacher: &mut Cacher) -> Self::Prepared;
136}
137
138pub trait IntoSelect<'columns, S>: Sized {
154 type Out: 'static;
156
157 fn into_select(self) -> Select<'columns, S, Self::Out>;
163}
164
165pub struct MapImpl<D, F> {
170 dummy: D,
171 func: F,
172}
173
174impl<D, F, O> SelectImpl for MapImpl<D, F>
175where
176 D: SelectImpl,
177 F: FnMut(D::Out) -> O,
178{
179 type Out = O;
180 type Prepared = MapPrepared<D::Prepared, F>;
181
182 fn prepare(self, cacher: &mut Cacher) -> Self::Prepared {
183 MapPrepared {
184 inner: self.dummy.prepare(cacher),
185 map: self.func,
186 }
187 }
188}
189
190pub struct MapPrepared<X, M> {
191 inner: X,
192 map: M,
193}
194
195impl<X, M, Out> Prepared for MapPrepared<X, M>
196where
197 X: Prepared,
198 M: FnMut(X::Out) -> Out,
199{
200 type Out = Out;
201
202 fn call(&mut self, row: Row<'_>) -> Self::Out {
203 (self.map)(self.inner.call(row))
204 }
205}
206
207impl Prepared for () {
208 type Out = ();
209
210 fn call(&mut self, _row: Row<'_>) -> Self::Out {}
211}
212
213impl SelectImpl for () {
214 type Out = ();
215 type Prepared = ();
216
217 fn prepare(self, _cacher: &mut Cacher) -> Self::Prepared {}
218}
219
220impl<'columns, S> IntoSelect<'columns, S> for () {
221 type Out = ();
222
223 fn into_select(self) -> Select<'columns, S, Self::Out> {
224 Select::new(())
225 }
226}
227
228impl<T: DbTyp> Prepared for Cached<T> {
229 type Out = T;
230
231 fn call(&mut self, row: Row<'_>) -> Self::Out {
232 row.get(*self)
233 }
234}
235
236pub struct ColumnImpl<Out> {
237 pub(crate) expr: Rc<lower::Expr>,
238 pub(crate) _p: PhantomData<Out>,
239}
240
241impl<Out: DbTyp> SelectImpl for ColumnImpl<Out> {
242 type Out = Out;
243 type Prepared = Cached<Out>;
244
245 fn prepare(self, cacher: &mut Cacher) -> Self::Prepared {
246 Cached {
247 idx: cacher.cache_erased(self.expr),
248 _p: PhantomData,
249 }
250 }
251}
252
253impl<'columns, S, T> IntoSelect<'columns, S> for Expr<'columns, S, T>
254where
255 T: DbTyp,
256{
257 type Out = T;
258
259 fn into_select(self) -> Select<'columns, S, Self::Out> {
260 Select::new(ColumnImpl {
261 expr: self.inner,
262 _p: PhantomData,
263 })
264 }
265}
266
267impl<'columns, S, T> IntoSelect<'columns, S> for &T
268where
269 T: IntoSelect<'columns, S> + Clone,
270{
271 type Out = T::Out;
272
273 fn into_select(self) -> Select<'columns, S, Self::Out> {
274 T::clone(self).into_select()
275 }
276}
277
278impl<A, B> Prepared for (A, B)
279where
280 A: Prepared,
281 B: Prepared,
282{
283 type Out = (A::Out, B::Out);
284
285 fn call(&mut self, row: Row<'_>) -> Self::Out {
286 (self.0.call(row), self.1.call(row))
287 }
288}
289
290impl<A, B> SelectImpl for (A, B)
291where
292 A: SelectImpl,
293 B: SelectImpl,
294{
295 type Out = (A::Out, B::Out);
296 type Prepared = (A::Prepared, B::Prepared);
297
298 fn prepare(self, cacher: &mut Cacher) -> Self::Prepared {
299 let prepared_a = self.0.prepare(cacher);
300 let prepared_b = self.1.prepare(cacher);
301 (prepared_a, prepared_b)
302 }
303}
304
305impl<'columns, S, A, B> IntoSelect<'columns, S> for (A, B)
306where
307 A: IntoSelect<'columns, S>,
308 B: IntoSelect<'columns, S>,
309{
310 type Out = (A::Out, B::Out);
311
312 fn into_select(self) -> Select<'columns, S, Self::Out> {
313 Select::new((self.0.into_select().inner, self.1.into_select().inner))
314 }
315}
316
317#[cfg(test)]
318#[allow(unused)]
319mod tests {
320 use crate::IntoExpr;
321
322 use super::*;
323
324 struct User {
325 a: i64,
326 b: String,
327 }
328
329 struct UserSelect<A, B> {
330 a: A,
331 b: B,
332 }
333
334 impl<'columns, S, A, B> IntoSelect<'columns, S> for UserSelect<A, B>
335 where
336 A: IntoExpr<'columns, S, Typ = i64>,
337 B: IntoExpr<'columns, S, Typ = String>,
338 {
339 type Out = User;
340
341 fn into_select(self) -> Select<'columns, S, Self::Out> {
342 (self.a.into_expr(), self.b.into_expr())
343 .into_select()
344 .map((|(a, b)| User { a, b }) as fn((i64, String)) -> User)
345 .into_select()
346 }
347 }
348}