#[cfg(feature = "async")]
use std::future::Future;
#[cfg(feature = "async")]
use std::pin::Pin;
use rusqlite::{Connection, Row, ToSql};
use crate::entities::errors::DbResult;
#[cfg(feature = "async")]
pub(crate) type DynFut<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>;
#[cfg(feature = "async")]
pub(crate) type DynFutDbRes<T> = Pin<Box<dyn Future<Output = DbResult<T>> + Send + 'static>>;
pub trait IConnection {
type Locked: IConnection;
fn lock_sync(&self) -> DbResult<Self::Locked>;
fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T>;
}
#[cfg(feature = "async")]
pub trait IAsyncConnection {
type Locked: IConnection;
fn lock_sync(&self) -> DynFut<Self::Locked>;
fn with<
T: Send + Sync + 'static,
F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
fun: F,
) -> DynFutDbRes<T>;
}
pub trait INewDbRepo<Connection> {
fn create(connect: Connection) -> Self;
}
pub trait IDbRepo {
fn as_super(&self) -> &dyn IDbRepo {
unimplemented!()
}
fn init(&self) -> DbResult<()> {
self.as_super().init()
}
fn recreate_tables(&self) -> DbResult<()> {
self.drop()?;
self.init()
}
fn drop(&self) -> DbResult<()> {
self.as_super().drop()
}
fn set_indexes(&self) -> DbResult<()> {
self.as_super().set_indexes()
}
fn drop_indexes(&self) -> DbResult<()> {
self.as_super().drop_indexes()
}
fn get_size(&self) -> DbResult<usize> {
self.as_super().get_size()
}
}
pub trait IExecutor {
type Locked: IExecutor;
fn lock(&self) -> DbResult<Self::Locked>;
fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DbResult<T>;
fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DbResult<Vec<T>>;
fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()>;
fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64>;
}
#[cfg(feature = "async")]
pub trait IAsyncExecutor {
type Locked: IExecutor;
fn lock(&self) -> DynFut<Self::Locked>;
fn get_one<
T: Send + Sync + 'static,
F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DynFutDbRes<T>;
fn get_many<
T: Send + Sync + 'static,
F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DynFutDbRes<Vec<T>>;
fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()>;
}
impl IConnection for Connection {
type Locked = Self;
fn lock_sync(&self) -> DbResult<Self::Locked> {
panic!("Can not lock bare connection")
}
fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
fun(self)
}
}
#[cfg(feature = "async")]
impl IAsyncConnection for Connection {
type Locked = Self;
fn lock_sync(&self) -> DynFut<Self::Locked> {
panic!("Can not lock bare connection")
}
fn with<
T: Send + Sync + 'static,
F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
fun: F,
) -> DynFutDbRes<T> {
let res = fun(self);
Box::pin(async move { res })
}
}
impl<Cnn: IConnection> IConnection for &Cnn {
type Locked = Cnn::Locked;
fn lock_sync(&self) -> DbResult<Self::Locked> {
(**self).lock_sync()
}
fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
(**self).with(fun)
}
}
#[cfg(feature = "async")]
impl<Cnn: IAsyncConnection> IAsyncConnection for &Cnn {
type Locked = Cnn::Locked;
fn lock_sync(&self) -> DynFut<Self::Locked> {
(**self).lock_sync()
}
fn with<
T: Send + Sync + 'static,
F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
fun: F,
) -> DynFutDbRes<T> {
(**self).with(fun)
}
}
impl<Ex: IExecutor> IExecutor for &Ex {
type Locked = Ex::Locked;
fn lock(&self) -> DbResult<Self::Locked> {
(**self).lock()
}
fn get_one<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DbResult<T> {
(**self).get_one(query, params, serializer)
}
fn get_many<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DbResult<Vec<T>> {
(**self).get_many(query, params, serializer)
}
fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
(**self).execute(query, params)
}
fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
(**self).execute_return_id(query, params)
}
}
#[cfg(feature = "async")]
impl<Ex: IAsyncExecutor> IAsyncExecutor for &Ex {
type Locked = Ex::Locked;
fn lock(&self) -> DynFut<Self::Locked> {
(**self).lock()
}
fn get_one<
T: Send + Sync + 'static,
F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DynFutDbRes<T> {
(**self).get_one(query, params, serializer)
}
fn get_many<
T: Send + Sync + 'static,
F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
>(
&self,
query: &str,
params: &[&dyn ToSql],
serializer: F,
) -> DynFutDbRes<Vec<T>> {
(**self).get_many(query, params, serializer)
}
fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()> {
(**self).execute(query, params)
}
}