repo/sqlite: add task struct

- repo/sqlite: add method to get active tasks
This commit is contained in:
Dmitriy Pleshevskiy 2022-08-17 10:29:48 +03:00
parent 85497018c4
commit 78cbc633c4
Signed by: pleshevskiy
GPG Key ID: 1B59187B161C0215
6 changed files with 106 additions and 17 deletions

29
Cargo.lock generated
View File

@ -182,6 +182,15 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.0" version = "1.13.0"
@ -274,6 +283,7 @@ dependencies = [
"hashlink", "hashlink",
"libsqlite3-sys", "libsqlite3-sys",
"smallvec", "smallvec",
"time",
] ]
[[package]] [[package]]
@ -339,6 +349,7 @@ dependencies = [
"rusqlite", "rusqlite",
"serde", "serde",
"serde_json", "serde_json",
"time",
"xdg", "xdg",
] ]
@ -368,6 +379,24 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "time"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45"
dependencies = [
"itoa",
"libc",
"num_threads",
"time-macros",
]
[[package]]
name = "time-macros"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.3" version = "1.0.3"

View File

@ -12,7 +12,8 @@ maintenance = { status = "experimental" }
[dependencies] [dependencies]
clap = { version = "3.2.16", default-features = false, features = ["derive", "std"] } clap = { version = "3.2.16", default-features = false, features = ["derive", "std"] }
log = "0.4.17" log = "0.4.17"
rusqlite = { version = "0.28.0", features = ["bundled"] } rusqlite = { version = "0.28.0", features = ["bundled", "time"] }
serde = { version = "1.0.142", features = ["derive"] } serde = { version = "1.0.142", features = ["derive"] }
serde_json = "1.0.83" serde_json = "1.0.83"
time = "0.3"
xdg = "2.4.1" xdg = "2.4.1"

View File

@ -5,9 +5,9 @@ CREATE TABLE _tas_info (
CREATE TABLE tasks ( CREATE TABLE tasks (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
group TEXT NULL, project TEXT NULL,
link TEXT NULL, link TEXT NULL,
path TEXT NULL, dir_path TEXT NULL,
current BOOLEAN NOT NULL DEFAULT false, current BOOLEAN NOT NULL DEFAULT false,
@ -16,10 +16,9 @@ CREATE TABLE tasks (
); );
CREATE VIEW active_tasks AS ( CREATE VIEW active_tasks AS (
SELECT * SELECT t.*
FROM tasks FROM tasks AS t
WHERE finished_at IS NULL WHERE t.finished_at IS NULL
ORDER BY created_at ORDER BY t.created_at
); );
;

View File

@ -5,9 +5,9 @@ CREATE TABLE _tas_info (
CREATE TABLE tasks ( CREATE TABLE tasks (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
group TEXT NULL, project TEXT NULL,
link TEXT NULL, link TEXT NULL,
path TEXT NULL, dir_path TEXT NULL,
current BOOLEAN NOT NULL DEFAULT false, current BOOLEAN NOT NULL DEFAULT false,
@ -16,9 +16,8 @@ CREATE TABLE tasks (
); );
CREATE VIEW active_tasks AS ( CREATE VIEW active_tasks AS (
SELECT * SELECT t.*
FROM tasks FROM tasks AS t
WHERE finished_at IS NULL WHERE t.finished_at IS NULL
ORDER BY created_at ORDER BY t.created_at
); );

View File

@ -23,6 +23,8 @@ use crate::domain;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Connect, Connect,
PrepareQuery,
QueryData,
NotFound, NotFound,
InvalidData, InvalidData,
InsertData, InsertData,
@ -31,6 +33,9 @@ pub enum Error {
impl std::fmt::Display for Error { impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Error::Connect => f.write_str("Cannot connect to the repository"),
Error::PrepareQuery => f.write_str("Cannot prepare query"),
Error::QueryData => f.write_str("Cannot query data"),
Error::NotFound => f.write_str("Cannot find data"), Error::NotFound => f.write_str("Cannot find data"),
Error::InvalidData => f.write_str("Invalid data format"), Error::InvalidData => f.write_str("Invalid data format"),
Error::InsertData => f.write_str("Cannot insert data"), Error::InsertData => f.write_str("Cannot insert data"),

View File

@ -1,9 +1,52 @@
use std::path::PathBuf;
use rusqlite::Connection; use rusqlite::Connection;
use xdg::BaseDirectories; use xdg::BaseDirectories;
use crate::domain; use crate::domain;
use crate::repo::{Error, Repository}; use crate::repo::{Error, Repository};
struct Task {
id: i64,
name: String,
project: Option<String>,
link: Option<String>,
dir_path: Option<String>,
current: bool,
created_at: time::OffsetDateTime,
finished_at: Option<time::OffsetDateTime>,
}
impl From<Task> for domain::Task {
fn from(repo: Task) -> Self {
Self {
name: repo.name,
project: repo.project,
link: repo.link,
dir_path: repo.dir_path.map(PathBuf::from),
}
}
}
impl<'r> TryFrom<&'r rusqlite::Row<'_>> for Task {
type Error = rusqlite::Error;
fn try_from(row: &'r rusqlite::Row<'_>) -> Result<Self, Self::Error> {
Ok(Self {
id: row.get("id")?,
name: row.get("name")?,
project: row.get("project")?,
link: row.get("link")?,
dir_path: row.get("dir_path")?,
current: row.get("current")?,
created_at: row.get("created_at")?,
finished_at: row.get("finished_at")?,
})
}
}
const SCHEMA_FILE: &str = "schema.sql"; const SCHEMA_FILE: &str = "schema.sql";
pub struct SqliteRepo { pub struct SqliteRepo {
@ -28,8 +71,21 @@ impl Repository for SqliteRepo {
} }
fn get_tasks(&self) -> Result<Vec<domain::Task>, Error> { fn get_tasks(&self) -> Result<Vec<domain::Task>, Error> {
todo!() let mut stmt = self
.conn
.prepare("SELECT * FROM active_tasks")
.map_err(|_| Error::PrepareQuery)?;
let rows = stmt
.query_map([], |row| Task::try_from(row))
.map_err(|_| Error::QueryData)?;
rows.into_iter()
.map(|db_task| db_task.map(From::from).map_err(|_| Error::QueryData))
.collect::<Result<Vec<_>, Error>>()
.map_err(|_| Error::InvalidData)
} }
fn remove_task(&self, id: domain::TaskId) -> Result<domain::Task, Error> { fn remove_task(&self, id: domain::TaskId) -> Result<domain::Task, Error> {
todo!() todo!()
} }