easy_sqlite/impls/
mutex_connection.rs1use 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}