use crate::error::map_sqlx_err;
use crate::pool::{SqlxPool, SqlxTransaction, SqlxTransactionGuard};
use alibi_core::error::AuthResult;
pub use alibi_core::hooks::current_request_hook_context;
pub use alibi_core::store::{DatabaseHookContext, DatabaseHooks, HookBackend, HookControl};
#[derive(Debug, Clone, Copy)]
pub struct SqlxBackend;
impl HookBackend for SqlxBackend {
type Connection = SqlxPool;
type Transaction = SqlxTransaction;
}
pub type SqlxHookContext<'a> = DatabaseHookContext<'a, SqlxBackend>;
pub trait SqlxHookContextExt {
fn connection(&self) -> impl Future<Output = AuthResult<SqlxHookConnection<'_>>> + Send;
}
impl SqlxHookContextExt for SqlxHookContext<'_> {
async fn connection(&self) -> AuthResult<SqlxHookConnection<'_>> {
let inner = if let Some(transaction) = self.tx {
HookConnection::Transaction(transaction.lock().await)
} else {
match self.db {
#[cfg(feature = "sqlite")]
SqlxPool::Sqlite(pool) => {
HookConnection::Sqlite(pool.acquire().await.map_err(map_sqlx_err)?)
}
#[cfg(feature = "postgres")]
SqlxPool::Postgres(pool) => {
HookConnection::Postgres(pool.acquire().await.map_err(map_sqlx_err)?)
}
}
};
Ok(SqlxHookConnection { inner })
}
}
#[derive(Debug)]
enum HookConnection<'a> {
Transaction(SqlxTransactionGuard<'a>),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::pool::PoolConnection<sqlx::Sqlite>),
#[cfg(feature = "postgres")]
Postgres(sqlx::pool::PoolConnection<sqlx::Postgres>),
}
#[derive(Debug)]
pub struct SqlxHookConnection<'a> {
inner: HookConnection<'a>,
}
impl SqlxHookConnection<'_> {
#[cfg(feature = "sqlite")]
pub fn sqlite(&mut self) -> Option<&mut sqlx::SqliteConnection> {
match &mut self.inner {
HookConnection::Transaction(guard) => guard.sqlite(),
HookConnection::Sqlite(connection) => Some(connection),
#[cfg(feature = "postgres")]
HookConnection::Postgres(_) => None,
}
}
#[cfg(feature = "postgres")]
pub fn postgres(&mut self) -> Option<&mut sqlx::PgConnection> {
match &mut self.inner {
HookConnection::Transaction(guard) => guard.postgres(),
HookConnection::Postgres(connection) => Some(connection),
#[cfg(feature = "sqlite")]
HookConnection::Sqlite(_) => None,
}
}
}