Files
rustpad/src/database.rs
T
2026-07-24 11:22:44 +02:00

66 lines
1.8 KiB
Rust

use crate::queries;
use sqlx::{AnyPool, any::AnyPoolOptions};
use tracing::{debug, info};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DatabaseKind {
Sqlite,
Postgres,
MySql,
}
#[derive(Debug, Clone)]
pub struct Database {
pool: AnyPool,
kind: DatabaseKind,
}
impl Database {
pub async fn connect(url: &str, max_connections: u32) -> Result<Self, sqlx::Error> {
sqlx::any::install_default_drivers();
let kind = DatabaseKind::from_url(url)?;
debug!(?kind, max_connections, "initializing database pool");
let pool = AnyPoolOptions::new()
.max_connections(max_connections)
.connect(url)
.await?;
if kind == DatabaseKind::Sqlite {
debug!("applying SQLite connection pragmas");
sqlx::query(queries::SQLITE_FOREIGN_KEYS_ON)
.execute(&pool)
.await?;
sqlx::query(queries::SQLITE_JOURNAL_WAL)
.execute(&pool)
.await?;
sqlx::query(queries::SQLITE_BUSY_TIMEOUT)
.execute(&pool)
.await?;
}
info!(?kind, max_connections, "database pool ready");
Ok(Self { pool, kind })
}
pub fn pool(&self) -> &AnyPool {
&self.pool
}
pub fn kind(&self) -> DatabaseKind {
self.kind
}
}
impl DatabaseKind {
fn from_url(url: &str) -> Result<Self, sqlx::Error> {
if url.starts_with("sqlite:") {
Ok(Self::Sqlite)
} else if url.starts_with("postgres:") || url.starts_with("postgresql:") {
Ok(Self::Postgres)
} else if url.starts_with("mysql:") {
Ok(Self::MySql)
} else {
Err(sqlx::Error::Configuration(
"DATABASE_URL must use sqlite://, postgres:// or mysql://".into(),
))
}
}
}