mod models; #[rustfmt::skip] mod schema; use diesel::{ r2d2::{ConnectionManager, Pool}, SqliteConnection, }; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; use std::{error::Error, fmt, path::Path}; pub use models::event::{Event, NewEvent, EVENT_TYPES}; pub use models::image::{Image, NewImage}; pub use models::plant::{NewPlant, Plant}; pub use models::session::Session; pub use models::user::{NewUser, User}; pub type DbPool = Pool>; pub type DbResult = Result; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); #[derive(Debug)] pub enum DbError { Pool(diesel::r2d2::PoolError), Db(diesel::result::Error), } impl fmt::Display for DbError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Pool(_) => write!(f, "failed to acquire connection from pool"), Self::Db(_) => write!(f, "error while executing query"), } } } impl Error for DbError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::Pool(err) => Some(err), Self::Db(err) => Some(err), } } } impl From for DbError { fn from(value: diesel::r2d2::PoolError) -> Self { Self::Pool(value) } } impl From for DbError { fn from(value: diesel::result::Error) -> Self { Self::Db(value) } } pub fn initialize_db(path: impl AsRef, run_migrations: bool) -> Result { let manager = ConnectionManager::::new(path.as_ref().to_string_lossy()); let pool = Pool::new(manager)?; if run_migrations { pool.get()?.run_pending_migrations(MIGRATIONS).unwrap(); } Ok(pool) }