use std::path::Path; use rusqlite::{Connection, ToSql}; use chrono::{DateTime, Utc}; 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>; fn meta_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result>; fn entries_by_sheet(&mut self, sheet: String) -> error::Result> { self.entry_query("some".into(), &[]) } fn entry_insert(&mut self, at: Time, note: String) -> error::Result<()> { self.execute("", &[]) } } pub struct SqliteDatabase { connection: Connection, } impl SqliteDatabase { pub fn from_memory() -> error::Result { Ok(SqliteDatabase { connection: Connection::open_in_memory()?, }) } pub fn from_path>(path: P) -> error::Result { 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> { let mut stmt = self.connection.prepare(query)?; let results = stmt.query_map([], |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> { let mut stmt = self.connection.prepare(query)?; let results = stmt.query_map([], |row| Ok(Meta { id: row.get("id")?, key: row.get("key")?, value: row.get("value")?, }))?.filter_map(|r| r.ok()).collect(); Ok(results) } }