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