rust_query/
query.rs

1use std::{
2    cell::Cell,
3    fmt::Debug,
4    marker::PhantomData,
5    ops::{Deref, DerefMut},
6};
7
8use rusqlite::Connection;
9use sea_query::SqliteQueryBuilder;
10use sea_query_rusqlite::{RusqliteBinder, RusqliteValues};
11
12use crate::{
13    dummy_impl::{Cacher, IntoSelect, Prepared, Row, SelectImpl},
14    rows::Rows,
15};
16
17/// This is the type used by the [crate::Transaction::query] method.
18pub struct Query<'outer, 'inner, S> {
19    pub(crate) phantom: PhantomData<&'inner &'outer ()>,
20    pub(crate) q: Rows<'inner, S>,
21    pub(crate) conn: &'inner rusqlite::Connection,
22}
23
24impl<'inner, S> Deref for Query<'_, 'inner, S> {
25    type Target = Rows<'inner, S>;
26
27    fn deref(&self) -> &Self::Target {
28        &self.q
29    }
30}
31
32impl<S> DerefMut for Query<'_, '_, S> {
33    fn deref_mut(&mut self) -> &mut Self::Target {
34        &mut self.q
35    }
36}
37
38impl<'outer, 'inner, S> Query<'outer, 'inner, S> {
39    /// Turn a database query into a [Vec] of results.
40    ///
41    /// The order of rows that is returned is unstable. This means that the order may change between any two
42    /// executions of the exact same query. If a specific order (or even a consistent order) is required,
43    /// then you have to use something like [slice::sort].
44    pub fn into_vec<O>(&self, select: impl IntoSelect<'inner, 'outer, S, Out = O>) -> Vec<O> {
45        self.into_vec_private(select)
46    }
47
48    pub(crate) fn into_vec_private<'x, D>(&self, dummy: D) -> Vec<D::Out>
49    where
50        D: IntoSelect<'x, 'outer, S>,
51    {
52        let mut cacher = Cacher::new();
53        let mut prepared = dummy.into_select().inner.prepare(&mut cacher);
54
55        let (select, cached) = self.ast.clone().full().simple(cacher.columns);
56        let (sql, values) = select.build_rusqlite(SqliteQueryBuilder);
57        if SHOW_SQL.get() {
58            println!("{sql}");
59            println!("{values:?}");
60        }
61        if GET_PLAN.get() {
62            let node = get_node(&self.conn, &values, &sql);
63            PLAN.set(Some(node));
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    static GET_PLAN: Cell<bool> = const { Cell::new(false) };
80    static PLAN: Cell<Option<Node>> = const { Cell::new(None) };
81}
82
83pub fn show_sql<R>(f: impl FnOnce() -> R) -> R {
84    let old = SHOW_SQL.get();
85    SHOW_SQL.set(true);
86    let res = f();
87    SHOW_SQL.set(old);
88    res
89}
90
91pub fn get_plan<R>(f: impl FnOnce() -> R) -> (R, Node) {
92    let old = GET_PLAN.get();
93    GET_PLAN.set(true);
94    let res = f();
95    GET_PLAN.set(old);
96    (res, PLAN.take().unwrap())
97}
98
99fn get_node(conn: &Connection, values: &RusqliteValues, sql: &str) -> Node {
100    let mut prepared = conn.prepare(&format!("EXPLAIN QUERY PLAN {sql}")).unwrap();
101    let rows = prepared
102        .query_map(&*values.as_params(), |row| {
103            Ok((
104                row.get_unwrap("parent"),
105                Node {
106                    id: row.get_unwrap("id"),
107                    detail: row.get_unwrap("detail"),
108                    children: vec![],
109                },
110            ))
111        })
112        .unwrap();
113    let mut out = Node {
114        id: 0,
115        detail: "QUERY PLAN".to_owned(),
116        children: vec![],
117    };
118    rows.for_each(|res| {
119        let (id, node) = res.unwrap();
120        out.get_mut(id).children.push(node);
121    });
122
123    out
124}
125
126pub struct Node {
127    id: i64,
128    detail: String,
129    children: Vec<Node>,
130}
131
132impl Node {
133    fn get_mut(&mut self, id: i64) -> &mut Node {
134        if self.id == id {
135            return self;
136        }
137        self.children.last_mut().unwrap().get_mut(id)
138    }
139}
140
141impl Debug for Node {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        f.write_str(&self.detail)?;
144        if !self.children.is_empty() {
145            f.write_str(" ")?;
146            f.debug_list().entries(&self.children).finish()?;
147        }
148        Ok(())
149    }
150}