rust_query/
exec.rs

1use std::{
2    cell::Cell,
3    marker::PhantomData,
4    ops::{Deref, DerefMut},
5};
6
7use sea_query::SqliteQueryBuilder;
8use sea_query_rusqlite::RusqliteBinder;
9
10use crate::{
11    dummy::{Cacher, Dummy, Row},
12    rows::Rows,
13};
14
15/// This is the top level query type and dereferences to [Rows].
16/// Most importantly it can turn the query result into a [Vec].
17pub struct Query<'outer, 'inner, S> {
18    pub(crate) phantom: PhantomData<&'outer ()>,
19    pub(crate) q: Rows<'inner, S>,
20    pub(crate) conn: &'inner rusqlite::Connection,
21}
22
23impl<'outer, 'inner, S> Deref for Query<'outer, 'inner, S> {
24    type Target = Rows<'inner, S>;
25
26    fn deref(&self) -> &Self::Target {
27        &self.q
28    }
29}
30
31impl<'outer, 'inner, S> DerefMut for Query<'outer, 'inner, S> {
32    fn deref_mut(&mut self) -> &mut Self::Target {
33        &mut self.q
34    }
35}
36
37impl<'outer, 'inner, S> Query<'outer, 'inner, S> {
38    /// Turn a database query into a rust [Vec] of results.
39    ///
40    /// Types that implement [crate::IntoColumn], will also implement [Dummy].
41    /// Tuples of two values also implement [Dummy]. If you want to return more
42    /// than two values, then you should use a struct that derives [crate::FromDummy].
43    pub fn into_vec<D>(&'inner self, dummy: D) -> Vec<D::Out>
44    where
45        D: Dummy<'inner, 'outer, S>,
46    {
47        self.into_vec_private(dummy)
48    }
49
50    pub(crate) fn into_vec_private<'x, D>(&'inner self, dummy: D) -> Vec<D::Out>
51    where
52        D: Dummy<'x, 'outer, S>,
53        S: 'x,
54    {
55        let mut f = dummy.prepare(Cacher {
56            _p: PhantomData,
57            ast: &self.ast,
58        });
59
60        let select = self.ast.simple();
61        let (sql, values) = select.build_rusqlite(SqliteQueryBuilder);
62        if SHOW_SQL.get() {
63            println!("{sql}");
64            println!("{values:?}");
65        }
66
67        let mut statement = self.conn.prepare_cached(&sql).unwrap();
68        let mut rows = statement.query(&*values.as_params()).unwrap();
69
70        let mut out = vec![];
71        while let Some(row) = rows.next().unwrap() {
72            let row = Row {
73                _p: PhantomData,
74                _p2: PhantomData,
75                row,
76            };
77            out.push(f(row));
78        }
79        out
80    }
81}
82
83thread_local! {
84    static SHOW_SQL: Cell<bool> = const { Cell::new(false) };
85}
86
87pub fn show_sql<R>(f: impl FnOnce() -> R) -> R {
88    let old = SHOW_SQL.get();
89    SHOW_SQL.set(true);
90    let res = f();
91    SHOW_SQL.set(old);
92    res
93}