use crate::project::{Project, Task};
use rusqlite::{Connection, params};
use std::path::PathBuf;
#[derive(Debug)]
pub struct DB {
conn: Connection,
}
impl DB {
pub fn new(path: PathBuf) -> rusqlite::Result<Self> {
let conn = Connection::open(path)?;
conn.execute("PRAGMA foreign_keys = ON;", params![])?;
Ok(DB { conn })
}
pub fn init(&self) -> rusqlite::Result<()> {
self.conn.execute(
"CREATE TABLE IF NOT EXISTS Project (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL
)",
(),
)?;
self.conn.execute(
"CREATE TABLE IF NOT EXISTS Task (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
is_done INTEGER NOT NULL DEFAULT 0,
proj_id INTEGER NOT NULL,
FOREIGN KEY (proj_id) REFERENCES Project (id) ON DELETE CASCADE
)",
(),
)?;
Ok(())
}
pub fn insert_new_project(&self, project_title: &String) -> rusqlite::Result<i64> {
self.conn.execute(
"INSERT INTO Project (title) VALUES (?)",
params![project_title],
)?;
let id = self.conn.last_insert_rowid();
Ok(id)
}
pub fn delete_project_by_id(&self, proj_id: i64) -> rusqlite::Result<()> {
self
.conn
.execute("DELETE FROM Project WHERE id = ?", params![proj_id])?;
Ok(())
}
pub fn get_all_projects(&self) -> rusqlite::Result<Vec<Project>> {
let mut stmt = self.conn.prepare("SELECT id, title FROM Project")?;
let proj_iter = stmt.query_map(params![], |row| {
Ok(Project::new(row.get(0)?, row.get(1)?, vec![]))
})?;
let mut all_projects = Vec::new();
for proj in proj_iter {
all_projects.push(proj?);
}
Ok(all_projects)
}
pub fn rename_project_by_id(&self, new_title: &String, proj_id: i64) -> rusqlite::Result<()> {
self.conn.execute(
"UPDATE Project SET title = ? WHERE id = ?",
params![new_title, proj_id],
)?;
Ok(())
}
pub fn insert_new_task_in_project(
&self,
task_title: &String,
proj_id: i64,
) -> rusqlite::Result<i64> {
self.conn.execute(
"INSERT INTO Task (title, proj_id) VALUES (?, ?)",
params![task_title, proj_id],
)?;
let id = self.conn.last_insert_rowid();
Ok(id)
}
pub fn delete_task_by_id(&self, task_id: i64) -> rusqlite::Result<()> {
self
.conn
.execute("DELETE FROM Task WHERE id = ?", params![task_id])?;
Ok(())
}
pub fn rename_task_by_id(&self, task_id: i64, new_title: &String) -> rusqlite::Result<()> {
self.conn.execute(
"UPDATE Task SET title = ? WHERE id = ?",
params![new_title, task_id],
)?;
Ok(())
}
pub fn update_task_status(&self, task_id: i64, is_done: bool) -> rusqlite::Result<()> {
self.conn.execute(
"UPDATE Task SET is_done = ? WHERE id = ?",
params![is_done, task_id],
)?;
Ok(())
}
pub fn get_all_tasks_in_project(&self, proj_id: i64) -> rusqlite::Result<Vec<Task>> {
let mut stmt = self
.conn
.prepare("SELECT id, title, is_done FROM Task WHERE proj_id = ?")?;
let task_iter = stmt.query_map(params![proj_id], |row| {
Ok(Task::new(
row.get(0)?,
row.get(1)?,
row.get::<_, i32>(2)? != 0,
))
})?;
let mut all_tasks = Vec::new();
for task in task_iter {
all_tasks.push(task?);
}
Ok(all_tasks)
}
}