easy_sqlite/impls/
mutex_connection.rs

1use std::mem;
2use std::path::Path;
3use std::sync::{Arc, Mutex, MutexGuard};
4
5use rusqlite::{Connection, Row, ToSql};
6
7use crate::entities::errors::{DbError, DbResult};
8use crate::impls::executor::Executor;
9use crate::traits::repo::{IConnection, IExecutor};
10
11#[derive(Clone)]
12pub struct MSQLConnection {
13    inner: Arc<Mutex<Connection>>,
14}
15
16#[derive(Clone)]
17pub struct Lock {
18    mtx: Arc<Mutex<Connection>>,
19    guard: Option<Arc<MutexGuard<'static, Connection>>>,
20}
21
22impl Drop for Lock {
23    fn drop(&mut self) {
24        let _ = mem::replace(&mut self.guard, None);
25    }
26}
27
28impl MSQLConnection {
29    pub fn new<P: AsRef<Path>>(path: P) -> DbResult<Self> {
30        let cnct = Connection::open(path).map_err(|err| DbError::CanNotConnect(err.to_string()))?;
31        Ok(Self {
32            inner: Arc::new(Mutex::new(cnct)),
33        })
34    }
35}
36
37impl IConnection for MSQLConnection {
38    type Locked = Lock;
39
40    fn lock_sync(&self) -> DbResult<Self::Locked> {
41        let mtx = self.inner.clone();
42        let guard = self.inner.lock()?;
43        let guard: MutexGuard<'static, Connection> = unsafe { mem::transmute(guard) };
44        Ok(Lock {
45            mtx,
46            guard: Some(Arc::new(guard)),
47        })
48    }
49
50    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
51        let guard = self.inner.lock()?;
52        fun(&guard)
53    }
54}
55
56impl IExecutor for MSQLConnection {
57    type Locked = Lock;
58
59    fn lock(&self) -> DbResult<Self::Locked> {
60        self.lock_sync()
61    }
62
63    fn get_one<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
64        &self,
65        query: &str,
66        params: &[&dyn ToSql],
67        serializer: F,
68    ) -> DbResult<T> {
69        Executor::new(self).get_one(query, params, serializer)
70    }
71
72    fn get_many<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
73        &self,
74        query: &str,
75        params: &[&dyn ToSql],
76        serializer: F,
77    ) -> DbResult<Vec<T>> {
78        Executor::new(self).get_many(query, params, serializer)
79    }
80
81    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
82        Executor::new(self).execute(query, params)
83    }
84
85    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
86        Executor::new(self).execute_return_id(query, params)
87    }
88}
89
90impl IConnection for Lock {
91    type Locked = Self;
92
93    fn lock_sync(&self) -> DbResult<Self::Locked> {
94        Ok(Self {
95            mtx: self.mtx.clone(),
96            guard: self.guard.clone(),
97        })
98    }
99
100    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
101        if let Some(ref grd) = self.guard {
102            fun(grd)
103        } else {
104            unreachable!()
105        }
106    }
107}
108
109impl IExecutor for Lock {
110    type Locked = Self;
111
112    fn lock(&self) -> DbResult<Self::Locked> {
113        self.lock_sync()
114    }
115
116    fn get_one<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
117        &self,
118        query: &str,
119        params: &[&dyn ToSql],
120        serializer: F,
121    ) -> DbResult<T> {
122        Executor::new(self).get_one(query, params, serializer)
123    }
124
125    fn get_many<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
126        &self,
127        query: &str,
128        params: &[&dyn ToSql],
129        serializer: F,
130    ) -> DbResult<Vec<T>> {
131        Executor::new(self).get_many(query, params, serializer)
132    }
133
134    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
135        Executor::new(self).execute(query, params)
136    }
137
138    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
139        Executor::new(self).execute_return_id(query, params)
140    }
141}