1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
mod metadata;
mod tables;

pub use tables::*;

use rusqlite::{Connection, Result, Statement};
use std::path::Path;

#[derive(Debug)]
pub struct SqlReader {
    pub path: String,
}

impl SqlReader {
    fn read_column_from_table<
        T: rusqlite::types::FromSql + std::default::Default,
    >(
        &self,
        column_name: &str,
        table_name: &str,
    ) -> Vec<T> {
        let connection: Connection = get_sql_connection(&self.path);
        let column_names: Vec<String> =
            self.get_table_columns(table_name).unwrap();
        let order_by: String = column_names.join(", ");
        let query: String = format!(
            "SELECT {} FROM {} ORDER BY {}",
            column_name, table_name, order_by
        );
        let mut stmt: Statement = connection.prepare(&query).unwrap();
        let rows = stmt
            .query_map(
                [],
                // |row| row.get::<usize, T>(0)
                |row| match row.get::<usize, T>(0) {
                    Ok(value) => Ok(value),
                    _ => Ok(T::default()),
                },
            )
            .unwrap();
        rows.collect::<Result<Vec<T>>>().unwrap()
    }

    fn get_table_columns(&self, table_name: &str) -> Result<Vec<String>> {
        let connection: Connection = get_sql_connection(&self.path);
        let query = format!("PRAGMA table_info({})", table_name);
        let mut stmt: Statement = connection.prepare(&query)?;
        let rows = stmt.query_map([], |row| row.get::<usize, String>(1))?;
        rows.collect()
    }
}

fn get_sql_connection(path: &String) -> Connection {
    let db_file_path: std::path::PathBuf = Path::new(path).join("analysis.tdf");
    let connection: Connection = Connection::open(&db_file_path).unwrap();
    connection
}

pub trait ReadableFromSql {
    fn from_sql(sql_reader: &SqlReader) -> Self;
}