diff options
Diffstat (limited to 'src/list.rs')
| -rw-r--r-- | src/list.rs | 142 |
1 files changed, 55 insertions, 87 deletions
diff --git a/src/list.rs b/src/list.rs index 4222cbf..8624650 100644 --- a/src/list.rs +++ b/src/list.rs @@ -58,22 +58,21 @@ impl DBExecutable for UserQuery<'_> { type T = User; fn execute(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<Self::T>> { match self { - UserQuery::Insert(_, _) => self.db_insert(tx), - UserQuery::Delete(_) => self.db_delete(tx), - UserQuery::QueryByEmail(_) => self.db_query_by_email(tx), + UserQuery::Insert(name, email) => self.db_insert(tx, name, email), + UserQuery::Delete(email) => self.db_delete(tx, email), + UserQuery::QueryByEmail(email) => self.db_query_by_email(tx, email), UserQuery::QueryAll => self.db_query_all(tx), } } } impl UserQuery<'_> { - fn db_insert(&self, tx: &rusqlite::Transaction<'_>) -> Result<QueryResult<User>> { - let (name, email) = if let UserQuery::Insert(name, email) = self { - (name, email) - } else { - unreachable!("this should only be called by a UserQuery::Insert") - }; - + fn db_insert( + &self, + tx: &rusqlite::Transaction<'_>, + name: &Option<&str>, + email: &str, + ) -> Result<QueryResult<User>> { if let Some(name) = name { let q = "INSERT INTO user (name, email) VALUES (?, ?)"; tx.execute(q, [name, email])?; @@ -85,25 +84,17 @@ impl UserQuery<'_> { Ok(QueryResult::Empty) } - fn db_delete(&self, tx: &rusqlite::Transaction<'_>) -> Result<QueryResult<User>> { - let email = if let UserQuery::Delete(email) = self { - email - } else { - unreachable!("this should only be called by a UserQuery::Delete") - }; - + fn db_delete(&self, tx: &rusqlite::Transaction<'_>, email: &str) -> Result<QueryResult<User>> { let q = "DELETE FROM user WHERE email = ?"; tx.execute(q, [email])?; Ok(QueryResult::Empty) } - fn db_query_by_email(&self, tx: &rusqlite::Transaction<'_>) -> Result<QueryResult<User>> { - let email = if let UserQuery::QueryByEmail(email) = self { - email - } else { - unreachable!("this should only be called by a UserQuery::QueryByEmail") - }; - + fn db_query_by_email( + &self, + tx: &rusqlite::Transaction<'_>, + email: &str, + ) -> Result<QueryResult<User>> { let q = "SELECT * FROM user WHERE email LIKE ?"; let mut stmt = tx.prepare(q)?; let ris = stmt @@ -168,7 +159,7 @@ impl List { enum ListQuery<'a> { Insert(&'a str, Option<&'a str>), Delete(&'a str), - QueryByAddress(&'a str), + QueryByName(&'a str), QueryAll, } @@ -177,22 +168,21 @@ impl DBExecutable for ListQuery<'_> { 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::Insert(name, desc) => self.db_insert(tx, name, desc), + ListQuery::Delete(name) => self.db_delete(tx, name), + ListQuery::QueryByName(name) => self.db_query_by_address(tx, name), 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"); - }; - + fn db_insert( + &self, + tx: &rusqlite::Transaction, + name: &str, + desc: &Option<&str>, + ) -> Result<QueryResult<List>> { if let Some(desc) = desc { let q = "INSERT INTO list (name, description) VALUES (?, ?)"; tx.execute(q, [name, desc])?; @@ -203,25 +193,17 @@ impl ListQuery<'_> { 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") - }; - + fn db_delete(&self, tx: &rusqlite::Transaction, name: &str) -> Result<QueryResult<List>> { 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") - }; - + fn db_query_by_address( + &self, + tx: &rusqlite::Transaction, + name: &str, + ) -> Result<QueryResult<List>> { let q = "SELECT * FROM list WHERE name = ?"; let mut stmt = tx.prepare(q)?; let ris = stmt @@ -272,23 +254,22 @@ impl DBExecutable for SubscriptionQuery<'_> { fn execute(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<Self::T>> { match self { - SubscriptionQuery::Insert(_, _) => self.db_insert(tx), + SubscriptionQuery::Insert(email, list_name) => self.db_insert(tx, email, list_name), SubscriptionQuery::Count => self.db_query_all(tx), - SubscriptionQuery::Delete(_, _) => self.db_delete(tx), - SubscriptionQuery::Lists(_) => self.db_lists(tx), - SubscriptionQuery::Subscribers(_) => self.db_subscribers(tx), + SubscriptionQuery::Delete(email, list_name) => self.db_delete(tx, email, list_name), + SubscriptionQuery::Lists(email) => self.db_lists(tx, email), + SubscriptionQuery::Subscribers(list_name) => self.db_subscribers(tx, list_name), } } } impl SubscriptionQuery<'_> { - fn db_insert(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<SubscriptionResult>> { - let (email, list_name) = if let SubscriptionQuery::Insert(a, b) = self { - (a, b) - } else { - unreachable!("this should only be called by SubscriptionQuery::Insert") - }; - + fn db_insert( + &self, + tx: &rusqlite::Transaction, + email: &str, + list_name: &str, + ) -> Result<QueryResult<SubscriptionResult>> { let q = "INSERT INTO subscription SELECT user.id, list.id FROM user CROSS JOIN list WHERE user.email = ? AND list.name = ?"; @@ -298,39 +279,31 @@ impl SubscriptionQuery<'_> { } fn db_query_all(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<SubscriptionResult>> { - match self { - SubscriptionQuery::Count => (), - _ => unreachable!("this should only be called by SubscriptionQuery::Count"), - }; - let q = "SELECT COUNT(*) FROM subscription"; let ris = tx.query_one(q, (), |row| Ok(row.get(0).unwrap()))?; Ok(QueryResult::Single(SubscriptionResult::Count(ris))) } - fn db_delete(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<SubscriptionResult>> { - let (email, name) = if let SubscriptionQuery::Delete(e, n) = self { - (e, n) - } else { - unreachable!("this should only be called by SubscriptionQuery::Delete") - }; - + fn db_delete( + &self, + tx: &rusqlite::Transaction, + email: &str, + list_name: &str, + ) -> Result<QueryResult<SubscriptionResult>> { let q = "WITH helper AS (SELECT user.id AS user_id, list.id AS list_id FROM user CROSS JOIN list WHERE user.email = ? AND list.name = ?) DELETE FROM subscription WHERE EXISTS ( SELECT 1 FROM helper WHERE helper.user_id = subscription.user_id AND helper.list_id = subscription.list_id)"; - tx.execute(q, [email, name])?; + tx.execute(q, [email, list_name])?; Ok(QueryResult::Empty) } - fn db_lists(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<SubscriptionResult>> { - let email = if let SubscriptionQuery::Lists(email) = self { - email - } else { - unreachable!("this should only be called by SubscriptionQuery::Lists") - }; - + fn db_lists( + &self, + tx: &rusqlite::Transaction, + email: &str, + ) -> Result<QueryResult<SubscriptionResult>> { let q = "SELECT list.name, list.description FROM subscription JOIN list ON list.id = subscription.list_id JOIN user ON user.id = subscription.user_id @@ -352,20 +325,15 @@ impl SubscriptionQuery<'_> { fn db_subscribers( &self, tx: &rusqlite::Transaction, + list_name: &str, ) -> Result<QueryResult<SubscriptionResult>> { - let name = if let SubscriptionQuery::Subscribers(name) = self { - name - } else { - unreachable!("this should only be called by SubscriptionQuery::Subscribers") - }; - let q = "SELECT user.name, user.email FROM subscription JOIN list ON list.id = subscription.list_id JOIN user ON user.id = subscription.user_id WHERE list.name = ?"; let ris = tx .prepare(q)? - .query([name])? + .query([list_name])? .map(|row| { Ok(SubscriptionResult::Subscriber(User { name: row.get(0).unwrap(), |
