rust_query/
query.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_impl::{Cacher, IntoSelect, Prepared, Row, SelectImpl},
12    rows::Rows,
13};
14
15/// This is the type used by the [crate::Transaction::query] method.
16pub struct Query<'outer, 'inner, S> {
17    pub(crate) phantom: PhantomData<&'inner &'outer ()>,
18    pub(crate) q: Rows<'inner, S>,
19    pub(crate) conn: &'inner rusqlite::Connection,
20}
21
22impl<'outer, 'inner, S> Deref for Query<'outer, 'inner, S> {
23    type Target = Rows<'inner, S>;
24
25    fn deref(&self) -> &Self::Target {
26        &self.q
27    }
28}
29
30impl<'outer, 'inner, S> DerefMut for Query<'outer, 'inner, S> {
31    fn deref_mut(&mut self) -> &mut Self::Target {
32        &mut self.q
33    }
34}
35
36impl<'outer, 'inner, S> Query<'outer, 'inner, S> {
37    /// Turn a database query into a rust [Vec] of results.
38    ///
39    /// Types that implement [crate::IntoExpr], will also implement [IntoSelect].
40    /// Tuples of two values also implement [IntoSelect]. If you want to return more
41    /// than two values, then you should use a struct that derives [rust_query_macros::Select].
42    ///
43    /// The order of rows that is returned is unstable. This means that the order may change between any two
44    /// executions of the exact same query. If a specific order (or even a consistent order) is required,
45    /// then you have to use something like [slice::sort].
46    pub fn into_vec<O>(&self, select: impl IntoSelect<'inner, 'outer, S, Out = O>) -> Vec<O> {
47        self.into_vec_private(select)
48    }
49
50    pub(crate) fn into_vec_private<'x, D>(&self, dummy: D) -> Vec<D::Out>
51    where
52        D: IntoSelect<'x, 'outer, S>,
53    {
54        let mut cacher = Cacher::new();
55        let mut prepared = dummy.into_select().inner.prepare(&mut cacher);
56
57        let cached = self.ast.cache(cacher.columns);
58
59        let select = self.ast.simple();
60        let (sql, values) = select.build_rusqlite(SqliteQueryBuilder);
61        if SHOW_SQL.get() {
62            println!("{sql}");
63            println!("{values:?}");
64        }
65
66        let mut statement = self.conn.prepare_cached(&sql).unwrap();
67        let mut rows = statement.query(&*values.as_params()).unwrap();
68
69        let mut out = vec![];
70        while let Some(row) = rows.next().unwrap() {
71            out.push(prepared.call(Row::new(row, &cached)));
72        }
73        out
74    }
75}
76
77thread_local! {
78    static SHOW_SQL: Cell<bool> = const { Cell::new(false) };
79}
80
81pub fn show_sql<R>(f: impl FnOnce() -> R) -> R {
82    let old = SHOW_SQL.get();
83    SHOW_SQL.set(true);
84    let res = f();
85    SHOW_SQL.set(old);
86    res
87}