aboutsummaryrefslogtreecommitdiff
path: root/src/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/db')
-rw-r--r--src/db/mod.rs59
-rw-r--r--src/db/models.rs24
2 files changed, 50 insertions, 33 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,
diff --git a/src/db/models.rs b/src/db/models.rs
index 95acb16..54e8ce2 100644
--- a/src/db/models.rs
+++ b/src/db/models.rs
@@ -24,15 +24,15 @@ pub struct Meme {
}
impl Meme {
- pub fn image(&self, conn: &PgConnection) -> Option<Result<Image>> {
+ pub fn image(&self, conn: &mut PgConnection) -> Option<Result<Image>> {
self.image_id.map(|x: i32| images::table.filter(images::id.eq(x)).first(conn).map_err(Error::from))
}
- pub fn audio(&self, conn: &PgConnection) -> Option<Result<Audio>> {
+ pub fn audio(&self, conn: &mut PgConnection) -> Option<Result<Audio>> {
self.audio_id.map(|x: i32| audio::table.filter(audio::id.eq(x)).first(conn).map_err(Error::from))
}
- pub fn find(conn: &PgConnection, id: i32) -> Result<Meme> {
+ pub fn find(conn: &mut PgConnection, id: i32) -> Result<Meme> {
memes::table.find(id).get_result(conn).map_err(Error::from)
}
}
@@ -48,7 +48,7 @@ pub struct NewMeme {
}
impl NewMeme {
- pub fn save(mut self, conn: &PgConnection, by_user: u64) -> Result<Meme> {
+ pub fn save(mut self, conn: &mut PgConnection, by_user: u64) -> Result<Meme> {
let metadata = Metadata::create(conn, by_user)?;
self.metadata_id = metadata.id;
@@ -71,7 +71,7 @@ pub struct Audio {
}
impl Audio {
- pub fn create(conn: &PgConnection, data: Vec<u8>, by_user: u64) -> Result<i32> {
+ pub fn create(conn: &mut PgConnection, data: Vec<u8>, by_user: u64) -> Result<i32> {
let mut data_hash = ::sha1::Sha1::new();
data_hash.update(&data);
let data_hash = data_hash.digest().bytes().to_vec();
@@ -121,7 +121,7 @@ pub struct Image {
}
impl Image {
- pub fn create(conn: &PgConnection, filename: &str, data: Vec<u8>, by_user: u64) -> Result<i32> {
+ pub fn create(conn: &mut PgConnection, filename: &str, data: Vec<u8>, by_user: u64) -> Result<i32> {
let mut data_hash = ::sha1::Sha1::new();
data_hash.update(&data);
let data_hash = data_hash.digest().bytes().to_vec();
@@ -171,7 +171,7 @@ pub struct Metadata {
}
impl Metadata {
- pub fn create(conn: &PgConnection, by_user: u64) -> Result<Metadata> {
+ pub fn create(conn: &mut PgConnection, by_user: u64) -> Result<Metadata> {
::diesel::insert_into(metadata::table)
.values(&NewMetadata {
created_by: by_user as i64,
@@ -180,7 +180,7 @@ impl Metadata {
.map_err(Error::from)
}
- pub fn find(conn: &PgConnection, id: i32) -> Result<Metadata> {
+ pub fn find(conn: &mut PgConnection, id: i32) -> Result<Metadata> {
metadata::table.find(id)
.get_result::<Metadata>(conn)
.map_err(Error::from)
@@ -204,7 +204,7 @@ pub struct AuditRecord {
}
impl AuditRecord {
- pub fn create(conn: &PgConnection, metadata: i32, by_user: u64) -> Result<AuditRecord> {
+ pub fn create(conn: &mut PgConnection, metadata: i32, by_user: u64) -> Result<AuditRecord> {
::diesel::insert_into(audit_records::table)
.values(&NewAuditRecord {
updated_by: by_user as i64,
@@ -262,7 +262,7 @@ pub struct NewInvocationRecord {
}
impl InvocationRecord {
- pub fn create(conn: &PgConnection, user_id: u64, message_id: u64, meme_id: i32, random: bool) -> Result<Self> {
+ pub fn create(conn: &mut PgConnection, user_id: u64, message_id: u64, meme_id: i32, random: bool) -> Result<Self> {
::diesel::insert_into(invocation_records::table)
.values(&NewInvocationRecord {
user_id: user_id as i64,
@@ -274,14 +274,14 @@ impl InvocationRecord {
.map_err(Error::from)
}
- pub fn last(conn: &PgConnection) -> Result<Self> {
+ pub fn last(conn: &mut PgConnection) -> Result<Self> {
invocation_records::table
.order(invocation_records::time.desc())
.first(conn)
.map_err(Error::from)
}
- pub fn last_n(conn: &PgConnection, n: usize) -> Result<Vec<Self>> {
+ pub fn last_n(conn: &mut PgConnection, n: usize) -> Result<Vec<Self>> {
invocation_records::table
.order(invocation_records::time.desc())
.limit(n as i64)