1pub mod models;
2mod schema;
3
4use anyhow::{Result, anyhow};
5use diesel::prelude::*;
6use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
7use std::collections::{HashMap, HashSet};
8
9use crate::models::{FullTx, Tag, TxMethod};
10
11pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("src/migrations");
13
14pub trait ConnCache {
15 fn conn(&mut self) -> &mut SqliteConnection;
16 fn cache(&self) -> &Cache;
17}
18
19#[derive(Clone)]
20pub struct Cache {
21 pub tags: HashMap<i32, Tag>,
22 pub tx_methods: HashMap<i32, TxMethod>,
23 pub txs: Option<HashMap<i32, Vec<FullTx>>>,
24 pub details: HashSet<String>,
25}
26
27impl Cache {
28 pub fn get_method_id(&self, name: &str) -> Result<i32> {
29 self.tx_methods
30 .values()
31 .find(|m| m.name == name)
32 .map(|m| m.id)
33 .ok_or_else(|| anyhow!("method '{name}' not found"))
34 }
35
36 pub fn get_method_by_name(&self, name: &str) -> Result<&TxMethod> {
37 self.tx_methods
38 .values()
39 .find(|m| m.name == name)
40 .ok_or_else(|| anyhow!("method '{name}' not found"))
41 }
42
43 pub fn get_method_by_name_mut(&mut self, name: &str) -> Result<&mut TxMethod> {
44 let method = self.get_method_by_name(name)?.id;
45
46 Ok(self.tx_methods.get_mut(&method).unwrap())
47 }
48
49 pub fn get_tag_id(&self, name: &str) -> Result<i32> {
50 self.tags
51 .values()
52 .find(|m| m.name == name)
53 .map(|m| m.id)
54 .ok_or_else(|| anyhow!("tag '{name}' not found"))
55 }
56
57 pub fn new_tags(&mut self, tags: Vec<Tag>) {
58 for tag in tags {
59 self.tags.insert(tag.id, tag);
60 }
61 }
62
63 pub fn new_tx_methods(&mut self, tx_methods: Vec<TxMethod>) {
64 for tx_method in tx_methods {
65 self.tx_methods.insert(tx_method.id, tx_method);
66 }
67 }
68
69 pub fn set_txs(&mut self, txs: HashMap<i32, Vec<FullTx>>) {
71 self.txs = Some(txs);
72 }
73
74 #[must_use]
75 pub fn get_txs(&self, id: i32) -> Option<&Vec<FullTx>> {
76 if let Some(txs) = &self.txs {
77 return txs.get(&id);
78 }
79
80 None
81 }
82
83 #[must_use]
84 pub fn get_methods(&self) -> Vec<&TxMethod> {
85 let mut methods = self.tx_methods.values().collect::<Vec<&TxMethod>>();
86 methods.sort_by_key(|value| value.position);
87 methods
88 }
89
90 #[must_use]
91 pub fn get_tags_set(&self) -> HashSet<String> {
92 self.tags
93 .values()
94 .map(|m| m.name.clone())
95 .collect::<HashSet<String>>()
96 }
97
98 #[must_use]
99 pub fn get_tags_sorted(&self) -> Vec<&Tag> {
100 let mut tags = self.tags.values().collect::<Vec<&Tag>>();
101 tags.sort_by_key(|value| &value.name);
102 tags
103 }
104}
105
106#[must_use]
107pub fn get_connection(db_url: &str) -> SqliteConnection {
108 let mut conn =
109 SqliteConnection::establish(db_url).expect("Failed to create connection to database");
110
111 conn.run_pending_migrations(MIGRATIONS)
112 .expect("Failed to run database migrations");
113
114 diesel::sql_query("PRAGMA foreign_keys = ON;")
115 .execute(&mut conn)
116 .unwrap();
117
118 conn
119}
120
121#[must_use]
122pub fn get_connection_no_migrations(db_url: &str) -> SqliteConnection {
123 let mut conn =
124 SqliteConnection::establish(db_url).expect("Failed to create connection to database");
125
126 diesel::sql_query("PRAGMA foreign_keys = ON;")
127 .execute(&mut conn)
128 .unwrap();
129
130 conn
131}