aboutsummaryrefslogtreecommitdiff
path: root/src/db/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/db/mod.rs')
-rw-r--r--src/db/mod.rs59
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,