aboutsummaryrefslogtreecommitdiffstats
path: root/src/local/database.rs
blob: b84bf99cc14c1de23995733851a4ab6a07f29cf6 (plain) (blame)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::path::Path;

use eyre::Result;
use shellexpand;

use rusqlite::{params, Connection};
use rusqlite::NO_PARAMS;

use super::history::History;

pub trait Database {
    fn save(&self, h: History) -> Result<()>;
    fn list(&self) -> Result<()>;
}

// Intended for use on a developer machine and not a sync server.
// TODO: implement IntoIterator
pub struct SqliteDatabase {
    conn: Connection,
}

impl SqliteDatabase{
    pub fn new(path: &str) -> Result<SqliteDatabase> {
        let path = shellexpand::full(path)?;
        let path = path.as_ref();

        debug!("opening sqlite database at {:?}", path);

        let create = !Path::new(path).exists();
        let conn = Connection::open(path)?;

        if create {
            Self::setup_db(&conn)?;
        }

        Ok(SqliteDatabase{
            conn: conn,
        })
    }

    fn setup_db(conn: &Connection) -> Result<()> {
        debug!("running sqlite database setup");

        conn.execute(
            "create table if not exists history (
                 id integer primary key,
                 timestamp integer not null,
                 command text not null,
                 cwd text not null
             )",
            NO_PARAMS,
        )?;

        Ok(())
    }
}

impl Database for SqliteDatabase {
    fn save(&self, h: History) -> Result<()> {
        debug!("saving history to sqlite");

        self.conn.execute(
            "insert into history (
                timestamp, 
                command,
                cwd
             ) values (?1, ?2, ?3)", 
            params![h.timestamp, h.command, h.cwd])?;

        Ok(())
    }

    fn list(&self) -> Result<()> {
        debug!("listing history");
    
        let mut stmt = self.conn.prepare("SELECT timestamp, command, cwd FROM history")?;
        let history_iter = stmt.query_map(params![], |row| {
            Ok(History {
                timestamp: row.get(0)?,
                command: row.get(1)?,
                cwd: row.get(2)?,
            })
        })?;

        for h in history_iter {
            let h = h.unwrap();

            println!("{}:{}:{}", h.timestamp, h.cwd, h.command);
        }

        Ok(())
    }
}