use anyhow::Result; use chrono::{NaiveDate, NaiveTime}; use rusqlite::{params, Connection}; use rusqlite_migration::{Migrations, M}; use uuid::Uuid; use crate::model::event::Event; pub fn init(db_path: &str) -> Result { let mut conn = Connection::open(db_path)?; let migrations = Migrations::new(vec![M::up(include_str!("migrations/1-init.sql"))]); migrations.to_latest(&mut conn)?; Ok(conn) } pub fn insert(conn: &Connection, event: &Event) -> Result<()> { let repetition = match &event.repetition { Some(r) => Some(serde_json::to_string(&r)?), None => None, }; conn.execute( "INSERT INTO events (id, date, start, end, name, repetition, created, updated) VALUES (?, ?, ?, ?, ?, ?, datetime(), datetime())", params![event.id.to_hyphenated().to_string(), event.date, event.start, event.end, event.name, repetition] )?; Ok(()) } pub fn update(conn: &Connection, event: &Event) -> Result<()> { let repetition = match &event.repetition { Some(r) => Some(serde_json::to_string(&r)?), None => None, }; conn.execute( "UPDATE events SET date = ?, start = ?, end = ?, name = ?, repetition = ?, updated = datetime() WHERE id = ?", params![event.date, event.start, event.end, event.name, repetition, event.id.to_hyphenated().to_string()] )?; Ok(()) } pub fn delete(conn: &Connection, id: &Uuid) -> Result<()> { conn.execute( "DELETE FROM events WHERE id = ?", params![id.to_hyphenated().to_string()], )?; Ok(()) } pub fn list_recurring(conn: &Connection) -> Result> { let mut stmt = conn.prepare( " SELECT id, date, start, end, name, repetition FROM events WHERE repetition IS NOT NULL", )?; let iter = stmt.query_map([], |row| { Ok(read_recurring_event( row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?, )) })?; let mut res = vec![]; for event in iter { res.push(event??) } Ok(res) } fn read_recurring_event( uuid: String, date: NaiveDate, start: Option, end: Option, name: String, repetition: Option, ) -> Result { let id = Uuid::parse_str(&uuid)?; let repetition = match repetition { Some(r) => Some(serde_json::from_str(&r)?), None => None, }; Ok(Event { id, date, start, end, name, repetition, }) } pub fn list_non_recurring_between( conn: &Connection, start: NaiveDate, end: NaiveDate, ) -> Result> { let mut stmt = conn.prepare( " SELECT id, date, start, end, name FROM events WHERE repetition IS NULL AND date >= ? AND date <= ? ", )?; let iter = stmt.query_map([start, end], |row| { let uuid: String = row.get(0)?; let date = row.get(1)?; let start = row.get(2)?; let end = row.get(3)?; let name = row.get(4)?; Ok(Uuid::parse_str(&uuid).map(|id| Event { id, date, start, end, name, repetition: None, })) })?; let mut res = vec![]; for event in iter { res.push(event??) } Ok(res) }