diff options
Diffstat (limited to 'src/plugins/remind/database.rs')
| -rw-r--r-- | src/plugins/remind/database.rs | 128 |
1 files changed, 119 insertions, 9 deletions
diff --git a/src/plugins/remind/database.rs b/src/plugins/remind/database.rs index c0c127e..e434ec0 100644 --- a/src/plugins/remind/database.rs +++ b/src/plugins/remind/database.rs @@ -1,14 +1,30 @@ -#[cfg(feature = "mysql")] -extern crate dotenv; - use std::collections::HashMap; use std::collections::hash_map::Entry; use std::fmt; +#[cfg(feature = "mysql")] +use std::sync::Arc; + +#[cfg(feature = "mysql")] +use diesel::mysql::MysqlConnection; +#[cfg(feature = "mysql")] +use diesel::prelude::*; +#[cfg(feature = "mysql")] +use r2d2::Pool; +#[cfg(feature = "mysql")] +use r2d2_diesel::ConnectionManager; + +#[cfg(feature = "mysql")] +use failure::ResultExt; + use chrono::NaiveDateTime; use super::error::*; +#[cfg(feature = "mysql")] +static LAST_ID_SQL: &'static str = "SELECT LAST_INSERT_ID()"; + +#[cfg_attr(feature = "mysql", derive(Queryable))] #[derive(Clone, Debug)] pub struct Event { pub id: i64, @@ -16,7 +32,7 @@ pub struct Event { pub content: String, pub author: String, pub time: NaiveDateTime, - pub repeat: Option<u64>, + pub repeat: Option<i64>, } impl fmt::Display for Event { @@ -29,18 +45,20 @@ impl fmt::Display for Event { } } +#[cfg_attr(feature = "mysql", derive(Insertable))] +#[cfg_attr(feature = "mysql", table_name = "events")] #[derive(Debug)] pub struct NewEvent<'a> { pub receiver: &'a str, pub content: &'a str, pub author: &'a str, pub time: &'a NaiveDateTime, - pub repeat: Option<u64>, + pub repeat: Option<i64>, } pub trait Database: Send + Sync { - fn insert_event(&mut self, event: &NewEvent) -> Result<(), RemindError>; - fn update_event_time(&mut self, id: i64, &NaiveDateTime) -> Result<(), RemindError>; + fn insert_event(&mut self, event: &NewEvent) -> Result<i64, RemindError>; + fn update_event_time(&mut self, id: i64, time: &NaiveDateTime) -> Result<(), RemindError>; fn get_events_before(&self, time: &NaiveDateTime) -> Result<Vec<Event>, RemindError>; fn get_user_events(&self, user: &str) -> Result<Vec<Event>, RemindError>; fn get_event(&self, id: i64) -> Result<Event, RemindError>; @@ -49,7 +67,7 @@ pub trait Database: Send + Sync { // HashMap impl Database for HashMap<i64, Event> { - fn insert_event(&mut self, event: &NewEvent) -> Result<(), RemindError> { + fn insert_event(&mut self, event: &NewEvent) -> Result<i64, RemindError> { let mut id = 0; while self.contains_key(&id) { id += 1; @@ -65,7 +83,7 @@ impl Database for HashMap<i64, Event> { }; match self.insert(id, event) { - None => Ok(()), + None => Ok(id), Some(_) => Err(ErrorKind::Duplicate)?, } } @@ -126,3 +144,95 @@ impl Database for HashMap<i64, Event> { } } } + +#[cfg(feature = "mysql")] +mod schema { + table! { + events (id) { + id -> Bigint, + receiver -> Varchar, + content -> Text, + author -> Varchar, + time -> Timestamp, + repeat -> Nullable<Bigint>, + } + } +} + +#[cfg(feature = "mysql")] +use self::schema::events; + +#[cfg(feature = "mysql")] +impl Database for Arc<Pool<ConnectionManager<MysqlConnection>>> { + fn insert_event(&mut self, event: &NewEvent) -> Result<i64, RemindError> { + use diesel::{self, dsl::sql, types::Bigint}; + let conn = &*self.get().context(ErrorKind::NoConnection)?; + + diesel::insert_into(events::table) + .values(event) + .execute(conn) + .context(ErrorKind::MysqlError)?; + + let id = sql::<Bigint>(LAST_ID_SQL) + .get_result(conn) + .context(ErrorKind::MysqlError)?; + + Ok(id) + } + + fn update_event_time(&mut self, id: i64, time: &NaiveDateTime) -> Result<(), RemindError> { + use self::events::columns; + use diesel; + let conn = &*self.get().context(ErrorKind::NoConnection)?; + + match diesel::update(events::table.filter(columns::id.eq(id))) + .set(columns::time.eq(time)) + .execute(conn) + { + Ok(0) => Err(ErrorKind::NotFound)?, + Ok(_) => Ok(()), + Err(e) => Err(e).context(ErrorKind::MysqlError)?, + } + } + + fn get_events_before(&self, time: &NaiveDateTime) -> Result<Vec<Event>, RemindError> { + use self::events::columns; + let conn = &*self.get().context(ErrorKind::NoConnection)?; + + Ok(events::table + .filter(columns::time.lt(time)) + .load::<Event>(conn) + .context(ErrorKind::MysqlError)?) + } + + fn get_user_events(&self, user: &str) -> Result<Vec<Event>, RemindError> { + use self::events::columns; + let conn = &*self.get().context(ErrorKind::NoConnection)?; + + Ok(events::table + .filter(columns::receiver.eq(user)) + .load::<Event>(conn) + .context(ErrorKind::MysqlError)?) + } + + fn get_event(&self, id: i64) -> Result<Event, RemindError> { + let conn = &*self.get().context(ErrorKind::NoConnection)?; + + Ok(events::table + .find(id) + .first(conn) + .context(ErrorKind::MysqlError)?) + } + + fn delete_event(&mut self, id: i64) -> Result<(), RemindError> { + use self::events::columns; + use diesel; + + let conn = &*self.get().context(ErrorKind::NoConnection)?; + match diesel::delete(events::table.filter(columns::id.eq(id))).execute(conn) { + Ok(0) => Err(ErrorKind::NotFound)?, + Ok(_) => Ok(()), + Err(e) => Err(e).context(ErrorKind::MysqlError)?, + } + } +} |
