tiempo-rs/src/database.rs

89 lines
2.5 KiB
Rust

use std::path::Path;
use rusqlite::{Connection, ToSql};
use crate::error;
use crate::models::{Entry, Meta};
use crate::types::Time;
pub trait Database {
/// This is used to create tables and insert rows
fn execute(&mut self, query: &str, params: &[&dyn ToSql]) -> error::Result<()>;
/// And this is used to retrieve data
fn entry_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Entry>>;
fn meta_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Meta>>;
// Entry queries
fn entries_by_sheet(&mut self, sheet: &str) -> error::Result<Vec<Entry>> {
self.entry_query("select * from entries where sheet=?1", &[&sheet])
}
fn entry_insert(&mut self, at: Time, note: String) -> error::Result<()> {
self.execute("", &[])
}
// Meta queries
fn current_sheet(&self) -> error::Result<Option<String>> {
let results = self.meta_query("select * from meta where key=?1", &[&"current_sheet"])?;
Ok(results.into_iter().next().map(|m| m.value))
}
}
pub struct SqliteDatabase {
connection: Connection,
}
impl SqliteDatabase {
pub fn from_memory() -> error::Result<impl Database> {
Ok(SqliteDatabase {
connection: Connection::open_in_memory()?,
})
}
pub fn from_path<P: AsRef<Path>>(path: P) -> error::Result<impl Database> {
Ok(SqliteDatabase {
connection: Connection::open(path)?,
})
}
}
impl Database for SqliteDatabase {
fn execute(&mut self, query: &str, params: &[&dyn ToSql]) -> error::Result<()> {
self.connection.execute(query, params)?;
Ok(())
}
fn entry_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Entry>> {
let mut stmt = self.connection.prepare(query)?;
let results = stmt.query_map(params, |row| {
let x = Ok(Entry {
id: row.get("id")?,
note: row.get("note")?,
start: row.get("start")?,
end: row.get("end")?,
sheet: row.get("sheet")?,
});
x})?.filter_map(|r| r.ok()).collect();
Ok(results)
}
fn meta_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Meta>> {
let mut stmt = self.connection.prepare(query)?;
let results = stmt.query_map(params, |row| Ok(Meta {
id: row.get("id")?,
key: row.get("key")?,
value: row.get("value")?,
}))?.filter_map(|r| r.ok()).collect();
Ok(results)
}
}