hms_db/
db.rs

1use crate::{
2    models::{NewSnip, Snip},
3    prelude::*,
4    schema::snips::dsl::*,
5};
6use chrono::Utc;
7use diesel::{
8    delete, insert_into,
9    prelude::*,
10    result::{DatabaseErrorKind, Error as DieselError},
11    update,
12};
13
14pub struct HmsDb<'a> {
15    pub conn: &'a mut SqliteConnection,
16}
17
18impl<'a> HmsDb<'a> {
19    pub fn insert_snip(&mut self, new_snip: &NewSnip) -> Result<Snip> {
20        insert_into(snips)
21            .values(new_snip)
22            .returning(Snip::as_returning())
23            .get_result(self.conn)
24            .map_err(|e| match e {
25                DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _) => {
26                    HmsDbError::AliasConstraintError("Alias already in use.".to_string())
27                }
28                DieselError::DatabaseError(DatabaseErrorKind::CheckViolation, _) => {
29                    HmsDbError::AliasConstraintError(
30                        "Alias exceeds length limit (50 characters max).".to_string(),
31                    )
32                }
33                other => HmsDbError::from(other),
34            })
35    }
36
37    pub fn insert_snips(&mut self, new_snips: &Vec<NewSnip>) -> Result<()> {
38        insert_into(snips)
39            .values(new_snips)
40            .execute(self.conn)
41            .map(|_| ())
42            .map_err(|e| match e {
43                DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _) => {
44                    HmsDbError::AliasConstraintError(
45                        "One or more aliases conflict with existing aliases.".to_string(),
46                    )
47                }
48                DieselError::DatabaseError(DatabaseErrorKind::CheckViolation, _) => {
49                    HmsDbError::AliasConstraintError(
50                        "One or more aliases exceed the length limit (50 characters max)."
51                            .to_string(),
52                    )
53                }
54                other => HmsDbError::from(other),
55            })
56    }
57
58    pub fn find_snip_by_id(&mut self, snip_id: i32) -> Result<Snip> {
59        snips
60            .find(snip_id)
61            .get_result(self.conn)
62            .map_err(From::from)
63    }
64
65    pub fn find_snips_by_alias(
66        &mut self,
67        snip_alias: &str,
68        limit: i64,
69        offset: i64,
70    ) -> Result<Vec<Snip>> {
71        snips
72            .filter(alias.like(format!("%{}%", snip_alias)))
73            .limit(limit)
74            .offset(offset)
75            .load::<Snip>(self.conn)
76            .map_err(From::from)
77    }
78
79    pub fn increment_snip_access_count(&mut self, snip: &Snip) -> Result<()> {
80        let now = Utc::now().naive_utc();
81        update(snip)
82            .set((access_count.eq(access_count + 1), last_access.eq(now)))
83            .execute(self.conn)?;
84        Ok(())
85    }
86
87    pub fn delete_snip(&mut self, snip: &Snip) -> Result<()> {
88        delete(snip).execute(self.conn)?;
89        Ok(())
90    }
91
92    pub fn fetch_top_snips_by_access(&mut self, limit: i64) -> Result<Vec<Snip>> {
93        snips
94            .limit(limit)
95            .filter(access_count.gt(0))
96            .order(access_count.desc())
97            .load::<Snip>(self.conn)
98            .map_err(From::from)
99    }
100}