repo/sqlite: implement methods

- get list
- get one
- insert
- remove
This commit is contained in:
Dmitriy Pleshevskiy 2022-08-19 19:06:00 +03:00
parent 78cbc633c4
commit a6cb3c7804
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
4 changed files with 102 additions and 27 deletions

View file

@ -5,20 +5,22 @@ CREATE TABLE _tas_info (
CREATE TABLE tasks (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
project TEXT NULL,
link TEXT NULL,
dir_path TEXT NULL,
project TEXT ,
link TEXT ,
dir_path TEXT ,
current BOOLEAN NOT NULL DEFAULT false,
created_at DATETIME NOT NULL DEFAULT datetime('now'),
finished_at DATETIME NULL
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
finished_at DATETIME
);
CREATE VIEW active_tasks AS (
SELECT t.*
FROM tasks AS t
WHERE t.finished_at IS NULL
ORDER BY t.created_at
);
CREATE VIEW active_tasks
AS
SELECT
t.*,
row_number() OVER (ORDER BY t.created_at) AS idx
FROM tasks AS t
WHERE t.finished_at IS NULL
ORDER BY t.created_at
;

View file

@ -5,19 +5,22 @@ CREATE TABLE _tas_info (
CREATE TABLE tasks (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
project TEXT NULL,
link TEXT NULL,
dir_path TEXT NULL,
project TEXT ,
link TEXT ,
dir_path TEXT ,
current BOOLEAN NOT NULL DEFAULT false,
created_at DATETIME NOT NULL DEFAULT datetime('now'),
finished_at DATETIME NULL
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
finished_at DATETIME
);
CREATE VIEW active_tasks AS (
SELECT t.*
FROM tasks AS t
WHERE t.finished_at IS NULL
ORDER BY t.created_at
);
CREATE VIEW active_tasks
AS
SELECT
t.*,
row_number() OVER (ORDER BY t.created_at) AS idx
FROM tasks AS t
WHERE t.finished_at IS NULL
ORDER BY t.created_at
;

View file

@ -28,6 +28,7 @@ pub enum Error {
NotFound,
InvalidData,
InsertData,
RemoveData,
}
impl std::fmt::Display for Error {
@ -39,6 +40,7 @@ impl std::fmt::Display for Error {
Error::NotFound => f.write_str("Cannot find data"),
Error::InvalidData => f.write_str("Invalid data format"),
Error::InsertData => f.write_str("Cannot insert data"),
Error::RemoveData => f.write_str("Cannot remove data"),
}
}
}

View file

@ -1,6 +1,6 @@
use std::path::PathBuf;
use rusqlite::Connection;
use rusqlite::{Connection, OptionalExtension};
use xdg::BaseDirectories;
use crate::domain;
@ -17,6 +17,8 @@ struct Task {
created_at: time::OffsetDateTime,
finished_at: Option<time::OffsetDateTime>,
idx: i64,
}
impl From<Task> for domain::Task {
@ -43,6 +45,7 @@ impl<'r> TryFrom<&'r rusqlite::Row<'_>> for Task {
current: row.get("current")?,
created_at: row.get("created_at")?,
finished_at: row.get("finished_at")?,
idx: row.get("idx")?,
})
}
}
@ -57,17 +60,53 @@ impl SqliteRepo {
pub fn new(xdg_dirs: BaseDirectories) -> Result<Self, Error> {
let file_path = xdg_dirs.get_data_file(SCHEMA_FILE);
let conn = Connection::open(file_path).map_err(|_| Error::Connect)?;
/*
conn.execute_batch(&format!(
"BEGIN; {} COMMIT;",
include_str!("../../database/schema.sql")
))
.map_err(|err| match err {
rusqlite::Error::SqlInputError { .. } => panic!("{}", err),
_ => err,
})
.ok();
*/
Ok(Self { conn })
}
}
impl Repository for SqliteRepo {
fn get_current_task_opt(&self) -> Result<Option<domain::CurrentTaskInfo>, Error> {
todo!()
let mut stmt = self
.conn
.prepare("SELECT * FROM active_tasks WHERE current IS true")
.map_err(|_| Error::PrepareQuery)?;
let row = stmt
.query_row([], |row| Task::try_from(row))
.optional()
.map_err(|_| Error::QueryData)?;
Ok(row.map(|db_task| domain::CurrentTaskInfo {
task_idx: db_task.idx as usize,
task: db_task.into(),
}))
}
fn get_task_opt(&self, id: domain::TaskId) -> Result<Option<domain::Task>, Error> {
todo!()
let mut stmt = self
.conn
.prepare("SELECT * FROM active_tasks WHERE idx = ?")
.map_err(|_| Error::PrepareQuery)?;
let row = stmt
.query_row([id as i64], |row| Task::try_from(row))
.optional()
.map_err(|_| Error::QueryData)?;
Ok(row.map(From::from))
}
fn get_tasks(&self) -> Result<Vec<domain::Task>, Error> {
@ -87,11 +126,40 @@ impl Repository for SqliteRepo {
}
fn remove_task(&self, id: domain::TaskId) -> Result<domain::Task, Error> {
todo!()
let task = self.get_task_opt(id)?.ok_or(Error::NotFound)?;
let mut stmt = self
.conn
.prepare("DELETE FROM tasks WHERE id = ?")
.map_err(|_| Error::PrepareQuery)?;
stmt.execute([&(id as i64)])
.map_err(|_| Error::RemoveData)?;
Ok(task)
}
fn insert_task(&self, insert_data: super::InsertTaskData) -> Result<domain::Task, Error> {
todo!()
let mut stmt = self
.conn
.prepare(
"INSERT INTO tasks (name, project, link, dir_path)
VALUES (?1, ?2, ?3, ?4)",
)
.map_err(|_| Error::PrepareQuery)?;
let id = stmt
.insert((
&insert_data.name,
&insert_data.project,
&insert_data.link,
&insert_data
.dir_path
.and_then(|p| p.into_os_string().into_string().ok()),
))
.map_err(|_| Error::InsertData)?;
self.get_task_opt(id as usize)?.ok_or(Error::NotFound)
}
fn update_task(