1use crate::error::map_sqlx_err;
4use crate::pool::{SqlxPool, SqlxTransaction, SqlxTransactionGuard};
5use alibi_core::error::AuthResult;
6pub use alibi_core::hooks::current_request_hook_context;
7pub use alibi_core::store::{DatabaseHookContext, DatabaseHooks, HookBackend, HookControl};
8
9#[derive(Debug, Clone, Copy)]
16pub struct SqlxBackend;
17
18impl HookBackend for SqlxBackend {
19 type Connection = SqlxPool;
20 type Transaction = SqlxTransaction;
21}
22
23pub type SqlxHookContext<'a> = DatabaseHookContext<'a, SqlxBackend>;
25
26pub trait SqlxHookContextExt {
28 fn connection(&self) -> impl Future<Output = AuthResult<SqlxHookConnection<'_>>> + Send;
36}
37
38impl SqlxHookContextExt for SqlxHookContext<'_> {
39 async fn connection(&self) -> AuthResult<SqlxHookConnection<'_>> {
40 let inner = if let Some(transaction) = self.tx {
41 HookConnection::Transaction(transaction.lock().await)
42 } else {
43 match self.db {
44 #[cfg(feature = "sqlite")]
45 SqlxPool::Sqlite(pool) => {
46 HookConnection::Sqlite(pool.acquire().await.map_err(map_sqlx_err)?)
47 }
48 #[cfg(feature = "postgres")]
49 SqlxPool::Postgres(pool) => {
50 HookConnection::Postgres(pool.acquire().await.map_err(map_sqlx_err)?)
51 }
52 }
53 };
54 Ok(SqlxHookConnection { inner })
55 }
56}
57
58#[derive(Debug)]
59enum HookConnection<'a> {
60 Transaction(SqlxTransactionGuard<'a>),
61 #[cfg(feature = "sqlite")]
62 Sqlite(sqlx::pool::PoolConnection<sqlx::Sqlite>),
63 #[cfg(feature = "postgres")]
64 Postgres(sqlx::pool::PoolConnection<sqlx::Postgres>),
65}
66
67#[derive(Debug)]
72pub struct SqlxHookConnection<'a> {
73 inner: HookConnection<'a>,
74}
75
76impl SqlxHookConnection<'_> {
77 #[cfg(feature = "sqlite")]
79 pub fn sqlite(&mut self) -> Option<&mut sqlx::SqliteConnection> {
80 match &mut self.inner {
81 HookConnection::Transaction(guard) => guard.sqlite(),
82 HookConnection::Sqlite(connection) => Some(connection),
83 #[cfg(feature = "postgres")]
84 HookConnection::Postgres(_) => None,
85 }
86 }
87
88 #[cfg(feature = "postgres")]
90 pub fn postgres(&mut self) -> Option<&mut sqlx::PgConnection> {
91 match &mut self.inner {
92 HookConnection::Transaction(guard) => guard.postgres(),
93 HookConnection::Postgres(connection) => Some(connection),
94 #[cfg(feature = "sqlite")]
95 HookConnection::Sqlite(_) => None,
96 }
97 }
98}