easy_sqlite/impls/
executor.rs

1use rusqlite::{Connection, ToSql};
2use std::cell::RefCell;
3use std::rc::Rc;
4
5use crate::errors::{DbError, DbResult};
6use crate::traits::repo::{IConnection, IExecutor};
7
8pub struct Executor<Cnn: IConnection> {
9    cnn: Cnn,
10}
11
12impl<Cnn: IConnection> Executor<Cnn> {
13    #[inline]
14    pub fn new(cnn: Cnn) -> Self {
15        Self { cnn }
16    }
17}
18
19fn signal_error() -> rusqlite::Error {
20    rusqlite::Error::ExecuteReturnedResults
21}
22
23fn unwrap_err<T>(
24    handler: &RefCell<Option<DbError>>,
25    res: Result<T, rusqlite::Error>,
26) -> Result<T, DbError> {
27    if let Some(ref val) = *handler.borrow() {
28        Err(val.clone())
29    } else {
30        Ok(res?)
31    }
32}
33
34impl<Cnn: IConnection> IExecutor for Executor<Cnn> {
35    type Locked = Executor<Cnn::Locked>;
36
37    fn lock(&self) -> DbResult<Self::Locked> {
38        Ok(Executor::new(self.cnn.lock_sync()?))
39    }
40
41    fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
42        &self,
43        query: &str,
44        params: &[&dyn ToSql],
45        mut serializer: F,
46    ) -> DbResult<T> {
47        let real_error = Rc::new(RefCell::new(None));
48        let err_handler_copy = real_error.clone();
49        let m_serializer = move |row: &rusqlite::Row| -> rusqlite::Result<T> {
50            let other_copy = err_handler_copy.clone();
51            serializer(row).map_err(move |err| {
52                *other_copy.borrow_mut() = Some(err);
53                signal_error()
54            })
55        };
56        let fun = move |cnn: &Connection| -> DbResult<T> {
57            let mut statement = cnn.prepare(query)?;
58            let qmap = statement.query_map(params, m_serializer);
59            let val = unwrap_err(&real_error, qmap)?.next();
60            match val {
61                Some(val) => unwrap_err(&real_error, val),
62                None => Err(DbError::NotFound(None)),
63            }
64        };
65        self.cnn.with(fun)
66    }
67
68    fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
69        &self,
70        query: &str,
71        params: &[&dyn ToSql],
72        mut serializer: F,
73    ) -> DbResult<Vec<T>> {
74        let real_error = Rc::new(RefCell::new(None));
75        let err_handler_copy = real_error.clone();
76        let m_serializer = move |row: &rusqlite::Row| -> rusqlite::Result<T> {
77            serializer(row).map_err(|err| {
78                *err_handler_copy.borrow_mut() = Some(err);
79                signal_error()
80            })
81        };
82        let fun = move |cnn: &Connection| -> DbResult<Vec<T>> {
83            let mut statement = cnn.prepare(query)?;
84            let qmap = statement.query_map(params, m_serializer);
85            let val = unwrap_err(&real_error, qmap)?
86                .map(|res| unwrap_err(&real_error, res))
87                .collect::<Result<Vec<T>, _>>()?;
88            Ok(val)
89        };
90        self.cnn.with(fun)
91    }
92
93    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
94        self.cnn.with(move |cnn| {
95            cnn.execute(query, params)?;
96            Ok(())
97        })
98    }
99
100    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
101        self.cnn.with(move |cnn| {
102            cnn.execute(query, params)?;
103            Ok(cnn.last_insert_rowid())
104        })
105    }
106}