mod auth;
mod channel;
mod guild;
mod member;
mod role;
mod user;
pub use auth::AuthDbExt;
pub use channel::ChannelDbExt;
pub use guild::GuildDbExt;
pub use member::MemberDbExt;
pub use role::RoleDbExt;
pub use user::UserDbExt;
pub use sqlx;
use sqlx::{postgres::PgPoolOptions, Pool, Postgres, Transaction};
use std::sync::OnceLock;
pub static POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
pub async fn connect(url: &str) -> Result<(), sqlx::Error> {
let pool = PgPoolOptions::new().connect(url).await?;
POOL.set(pool)
.expect("cannot initialize database pool more than once");
Ok(())
}
#[must_use]
#[inline]
pub fn get_pool() -> &'static Pool<Postgres> {
POOL.get().expect("database pool not initialized")
}
pub async fn migrate() {
sqlx::migrate!("./migrations")
.run(get_pool())
.await
.expect("could not run database migrations");
}
pub trait DbExt<'t>: Sized + Send {
type Executor: sqlx::PgExecutor<'static>;
type Transaction: sqlx::PgExecutor<'t>;
fn executor(&self) -> Self::Executor;
fn transaction(&mut self) -> Self::Transaction;
}
impl DbExt<'static> for &'static Pool<Postgres> {
type Executor = Self;
type Transaction = Self::Executor;
#[inline]
fn executor(&self) -> Self::Executor {
self
}
#[inline]
fn transaction(&mut self) -> Self::Transaction {
self
}
}
impl<'t> DbExt<'t> for Transaction<'static, Postgres> {
type Executor = &'static Pool<Postgres>;
type Transaction = &'t mut Self;
#[inline]
fn executor(&self) -> Self::Executor {
get_pool()
}
#[inline]
fn transaction(&mut self) -> Self::Transaction {
unsafe { std::mem::transmute(self) }
}
}