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}