Add SearchFilter struct for LIKE-based search with dynamic column matching. Add DatabaseDriver type alias to support QueryBuilder generics across SQLite and Postgres feature flags.
89 lines
2.7 KiB
Rust
89 lines
2.7 KiB
Rust
use anyhow::Context;
|
|
use sqlx::migrate::Migrator;
|
|
|
|
#[cfg(all(feature = "sqlite", feature = "postgres"))]
|
|
compile_error!("features `sqlite` and `postgres` cannot both be enabled");
|
|
|
|
#[cfg(not(any(feature = "sqlite", feature = "postgres")))]
|
|
compile_error!("enable either the `sqlite` or `postgres` feature");
|
|
|
|
#[cfg(feature = "sqlite")]
|
|
pub type DatabasePool = sqlx::SqlitePool;
|
|
#[cfg(feature = "sqlite")]
|
|
type PoolOptions = sqlx::sqlite::SqlitePoolOptions;
|
|
#[cfg(feature = "sqlite")]
|
|
pub type DatabaseTransaction<'a> = sqlx::Transaction<'a, sqlx::Sqlite>;
|
|
#[cfg(feature = "sqlite")]
|
|
pub type DatabaseRow = sqlx::sqlite::SqliteRow;
|
|
#[cfg(feature = "sqlite")]
|
|
pub type DatabaseDriver = sqlx::Sqlite;
|
|
|
|
#[cfg(feature = "postgres")]
|
|
pub type DatabasePool = sqlx::PgPool;
|
|
#[cfg(feature = "postgres")]
|
|
type PoolOptions = sqlx::postgres::PgPoolOptions;
|
|
#[cfg(feature = "postgres")]
|
|
pub type DatabaseTransaction<'a> = sqlx::Transaction<'a, sqlx::Postgres>;
|
|
#[cfg(feature = "postgres")]
|
|
pub type DatabaseRow = sqlx::postgres::PgRow;
|
|
#[cfg(feature = "postgres")]
|
|
pub type DatabaseDriver = sqlx::Postgres;
|
|
|
|
pub struct Database {
|
|
pool: DatabasePool,
|
|
}
|
|
|
|
impl Database {
|
|
pub async fn connect(database_url: &str) -> anyhow::Result<Self> {
|
|
#[cfg(feature = "sqlite")]
|
|
let pool = {
|
|
use sqlx::sqlite::SqliteConnectOptions;
|
|
use std::str::FromStr;
|
|
|
|
let options = SqliteConnectOptions::from_str(database_url)
|
|
.with_context(|| format!("invalid database url: {database_url}"))?
|
|
.create_if_missing(true);
|
|
|
|
PoolOptions::new()
|
|
.max_connections(5)
|
|
.connect_with(options)
|
|
.await
|
|
.with_context(|| format!("failed to connect to database: {database_url}"))?
|
|
};
|
|
|
|
#[cfg(feature = "postgres")]
|
|
let pool = PoolOptions::new()
|
|
.max_connections(5)
|
|
.connect(database_url)
|
|
.await
|
|
.with_context(|| format!("failed to connect to database: {database_url}"))?;
|
|
|
|
#[cfg(feature = "sqlite")]
|
|
{
|
|
sqlx::query("PRAGMA foreign_keys = ON;")
|
|
.execute(&pool)
|
|
.await
|
|
.context("failed to enable foreign keys for sqlite")?;
|
|
}
|
|
|
|
let db = Self { pool };
|
|
db.migrate().await?;
|
|
Ok(db)
|
|
}
|
|
|
|
pub fn pool(&self) -> &DatabasePool {
|
|
&self.pool
|
|
}
|
|
|
|
pub fn clone_pool(&self) -> DatabasePool {
|
|
self.pool.clone()
|
|
}
|
|
|
|
pub async fn migrate(&self) -> anyhow::Result<()> {
|
|
static MIGRATOR: Migrator = sqlx::migrate!("./migrations");
|
|
MIGRATOR
|
|
.run(&self.pool)
|
|
.await
|
|
.context("database migration failed")
|
|
}
|
|
}
|