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