rex_db/
lib.rs

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
11// pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../db/src/migrations");
12pub 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    // TODO: Start using cache
70    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}