databeam/
database.rs

1//! Database handler
2use super::{
3    prelude::*,
4    sql::{create_db, Database, DatabaseOpts},
5};
6
7use serde::{Deserialize, Serialize};
8use sqlx::{Column, Row};
9use std::collections::BTreeMap;
10
11/// Default API return value
12#[allow(dead_code)]
13#[derive(Debug, Serialize, Deserialize, Clone)]
14pub struct DefaultReturn<T> {
15    pub success: bool,
16    pub message: String,
17    pub payload: T,
18}
19
20/// Basic return type for database output
21#[derive(Debug, Serialize, Deserialize, Clone)]
22pub struct DatabaseReturn(pub BTreeMap<String, String>);
23
24/// Basic database
25#[derive(Clone)]
26#[cfg(feature = "postgres")]
27pub struct StarterDatabase {
28    pub db: Database<sqlx::PgPool>,
29    pub options: DatabaseOpts,
30    #[cfg(feature = "redis")]
31    pub cache: RedisCache,
32    #[cfg(feature = "moka")]
33    pub cache: MokaCache,
34    #[cfg(feature = "oysters")]
35    pub cache: OystersCache,
36}
37
38/// Basic database
39#[derive(Clone)]
40#[cfg(feature = "mysql")]
41pub struct StarterDatabase {
42    pub db: Database<sqlx::MySqlPool>,
43    pub options: DatabaseOpts,
44    #[cfg(feature = "redis")]
45    pub cache: RedisCache,
46    #[cfg(feature = "moka")]
47    pub cache: MokaCache,
48    #[cfg(feature = "oysters")]
49    pub cache: OystersCache,
50}
51
52/// Basic database
53#[derive(Clone)]
54#[cfg(feature = "sqlite")]
55pub struct StarterDatabase {
56    pub db: Database<sqlx::SqlitePool>,
57    pub options: DatabaseOpts,
58    #[cfg(feature = "redis")]
59    pub cache: RedisCache,
60    #[cfg(feature = "moka")]
61    pub cache: MokaCache,
62    #[cfg(feature = "oysters")]
63    pub cache: OystersCache,
64}
65
66impl StarterDatabase {
67    pub async fn new(options: DatabaseOpts) -> StarterDatabase {
68        StarterDatabase {
69            db: create_db(options.clone()).await,
70            options,
71            #[cfg(feature = "redis")]
72            cache: RedisCache::new().await,
73            #[cfg(feature = "moka")]
74            cache: MokaCache::new().await,
75            #[cfg(feature = "oysters")]
76            cache: OystersCache::new().await,
77        }
78    }
79
80    /// Convert all columns into a [`HashMap`].
81    ///
82    /// # Arguments
83    /// * `row`
84    /// * `as_bytes` - a [`Vec`] containing all the columns that we want to read in their original `Vec<u8>` form
85    #[cfg(feature = "sqlite")]
86    pub fn textify_row(&self, row: sqlx::sqlite::SqliteRow) -> DatabaseReturn {
87        // get all columns
88        let columns = row.columns();
89
90        // create output
91        let mut out: BTreeMap<String, String> = BTreeMap::new();
92
93        for column in columns {
94            let name = column.name().to_string();
95            let value = row.get(&name.as_str());
96            out.insert(name, value);
97        }
98
99        // return
100        DatabaseReturn(out)
101    }
102
103    /// Convert all columns into a [`HashMap`].
104    ///
105    /// # Arguments
106    /// * `row`
107    /// * `as_bytes` - a [`Vec`] containing all the columns that we want to read in their original `Vec<u8>` form
108    #[cfg(feature = "postgres")]
109    pub fn textify_row(&self, row: sqlx::postgres::PgRow) -> DatabaseReturn {
110        // get all columns
111        let columns = row.columns();
112
113        // create output
114        let mut out: BTreeMap<String, String> = BTreeMap::new();
115
116        for column in columns {
117            let name = column.name().to_string();
118            let value = row.get(&name.as_str());
119            out.insert(name, value);
120        }
121
122        // return
123        DatabaseReturn(out)
124    }
125
126    /// Convert all columns into a [`HashMap`].
127    ///
128    /// # Arguments
129    /// * `row`
130    /// * `as_bytes` - a [`Vec`] containing all the columns that we want to read in their original `Vec<u8>` form
131    #[cfg(feature = "mysql")]
132    pub fn textify_row(&self, row: sqlx::mysql::MySqlRow) -> DatabaseReturn {
133        // get all columns
134        let columns = row.columns();
135
136        // create output
137        let mut out: BTreeMap<String, String> = BTreeMap::new();
138
139        for column in columns {
140            let name = column.name().to_string();
141
142            match row.try_get::<Vec<u8>, _>(&name.as_str()) {
143                Ok(value) => {
144                    // we're going to convert this to a string and then add it to the output!
145                    out.insert(
146                        column.name().to_string(),
147                        std::str::from_utf8(value.as_slice()).unwrap().to_string(),
148                    );
149                }
150                Err(_) => {
151                    // already text
152                    let value = row.get(&name.as_str());
153                    out.insert(name, value);
154                }
155            };
156        }
157
158        // return
159        DatabaseReturn(out)
160    }
161}