diff options
Diffstat (limited to 'src/db/mod.rs')
| -rw-r--r-- | src/db/mod.rs | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/src/db/mod.rs b/src/db/mod.rs index 180012d..483665e 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -26,6 +26,7 @@ use r2d2_postgres::{ use anyhow::anyhow; use lazy_static::lazy_static; +use diesel_migrations::MigrationHarness; use crate::{Error, Result}; @@ -35,6 +36,9 @@ use self::schema::*; mod schema; mod models; +const MIGRATIONS: diesel_migrations::EmbeddedMigrations = diesel_migrations::embed_migrations!(); +static MIGRATE: std::sync::Once = std::sync::Once::new(); + lazy_static! { static ref DB_URL: String = env::var("DATABASE_URL").expect("no database url in environment").into(); static ref DB_CONFIG: Config = Config::from_str(&DB_URL).expect("parsing db url as config"); @@ -42,20 +46,33 @@ lazy_static! { static ref RAW_CONN_MGR: RawPgConnMgr<NoTls> = RawPgConnMgr::new(DB_CONFIG.clone(), NoTls); } + #[inline] pub fn connection() -> Result<PgConnection> { - CONN_MGR.connect().map_err(Error::from) + CONN_MGR.connect() + .map(|mut conn| { + MIGRATE.call_once(|| { + log::info!("running migrations"); + conn.run_pending_migrations(MIGRATIONS).expect("failed running migrations"); + }); + + conn + }) + .map_err(Error::from) } #[inline] fn raw_connection() -> Result<RawPgConn> { - RAW_CONN_MGR.connect().map_err(Error::from) -} + // HACK + if !MIGRATE.is_completed() { + connection()?; + } -pub fn find_meme<T: AsRef<str>>(conn: &PgConnection, search: T) -> Result<Meme> { - use diesel::dsl::sql; - use diesel::sql_types::Text; + RAW_CONN_MGR.connect() + .map_err(Error::from) +} +pub fn find_meme<T: AsRef<str>>(conn: &mut PgConnection, search: T) -> Result<Meme> { let search = search.as_ref(); let mut meme = memes::table @@ -67,7 +84,7 @@ pub fn find_meme<T: AsRef<str>>(conn: &PgConnection, search: T) -> Result<Meme> let format_search = format!("%{}%", search); meme = memes::table - .filter(memes::title.ilike(&format_search).or(sql("content ILIKE ").bind::<Text, _>(&format_search))) + .filter(memes::title.ilike(&format_search).or(memes::content.ilike(&format_search))) .limit(1) .first::<Meme>(conn); } @@ -121,26 +138,26 @@ pub fn query_meme<T: AsRef<str>>(search: T, user_id: Option<u64>, age_desc: bool Ok(result) } -pub fn delete_meme<T: AsRef<str>>(conn: &PgConnection, search: T, deleted_by: u64) -> Result<()> { - conn.transaction::<(), Error, _>(|| { +pub fn delete_meme<T: AsRef<str>>(conn: &mut PgConnection, search: T, deleted_by: u64) -> Result<()> { + conn.transaction::<(), Error, _>(|tx| { let deleted = memes::table .filter(memes::title.eq(search.as_ref())) - .first::<Meme>(conn)?; + .first::<Meme>(tx)?; ::diesel::delete(memes::table) .filter(memes::id.eq(deleted.id)) - .execute(conn)?; + .execute(tx)?; if let Some(image_id) = deleted.image_id { let count = memes::table .filter(memes::image_id.eq(image_id)) .count() - .execute(conn)?; + .execute(tx)?; if count == 0 { ::diesel::delete(images::table) .filter(images::id.eq(image_id)) - .execute(conn)?; + .execute(tx)?; } } @@ -148,12 +165,12 @@ pub fn delete_meme<T: AsRef<str>>(conn: &PgConnection, search: T, deleted_by: u6 let count = memes::table .select(::diesel::dsl::count_star()) .filter(memes::audio_id.eq(audio_id)) - .execute(conn)?; + .execute(tx)?; if count == 0 { ::diesel::delete(audio::table) .filter(audio::id.eq(audio_id)) - .execute(conn)?; + .execute(tx)?; } } @@ -165,13 +182,13 @@ pub fn delete_meme<T: AsRef<str>>(conn: &PgConnection, search: T, deleted_by: u6 let _ = ::diesel::insert_into(tombstones::table) .values(&tombstone) - .execute(conn)?; + .execute(tx)?; Ok(()) }) } -pub fn rare_meme(conn: &PgConnection, audio: bool) -> Result<Meme> { +pub fn rare_meme(conn: &mut PgConnection, audio: bool) -> Result<Meme> { use rand::prelude::*; let mut raw_conn = raw_connection()?; @@ -227,7 +244,7 @@ pub fn rare_meme(conn: &PgConnection, audio: bool) -> Result<Meme> { Meme::find(conn, meme_id) } -pub fn rand_meme(conn: &PgConnection, audio: bool) -> Result<Meme> { +pub fn rand_meme(conn: &mut PgConnection, audio: bool) -> Result<Meme> { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec<i32> = if audio { @@ -256,7 +273,7 @@ pub fn rand_meme(conn: &PgConnection, audio: bool) -> Result<Meme> { .map_err(Error::from) } -pub fn rand_audio_meme(conn: &PgConnection) -> Result<Meme> { +pub fn rand_audio_meme(conn: &mut PgConnection) -> Result<Meme> { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec<i32> = memes::table @@ -274,7 +291,7 @@ pub fn rand_audio_meme(conn: &PgConnection) -> Result<Meme> { .map_err(Error::from) } -pub fn rand_silent_meme(conn: &PgConnection) -> Result<Meme> { +pub fn rand_silent_meme(conn: &mut PgConnection) -> Result<Meme> { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec<i32> = memes::table @@ -323,7 +340,7 @@ pub struct Stats { pub most_popular_meme_overall_count: usize, } -pub fn stats(conn: &PgConnection) -> Result<Stats> { +pub fn stats(conn: &mut PgConnection) -> Result<Stats> { use diesel::dsl::{count_star, count}; use chrono::{ NaiveDateTime, |
