easy-sqlite 0.4.1

Little sqlite framework
Documentation
use rusqlite::{Connection, ToSql};
use std::cell::RefCell;
use std::rc::Rc;

use crate::errors::{DbError, DbResult};
use crate::traits::repo::{IConnection, IExecutor};

pub struct Executor<Cnn: IConnection> {
    cnn: Cnn,
}

impl<Cnn: IConnection> Executor<Cnn> {
    #[inline]
    pub fn new(cnn: Cnn) -> Self {
        Self { cnn }
    }
}

fn signal_error() -> rusqlite::Error {
    rusqlite::Error::ExecuteReturnedResults
}

fn unwrap_err<T>(
    handler: &RefCell<Option<DbError>>,
    res: Result<T, rusqlite::Error>,
) -> Result<T, DbError> {
    if let Some(ref val) = *handler.borrow() {
        Err(val.clone())
    } else {
        Ok(res?)
    }
}

impl<Cnn: IConnection> IExecutor for Executor<Cnn> {
    type Locked = Executor<Cnn::Locked>;

    fn lock(&self) -> DbResult<Self::Locked> {
        Ok(Executor::new(self.cnn.lock_sync()?))
    }

    fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        mut serializer: F,
    ) -> DbResult<T> {
        let real_error = Rc::new(RefCell::new(None));
        let err_handler_copy = real_error.clone();
        let m_serializer = move |row: &rusqlite::Row| -> rusqlite::Result<T> {
            let other_copy = err_handler_copy.clone();
            serializer(row).map_err(move |err| {
                *other_copy.borrow_mut() = Some(err);
                signal_error()
            })
        };
        let fun = move |cnn: &Connection| -> DbResult<T> {
            let mut statement = cnn.prepare(query)?;
            let qmap = statement.query_map(params, m_serializer);
            let val = unwrap_err(&real_error, qmap)?.next();
            match val {
                Some(val) => unwrap_err(&real_error, val),
                None => Err(DbError::NotFound(None)),
            }
        };
        self.cnn.with(fun)
    }

    fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        mut serializer: F,
    ) -> DbResult<Vec<T>> {
        let real_error = Rc::new(RefCell::new(None));
        let err_handler_copy = real_error.clone();
        let m_serializer = move |row: &rusqlite::Row| -> rusqlite::Result<T> {
            serializer(row).map_err(|err| {
                *err_handler_copy.borrow_mut() = Some(err);
                signal_error()
            })
        };
        let fun = move |cnn: &Connection| -> DbResult<Vec<T>> {
            let mut statement = cnn.prepare(query)?;
            let qmap = statement.query_map(params, m_serializer);
            let val = unwrap_err(&real_error, qmap)?
                .map(|res| unwrap_err(&real_error, res))
                .collect::<Result<Vec<T>, _>>()?;
            Ok(val)
        };
        self.cnn.with(fun)
    }

    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
        self.cnn.with(move |cnn| {
            cnn.execute(query, params)?;
            Ok(())
        })
    }

    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
        self.cnn.with(move |cnn| {
            cnn.execute(query, params)?;
            Ok(cnn.last_insert_rowid())
        })
    }
}