1#[cfg(feature = "async")]
2use std::future::Future;
3#[cfg(feature = "async")]
4use std::pin::Pin;
5
6use rusqlite::{Connection, Row, ToSql};
7
8use crate::entities::errors::DbResult;
9
10#[cfg(feature = "async")]
11pub(crate) type DynFut<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>;
12#[cfg(feature = "async")]
13pub(crate) type DynFutDbRes<T> = Pin<Box<dyn Future<Output = DbResult<T>> + Send + 'static>>;
14
15pub trait IConnection {
16 type Locked: IConnection;
17
18 fn lock_sync(&self) -> DbResult<Self::Locked>;
19 fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T>;
20}
21
22#[cfg(feature = "async")]
23pub trait IAsyncConnection {
24 type Locked: IConnection;
25
26 fn lock_sync(&self) -> DynFut<Self::Locked>;
27 fn with<
28 T: Send + Sync + 'static,
29 F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
30 >(
31 &self,
32 fun: F,
33 ) -> DynFutDbRes<T>;
34}
35
36pub trait INewDbRepo<Connection> {
37 fn create(connect: Connection) -> Self;
38}
39
40pub trait IDbRepo {
41 fn as_super(&self) -> &dyn IDbRepo {
42 unimplemented!()
43 }
44 fn init(&self) -> DbResult<()> {
45 self.as_super().init()
46 }
47 fn recreate_tables(&self) -> DbResult<()> {
48 self.drop()?;
50 self.init()
51 }
52 fn drop(&self) -> DbResult<()> {
53 self.as_super().drop()
54 }
55 fn set_indexes(&self) -> DbResult<()> {
56 self.as_super().set_indexes()
57 }
58 fn drop_indexes(&self) -> DbResult<()> {
59 self.as_super().drop_indexes()
60 }
61 fn get_size(&self) -> DbResult<usize> {
62 self.as_super().get_size()
63 }
64}
65pub trait IExecutor {
98 type Locked: IExecutor;
99
100 fn lock(&self) -> DbResult<Self::Locked>;
101 fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
102 &self,
103 query: &str,
104 params: &[&dyn ToSql],
105 serializer: F,
106 ) -> DbResult<T>;
107 fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
108 &self,
109 query: &str,
110 params: &[&dyn ToSql],
111 serializer: F,
112 ) -> DbResult<Vec<T>>;
113 fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()>;
114 fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64>;
115}
116
117#[cfg(feature = "async")]
118pub trait IAsyncExecutor {
119 type Locked: IExecutor;
120
121 fn lock(&self) -> DynFut<Self::Locked>;
122 fn get_one<
123 T: Send + Sync + 'static,
124 F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
125 >(
126 &self,
127 query: &str,
128 params: &[&dyn ToSql],
129 serializer: F,
130 ) -> DynFutDbRes<T>;
131 fn get_many<
132 T: Send + Sync + 'static,
133 F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
134 >(
135 &self,
136 query: &str,
137 params: &[&dyn ToSql],
138 serializer: F,
139 ) -> DynFutDbRes<Vec<T>>;
140 fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()>;
141}
142
143impl IConnection for Connection {
148 type Locked = Self;
149
150 fn lock_sync(&self) -> DbResult<Self::Locked> {
151 panic!("Can not lock bare connection")
152 }
153
154 fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
155 fun(self)
156 }
157}
158
159#[cfg(feature = "async")]
160impl IAsyncConnection for Connection {
161 type Locked = Self;
162
163 fn lock_sync(&self) -> DynFut<Self::Locked> {
164 panic!("Can not lock bare connection")
165 }
166
167 fn with<
168 T: Send + Sync + 'static,
169 F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
170 >(
171 &self,
172 fun: F,
173 ) -> DynFutDbRes<T> {
174 let res = fun(self);
175 Box::pin(async move { res })
176 }
177}
178
179impl<Cnn: IConnection> IConnection for &Cnn {
180 type Locked = Cnn::Locked;
181
182 fn lock_sync(&self) -> DbResult<Self::Locked> {
183 (**self).lock_sync()
184 }
185
186 fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
187 (**self).with(fun)
188 }
189}
190
191#[cfg(feature = "async")]
192impl<Cnn: IAsyncConnection> IAsyncConnection for &Cnn {
193 type Locked = Cnn::Locked;
194
195 fn lock_sync(&self) -> DynFut<Self::Locked> {
196 (**self).lock_sync()
197 }
198
199 fn with<
200 T: Send + Sync + 'static,
201 F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
202 >(
203 &self,
204 fun: F,
205 ) -> DynFutDbRes<T> {
206 (**self).with(fun)
207 }
208}
209
210impl<Ex: IExecutor> IExecutor for &Ex {
211 type Locked = Ex::Locked;
212
213 fn lock(&self) -> DbResult<Self::Locked> {
214 (**self).lock()
215 }
216
217 fn get_one<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
218 &self,
219 query: &str,
220 params: &[&dyn ToSql],
221 serializer: F,
222 ) -> DbResult<T> {
223 (**self).get_one(query, params, serializer)
224 }
225
226 fn get_many<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
227 &self,
228 query: &str,
229 params: &[&dyn ToSql],
230 serializer: F,
231 ) -> DbResult<Vec<T>> {
232 (**self).get_many(query, params, serializer)
233 }
234
235 fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
236 (**self).execute(query, params)
237 }
238
239 fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
240 (**self).execute_return_id(query, params)
241 }
242}
243
244#[cfg(feature = "async")]
245impl<Ex: IAsyncExecutor> IAsyncExecutor for &Ex {
246 type Locked = Ex::Locked;
247
248 fn lock(&self) -> DynFut<Self::Locked> {
249 (**self).lock()
250 }
251
252 fn get_one<
253 T: Send + Sync + 'static,
254 F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
255 >(
256 &self,
257 query: &str,
258 params: &[&dyn ToSql],
259 serializer: F,
260 ) -> DynFutDbRes<T> {
261 (**self).get_one(query, params, serializer)
262 }
263
264 fn get_many<
265 T: Send + Sync + 'static,
266 F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
267 >(
268 &self,
269 query: &str,
270 params: &[&dyn ToSql],
271 serializer: F,
272 ) -> DynFutDbRes<Vec<T>> {
273 (**self).get_many(query, params, serializer)
274 }
275
276 fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()> {
277 (**self).execute(query, params)
278 }
279}