rest_api/database/
interfaces.rs

1use std::collections::HashMap;
2use std::path::Path;
3use std::fs;
4
5use super::table_schema::SqlTableSchema;
6use super::response::{Sqlite3ResponseBuilder, ResponseBuilder};
7use super::query::{Sqlite3Query, Query};
8
9use sqlite3::{open, Connection};
10use hyper::{Body, Request, Response};
11
12#[derive(Clone, Debug)]
13pub enum SQLType {
14    Null,
15    Integer,
16    Real,
17    Text,
18}
19
20
21type Config = HashMap<String, String>;
22
23#[async_trait::async_trait]
24pub trait DatabaseInterface {
25    // ( connection, existing? (or created) )
26    fn connect(config: &Config) -> (Self, bool)
27        where Self: Sized;
28    fn delete_db(config: &Config)
29        where Self: Sized;
30
31    fn create_tables_from_schemas(&self, schemas: Vec<&SqlTableSchema>) {
32        for schema in schemas {
33            self.table_from_types(schema.name.clone(), &schema.fields)
34        }
35    }
36
37    fn table_from_types(&self, table_name: String, types: &HashMap<String, SQLType>);
38    async fn process_api_request(&self, request: &mut Request<Body>, table: &SqlTableSchema) -> Response<Body>;
39}
40
41pub struct SQLite3Interface {
42    connection: Connection,
43}
44
45#[async_trait::async_trait]
46impl DatabaseInterface for SQLite3Interface {
47    fn connect(config: &Config) -> (Self, bool) {
48        let db_path = config.get("database_path").expect("Can't find 'database_path' config");
49
50        let existing = Path::new(db_path).exists();
51
52        let connection = open(db_path).expect(&format!("Can't open sqlite3 database at: {}", db_path));
53        
54        log::info!("Connected to database at {}", db_path);
55        (
56            Self {
57                connection
58            }
59            , existing
60        )
61    }
62
63    fn table_from_types(&self, table_name: String, types: &HashMap<String, SQLType>) {
64        let mut sql = format!("CREATE TABLE IF NOT EXISTS {} (ID INTEGER PRIMARY KEY,", table_name);
65
66        for (col_name, data_type) in types {
67            sql.push_str(&col_name);
68            let dtype = match data_type {
69                SQLType::Null => " NULL",
70                SQLType::Integer => " INTEGER",
71                SQLType::Real => " REAL",
72                SQLType::Text => " TEXT",
73            };
74            sql.push_str(dtype);
75            sql.push_str(", ")
76        }
77        // remove last ", "
78        sql.remove(sql.len()-1);
79        sql.remove(sql.len()-1);
80        sql.push_str(");");
81
82        log::info!("Creating table with SQL: {}", sql);
83
84        self.connection.execute(sql).expect("Can't create table");
85    }
86    
87    fn delete_db(config: &Config) {
88        let db_path = config.get("database_path").expect("Can't find 'database_path' config");
89        let result = fs::remove_file(db_path);
90
91        match result {
92            Ok(_) => log::info!("Deleted sqlite3 database"),
93            Err(e) => log::error!("Error when deleting sqlite3 database: {}", e)
94        }
95    }
96
97    async fn process_api_request(&self, request: &mut Request<Body>, table: &SqlTableSchema) -> Response<Body> {
98        // GENERATE QUERY
99        let query = Sqlite3Query::from_request(request, table).await;
100
101        if query.is_err() {
102            let error = query.err().unwrap();
103
104            if error.1 {
105                log::warn!("{}", error.0);
106                return Response::builder()
107                    .status(500)
108                    .body(Body::from("Server Error Encountered"))
109                    .unwrap();
110            } else {
111                log::debug!("{}", error.0);
112                return Response::builder()
113                    .status(400)
114                    .body(Body::from("Client Error"))
115                    .unwrap();
116            }
117        }
118
119        // EXECUTE QUERY
120        let query = query.unwrap();
121        let cursor = query.execute_sql(&self.connection);
122
123        if cursor.is_err() {
124            let error = cursor.err().unwrap();
125            log::warn!("{}", error);
126            
127            return Response::builder()
128                    .status(500)
129                    .body(Body::from("Server Error Encountered"))
130                    .unwrap();
131        }
132
133        // CREATE RESPONSE FROM DATA
134        let mut all_data = Vec::new();
135        let mut c = cursor.unwrap();
136        while let Ok(Some(d)) = c.next() {
137            all_data.push(d.to_vec())
138        }
139
140        let response_json_text = Sqlite3ResponseBuilder::from_row_data(all_data);
141        Response::new(Body::from(response_json_text))
142    }
143}
144
145// may be negative side effects
146// must be implemented for 'object safety' over threads
147unsafe impl Send for SQLite3Interface {}
148unsafe impl Sync for SQLite3Interface {}