From d649248b17cd3ac20a499464b559c7d83e9236fb Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Mon, 28 Nov 2022 10:59:46 -0500 Subject: db: run migrations in db connect, upgrade diesel --- Cargo.lock | 76 +++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 5 +-- src/commands/meme/create.rs | 14 ++++---- src/commands/meme/delete.rs | 4 +-- src/commands/meme/history.rs | 23 +++++++------- src/commands/meme/invoke.rs | 40 +++++++++++++++-------- src/commands/meme/mod.rs | 2 +- src/db/mod.rs | 59 ++++++++++++++++++++++------------ src/db/models.rs | 24 +++++++------- 9 files changed, 173 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6939d0a..f661164 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,29 +463,42 @@ dependencies = [ [[package]] name = "diesel" -version = "1.4.8" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" +checksum = "68c186a7418a2aac330bb76cde82f16c36b03a66fb91db32d20214311f9f6545" dependencies = [ "bitflags", "byteorder", "chrono", "diesel_derives", + "itoa 1.0.4", "pq-sys", "r2d2", ] [[package]] name = "diesel_derives" -version = "1.4.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +checksum = "143b758c91dbc3fe1fdcb0dba5bd13276c6a66422f2ef5795b58488248a310aa" dependencies = [ + "proc-macro-error", "proc-macro2", "quote", "syn", ] +[[package]] +name = "diesel_migrations" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ae22beef5e9d6fab9225ddb073c1c6c1a7a6ded5019d5da11d1e5c5adc34e2" +dependencies = [ + "diesel", + "migrations_internals", + "migrations_macros", +] + [[package]] name = "digest" version = "0.8.1" @@ -1186,6 +1199,27 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "migrations_internals" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c493c09323068c01e54c685f7da41a9ccf9219735c3766fbfd6099806ea08fbc" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "migrations_macros" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a8ff27a350511de30cdabb77147501c36ef02e0451d957abea2f30caffb2b58" +dependencies = [ + "migrations_internals", + "proc-macro2", + "quote", +] + [[package]] name = "mime" version = "0.3.16" @@ -1637,6 +1671,30 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.47" @@ -2410,6 +2468,7 @@ dependencies = [ "chrono", "ctrlc", "diesel", + "diesel_migrations", "dotenv", "either", "envconfig", @@ -2675,6 +2734,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + [[package]] name = "tracing" version = "0.1.37" diff --git a/Cargo.toml b/Cargo.toml index 4beb2d1..2e31c2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [features] default = ["db", "games"] -db = ["diesel", "postgres", "r2d2_postgres"] +db = ["diesel", "postgres", "r2d2_postgres", "diesel_migrations"] games = [] [dependencies] @@ -20,7 +20,7 @@ dotenv = "^0.13" chrono = "^0.4" time = "^0.1" fern = { version = "^0.5", features = ["colored"] } -diesel = { version = "~1.4", features = ["postgres", "chrono", "r2d2"], optional = true } +diesel = { version = "2.0", features = ["postgres", "chrono", "r2d2"], optional = true } ctrlc = { version = "~3.1", features = ["termination"] } rand = "^0.6" either = "~1.5" @@ -37,6 +37,7 @@ pest = "~2.1" pest_derive = "~2.1" postgres = { version = "^0.19", optional = true, features = ["with-chrono-0_4"] } r2d2_postgres = { version = "^0.18", optional = true } +diesel_migrations = { version = "2.0", optional = true } envconfig = "^0.8" envconfig_derive = "^0.8" diff --git a/src/commands/meme/create.rs b/src/commands/meme/create.rs index 11af7e9..dce5213 100644 --- a/src/commands/meme/create.rs +++ b/src/commands/meme/create.rs @@ -54,7 +54,7 @@ pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { let text = if text.is_empty() { None } else { Some(text) }; - let conn = connection()?; + let mut conn = connection()?; let image = msg.attachments.first(); @@ -65,7 +65,7 @@ pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { let image_id = image.map(|att| { let data = att.download()?; - Image::create(&conn, &att.filename, data, msg.author.id.0) + Image::create(&mut conn, &att.filename, data, msg.author.id.0) }).transpose()?; let save_result = NewMeme { @@ -74,7 +74,7 @@ pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { image_id, audio_id: None, metadata_id: 0, - }.save(&conn, msg.author.id.0).map(|_| {}); + }.save(&mut conn, msg.author.id.0).map(|_| {}); use diesel::result::DatabaseErrorKind; match save_result { @@ -147,13 +147,13 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> let text = args.rest().to_owned(); let text = if text.is_empty() { None } else { Some(text) }; - let conn = connection()?; + let mut conn = connection()?; let image = msg.attachments.first() .ok_or(anyhow!("no attachment")) .and_then(|att| { let data = att.download()?; - Image::create(&conn, &att.filename, data, msg.author.id.0) + Image::create(&mut conn, &att.filename, data, msg.author.id.0) }) .ok(); @@ -165,7 +165,7 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> return ctx.send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts); } - let audio_id = Audio::create(&conn, audio_data, msg.author.id.0)?; + let audio_id = Audio::create(&mut conn, audio_data, msg.author.id.0)?; let save_result = NewMeme { title, @@ -173,7 +173,7 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> image_id: image, audio_id: Some(audio_id), metadata_id: 0, - }.save(&conn, msg.author.id.0).map(|_| {}); + }.save(&mut conn, msg.author.id.0).map(|_| {}); use diesel::result::DatabaseErrorKind; match save_result { diff --git a/src/commands/meme/delete.rs b/src/commands/meme/delete.rs index e5e4333..7eafc80 100644 --- a/src/commands/meme/delete.rs +++ b/src/commands/meme/delete.rs @@ -26,9 +26,9 @@ use crate::{ pub fn delmeme(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { let title = args.single_quoted::()?; - let conn = connection()?; + let mut conn = connection()?; - match delete_meme(&conn, &title, msg.author.id.0) { + match delete_meme(&mut conn, &title, msg.author.id.0) { Ok(_) => msg.react(ctx, "💀"), Err(e) => { if let Some(NotFound) = e.downcast_ref::() { diff --git a/src/commands/meme/history.rs b/src/commands/meme/history.rs index 8186f57..f9e8851 100644 --- a/src/commands/meme/history.rs +++ b/src/commands/meme/history.rs @@ -51,9 +51,9 @@ static CLEAN_DATE_FORMAT: &'static str = "%b %-e %Y"; #[command] #[aliases("what")] pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> { - let conn = connection()?; + let mut conn = connection()?; - let record = match InvocationRecord::last(&conn) { + let record = match InvocationRecord::last(&mut conn) { Ok(x) => x, Err(e) => { if let Some(NotFound) = e.downcast_ref::() { @@ -66,11 +66,11 @@ pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> { }, }; - let meme = Meme::find(&conn, record.meme_id); + let meme = Meme::find(&mut conn, record.meme_id); match meme { Ok(ref meme) => { - let metadata = Metadata::find(&conn, meme.metadata_id)?; + let metadata = Metadata::find(&mut conn, meme.metadata_id)?; let author = CONFIG.discord.guild().member(&ctx, metadata.created_by as u64)?; ctx.send(msg.channel_id, @@ -95,7 +95,7 @@ pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> { pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { use itertools::Itertools; - let conn = connection()?; + let mut conn = connection()?; let n = args.single_quoted::().unwrap_or(CONFIG.default_hist); @@ -106,7 +106,7 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { let n = n.min(CONFIG.max_hist); - let records = InvocationRecord::last_n(&conn, n)?; + let records = InvocationRecord::last_n(&mut conn, n)?; if records.len() == 0 { info!("no memes in history"); @@ -123,9 +123,9 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { let ago = TIME_FORMATTER.convert((chrono::Utc::now() - dt).to_std().unwrap()); let rand = if rec.random { "R, " } else { "" }; - Meme::find(&conn, rec.meme_id) + Meme::find(&mut conn, rec.meme_id) .and_then(|meme| { - Metadata::find(&conn, meme.metadata_id).map(|metadata| (metadata, meme)) + Metadata::find(&mut conn, meme.metadata_id).map(|metadata| (metadata, meme)) }) .map(|(metadata, meme)| { let author_name = CONFIG.discord.guild().member(&ctx, metadata.created_by as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned()); @@ -157,8 +157,8 @@ pub fn stats(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> { user::User, }; - let conn = connection()?; - let stats = db::stats(&conn)?; + let mut conn = connection()?; + let stats = db::stats(&mut conn)?; debug!("reporting stats"); @@ -332,5 +332,6 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { return ctx.send(msg.channel_id, "no match".to_owned(), msg.tts); } + ctx.send(msg.channel_id, &result, msg.tts) -} \ No newline at end of file +} diff --git a/src/commands/meme/invoke.rs b/src/commands/meme/invoke.rs index c5ca502..de0272f 100644 --- a/src/commands/meme/invoke.rs +++ b/src/commands/meme/invoke.rs @@ -37,6 +37,18 @@ pub fn omen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> { _meme(ctx, msg, args, AudioPlayback::Optional) } +#[command] +pub fn silentomen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> { + let args = Args::new("", &[]); + _meme(ctx, msg, args, AudioPlayback::Prohibited) +} + +#[command] +pub fn audioomen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> { + let args = Args::new("", &[]); + _meme(ctx, msg, args, AudioPlayback::Required) +} + #[command] #[aliases("audiomeme", "audiomem")] pub fn audio_meme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { @@ -63,10 +75,10 @@ fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_playback: AudioPlay let search = args.raw().join(" "); - let conn = connection()?; - let mem = match find_meme(&conn, search) { + let mut conn = connection()?; + let mem = match find_meme(&mut conn, search) { Ok(x) => { - InvocationRecord::create(&conn, msg.author.id.0, msg.id.0, x.id, false)?; + InvocationRecord::create(&mut conn, msg.author.id.0, msg.id.0, x.id, false)?; x }, @@ -81,24 +93,24 @@ fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_playback: AudioPlay }, }; - send_meme(ctx, &mem, &conn, msg) + send_meme(ctx, &mem, &mut conn, msg) } fn rand_meme(ctx: &Context, message: &Message, audio_playback: AudioPlayback) -> Result<()> { - let conn = connection()?; + let mut conn = connection()?; let should_audio = ctx.users_listening()?; let mem = match audio_playback { - AudioPlayback::Required => db::rand_audio_meme(&conn), - AudioPlayback::Optional => db::rand_meme(&conn, should_audio), - AudioPlayback::Prohibited => db::rand_silent_meme(&conn), + AudioPlayback::Required => db::rand_audio_meme(&mut conn), + AudioPlayback::Optional => db::rand_meme(&mut conn, should_audio), + AudioPlayback::Prohibited => db::rand_silent_meme(&mut conn), }; match mem { Ok(mem) => { - InvocationRecord::create(&conn, message.author.id.0, message.id.0, mem.id, true)?; - send_meme(ctx, &mem, &conn, message)?; + InvocationRecord::create(&mut conn, message.author.id.0, message.id.0, mem.id, true)?; + send_meme(ctx, &mem, &mut conn, message)?; Ok(()) }, Err(e) => { @@ -121,13 +133,13 @@ fn rand_meme(ctx: &Context, message: &Message, audio_playback: AudioPlayback) -> pub fn rare_meme(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> { let should_audio = ctx.users_listening()?; - let conn = connection()?; - let meme = db::rare_meme(&conn, should_audio); + let mut conn = connection()?; + let meme = db::rare_meme(&mut conn, should_audio); match meme { Ok(meme) => { - InvocationRecord::create(&conn, msg.author.id.0, msg.id.0, meme.id, true)?; - send_meme(ctx, &meme, &conn, msg) + InvocationRecord::create(&mut conn, msg.author.id.0, msg.id.0, meme.id, true)?; + send_meme(ctx, &meme, &mut conn, msg) }, Err(e) => { match e.downcast_ref::() { diff --git a/src/commands/meme/mod.rs b/src/commands/meme/mod.rs index ee39d55..d816a93 100644 --- a/src/commands/meme/mod.rs +++ b/src/commands/meme/mod.rs @@ -51,7 +51,7 @@ group!({ ], }); -fn send_meme(ctx: &Context, t: &Meme, conn: &PgConnection, msg: &Message) -> Result<()> { +fn send_meme(ctx: &Context, t: &Meme, conn: &mut PgConnection, msg: &Message) -> Result<()> { let should_tts = t.content.as_ref().map(|t| t.len() > 0).unwrap_or(false) && thread_rng().gen::() % 25 == 0; 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 = RawPgConnMgr::new(DB_CONFIG.clone(), NoTls); } + #[inline] pub fn connection() -> Result { - 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 { - RAW_CONN_MGR.connect().map_err(Error::from) -} + // HACK + if !MIGRATE.is_completed() { + connection()?; + } -pub fn find_meme>(conn: &PgConnection, search: T) -> Result { - use diesel::dsl::sql; - use diesel::sql_types::Text; + RAW_CONN_MGR.connect() + .map_err(Error::from) +} +pub fn find_meme>(conn: &mut PgConnection, search: T) -> Result { let search = search.as_ref(); let mut meme = memes::table @@ -67,7 +84,7 @@ pub fn find_meme>(conn: &PgConnection, search: T) -> Result let format_search = format!("%{}%", search); meme = memes::table - .filter(memes::title.ilike(&format_search).or(sql("content ILIKE ").bind::(&format_search))) + .filter(memes::title.ilike(&format_search).or(memes::content.ilike(&format_search))) .limit(1) .first::(conn); } @@ -121,26 +138,26 @@ pub fn query_meme>(search: T, user_id: Option, age_desc: bool Ok(result) } -pub fn delete_meme>(conn: &PgConnection, search: T, deleted_by: u64) -> Result<()> { - conn.transaction::<(), Error, _>(|| { +pub fn delete_meme>(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::(conn)?; + .first::(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>(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>(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 { +pub fn rare_meme(conn: &mut PgConnection, audio: bool) -> Result { use rand::prelude::*; let mut raw_conn = raw_connection()?; @@ -227,7 +244,7 @@ pub fn rare_meme(conn: &PgConnection, audio: bool) -> Result { Meme::find(conn, meme_id) } -pub fn rand_meme(conn: &PgConnection, audio: bool) -> Result { +pub fn rand_meme(conn: &mut PgConnection, audio: bool) -> Result { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec = if audio { @@ -256,7 +273,7 @@ pub fn rand_meme(conn: &PgConnection, audio: bool) -> Result { .map_err(Error::from) } -pub fn rand_audio_meme(conn: &PgConnection) -> Result { +pub fn rand_audio_meme(conn: &mut PgConnection) -> Result { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec = memes::table @@ -274,7 +291,7 @@ pub fn rand_audio_meme(conn: &PgConnection) -> Result { .map_err(Error::from) } -pub fn rand_silent_meme(conn: &PgConnection) -> Result { +pub fn rand_silent_meme(conn: &mut PgConnection) -> Result { use rand::{thread_rng, seq::SliceRandom}; let ids: Vec = memes::table @@ -323,7 +340,7 @@ pub struct Stats { pub most_popular_meme_overall_count: usize, } -pub fn stats(conn: &PgConnection) -> Result { +pub fn stats(conn: &mut PgConnection) -> Result { 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> { + pub fn image(&self, conn: &mut PgConnection) -> Option> { 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> { + pub fn audio(&self, conn: &mut PgConnection) -> Option> { 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 { + pub fn find(conn: &mut PgConnection, id: i32) -> Result { 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 { + pub fn save(mut self, conn: &mut PgConnection, by_user: u64) -> Result { 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, by_user: u64) -> Result { + pub fn create(conn: &mut PgConnection, data: Vec, by_user: u64) -> Result { 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, by_user: u64) -> Result { + pub fn create(conn: &mut PgConnection, filename: &str, data: Vec, by_user: u64) -> Result { 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 { + pub fn create(conn: &mut PgConnection, by_user: u64) -> Result { ::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 { + pub fn find(conn: &mut PgConnection, id: i32) -> Result { metadata::table.find(id) .get_result::(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 { + pub fn create(conn: &mut PgConnection, metadata: i32, by_user: u64) -> Result { ::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 { + pub fn create(conn: &mut PgConnection, user_id: u64, message_id: u64, meme_id: i32, random: bool) -> Result { ::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 { + pub fn last(conn: &mut PgConnection) -> Result { invocation_records::table .order(invocation_records::time.desc()) .first(conn) .map_err(Error::from) } - pub fn last_n(conn: &PgConnection, n: usize) -> Result> { + pub fn last_n(conn: &mut PgConnection, n: usize) -> Result> { invocation_records::table .order(invocation_records::time.desc()) .limit(n as i64) -- cgit v1.3.1