aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/factoids/database.rs
blob: 522c9d03ea86e1c88a38eb607705a376cf7cf670 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#[cfg(feature = "mysql")]
extern crate dotenv;

use std::collections::HashMap;

#[cfg(feature = "mysql")]
use diesel::prelude::*;

#[cfg(feature = "mysql")]
use diesel::mysql::MysqlConnection;

use chrono::NaiveDateTime;

pub enum DbResponse {
    Success,
    Failed(&'static str),
}

#[cfg_attr(feature = "mysql", derive(Queryable))]
#[derive(Clone, Debug)]
pub struct Factoid {
    pub name: String,
    pub idx: i32,
    pub content: String,
    pub author: String,
    pub created: NaiveDateTime,
}

#[cfg_attr(feature = "mysql", derive(Insertable))]
#[cfg_attr(feature = "mysql", table_name="factoids")]
pub struct NewFactoid<'a> {
    pub name: &'a str,
    pub idx: i32,
    pub content: &'a str,
    pub author: &'a str,
    pub created: NaiveDateTime,
}


pub trait Database: Send {
    fn insert(&mut self, factoid: &NewFactoid) -> DbResponse;
    fn get(&self, name: &str, idx: i32) -> Option<Factoid>;
    fn count(&self, name: &str) -> Result<i32, &'static str>;
}

// HashMap
impl Database for HashMap<(String, i32), Factoid> {
    fn insert(&mut self, factoid: &NewFactoid) -> DbResponse {
        let factoid = Factoid {
            name: String::from(factoid.name),
            idx: factoid.idx,
            content: factoid.content.to_string(),
            author: factoid.author.to_string(),
            created: factoid.created,
        };

        let name = String::from(factoid.name.clone());
        match self.insert((name, factoid.idx), factoid) {
            None => DbResponse::Success,
            Some(_) => DbResponse::Failed("Factoid was overwritten"),
        }
    }

    fn get(&self, name: &str, idx: i32) -> Option<Factoid> {
        self.get(&(String::from(name), idx)).map(|f| f.clone())
    }

    fn count(&self, name: &str) -> Result<i32, &'static str> {
        Ok(self.iter()
               .filter(|&(&(ref n, _), _)| n == name)
               .count() as i32)
    }
}

// MySql
#[cfg(feature = "mysql")]
table! {
    factoids (name, idx) {
        name -> Varchar,
        idx -> Integer,
        content -> Text,
        author -> Varchar,
        created -> Timestamp,
    }
}

#[cfg(feature = "mysql")]
impl Database for MysqlConnection {
    fn insert(&mut self, factoid: &NewFactoid) -> DbResponse {
        use diesel;

        match diesel::insert_into(factoids::table)
                  .values(factoid)
                  .execute(self) {
            Ok(_) => DbResponse::Success,
            Err(_) => DbResponse::Failed("Database error - possible duplicate"),
        }
    }

    fn get(&self, name: &str, idx: i32) -> Option<Factoid> {
        factoids::table
            .find((name, idx))
            .limit(1)
            .load::<Factoid>(self)
            .ok()
            .and_then(|v| v.into_iter().next())
    }

    fn count(&self, name: &str) -> Result<i32, &'static str> {
        let count: Result<i64, _> = factoids::table
            .filter(factoids::columns::name.eq(name))
            .count()
            .first(self);

        match count {
            Ok(c) => Ok(c as i32),
            Err(_) => Err("Database Error"),
        }
    }
}