aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/list.rs205
1 files changed, 200 insertions, 5 deletions
diff --git a/src/list.rs b/src/list.rs
index 36cd492..a015da5 100644
--- a/src/list.rs
+++ b/src/list.rs
@@ -122,13 +122,127 @@ impl UserQuery<'_> {
}
}
+#[derive(Debug, PartialEq)]
+struct List {
+ address: String,
+ desc: Option<String>,
+}
+
+impl List {
+ fn new(name: &str) -> Self {
+ List {
+ address: String::from(name),
+ desc: None,
+ }
+ }
+
+ fn insert(&self) -> ListQuery<'_> {
+ ListQuery::Insert(&self.address, self.desc.as_deref())
+ }
+
+ fn delete(&self) -> ListQuery<'_> {
+ ListQuery::Delete(&self.address)
+ }
+
+ fn query_all<'a>() -> ListQuery<'a> {
+ ListQuery::QueryAll
+ }
+}
+
+enum ListQuery<'a> {
+ Insert(&'a str, Option<&'a str>),
+ Delete(&'a str),
+ QueryByAddress(&'a str),
+ QueryAll,
+}
+
+impl DBExecutable for ListQuery<'_> {
+ type T = List;
+
+ fn execute(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<Self::T>> {
+ match self {
+ ListQuery::Insert(_, _) => self.db_insert(tx),
+ ListQuery::Delete(_) => self.db_delete(tx),
+ ListQuery::QueryByAddress(_) => self.db_query_by_address(tx),
+ ListQuery::QueryAll => self.db_query_all(tx),
+ }
+ }
+}
+
+impl ListQuery<'_> {
+ fn db_insert(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<List>> {
+ let (name, desc) = if let ListQuery::Insert(name, desc) = self {
+ (name, desc)
+ } else {
+ unreachable!("this should only be called by ListQuery::Insert");
+ };
+
+ if let Some(desc) = desc {
+ let q = "INSERT INTO list (name, description) VALUES (?, ?)";
+ tx.execute(q, [name, desc])?;
+ } else {
+ let q = "INSERT INTO list (name) VALUES (?)";
+ tx.execute(q, [name])?;
+ }
+ Ok(QueryResult::Empty)
+ }
+
+ fn db_delete(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<List>> {
+ let name = if let ListQuery::Delete(name) = self {
+ name
+ } else {
+ unreachable!("this should only be called by ListQuery::Delete")
+ };
+
+ let q = "DELETE FROM list WHERE name = ?";
+ tx.execute(q, [name])?;
+ Ok(QueryResult::Empty)
+ }
+
+ fn db_query_by_address(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<List>> {
+ let name = if let ListQuery::QueryByAddress(name) = self {
+ name
+ } else {
+ unreachable!("this should only be called by ListQuery::QueryByName")
+ };
+
+ let q = "SELECT * FROM list WHERE name = ?";
+ let mut stmt = tx.prepare(q)?;
+ let ris = stmt
+ .query([name])?
+ .map(|row| {
+ Ok(List {
+ address: row.get(1).unwrap(),
+ desc: row.get(2).unwrap(),
+ })
+ })
+ .collect()?;
+ Ok(QueryResult::Vec(ris))
+ }
+
+ fn db_query_all(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<List>> {
+ let q = "SELECT * FROM list";
+ let mut stmt = tx.prepare(q)?;
+ let ris = stmt
+ .query(())?
+ .map(|row| {
+ Ok(List {
+ address: row.get(1).unwrap(),
+ desc: row.get(2).unwrap(),
+ })
+ })
+ .collect()?;
+ Ok(QueryResult::Vec(ris))
+ }
+}
+
#[cfg(test)]
mod tests {
use anyhow::Result;
use crate::{
database::{DB_NAME, Database},
- list::User,
+ list::{List, User},
};
fn setup() -> Result<Database> {
@@ -142,7 +256,7 @@ mod tests {
}
#[test]
- fn insert_wo_name() {
+ fn user_insert_wo_name() {
let mut database = setup().expect("Failed setup");
let user = User {
@@ -166,7 +280,7 @@ mod tests {
}
#[test]
- fn insert_with_name() {
+ fn user_insert_with_name() {
let mut database = setup().expect("Failed setup");
let user = User {
@@ -190,7 +304,7 @@ mod tests {
}
#[test]
- fn insert_twice() {
+ fn user_insert_twice() {
let mut database = setup().expect("Failed setup");
let user = User {
@@ -206,7 +320,7 @@ mod tests {
}
#[test]
- fn delete() {
+ fn user_delete() {
let mut database = setup().expect("Failed setup");
let user = User {
@@ -227,4 +341,85 @@ mod tests {
drop(database);
cleanup().expect("Failed cleanup");
}
+
+ #[test]
+ fn list_insert_wo_desc() {
+ let mut database = setup().expect("failed setup");
+
+ let list = List {
+ address: String::from("poul"),
+ desc: None,
+ };
+ database.execute(list.insert()).expect("failed insert");
+ let ris = database.execute(List::query_all()).expect("failed query");
+ match ris {
+ crate::database::QueryResult::Empty => assert!(false),
+ crate::database::QueryResult::Vec(items) => {
+ assert_eq!(items.len(), 1);
+ assert_eq!(items[0], list);
+ }
+ }
+
+ cleanup().expect("failed cleanup");
+ }
+
+ #[test]
+ fn list_insert_with_desc() {
+ let mut database = setup().expect("failed setup");
+
+ let list = List {
+ address: String::from("poul"),
+ desc: Some(String::from("The mailing list of the POuL")),
+ };
+ database.execute(list.insert()).expect("failed insert");
+ let ris = database.execute(List::query_all()).expect("failed query");
+ match ris {
+ crate::database::QueryResult::Empty => assert!(false),
+ crate::database::QueryResult::Vec(items) => {
+ assert_eq!(items.len(), 1);
+ assert_eq!(items[0], list);
+ }
+ }
+
+ drop(database);
+ cleanup().expect("failed cleanup");
+ }
+
+ #[test]
+ fn list_insert_twice() {
+ let mut database = setup().expect("failed setup");
+
+ let list = List {
+ address: String::from("poul"),
+ desc: Some(String::from("The mailing list of the POuL")),
+ };
+ database.execute(list.insert()).expect("failed insert");
+ assert!(database.execute(list.insert()).is_err());
+
+ drop(database);
+ cleanup().expect("failed cleanup");
+ }
+
+ #[test]
+ fn list_delete() {
+ let mut database = setup().expect("failed setup");
+
+ let list = List {
+ address: String::from("poul"),
+ desc: Some(String::from("The mailing list of the POuL")),
+ };
+ database.execute(list.insert()).expect("failed insert");
+ database.execute(list.delete()).expect("failed delete");
+
+ let ris = database
+ .execute(List::query_all())
+ .expect("Failed query all");
+ match ris {
+ crate::database::QueryResult::Empty => assert!(false),
+ crate::database::QueryResult::Vec(items) => assert!(items.is_empty()),
+ }
+
+ drop(database);
+ cleanup().expect("failed cleanup");
+ }
}
XMR address: 854DmXNrxULU3ZFJVs4Wc8PFhbq29RhqHhY8W6cdWrtFN3qmooKyyeYPcDzZTNRxphhJ5UzASQfAdEMwSteVqymk28aLhqj