aboutsummaryrefslogtreecommitdiff
path: root/src/list.rs
diff options
context:
space:
mode:
authorMroik <mroik@delayed.space>2026-04-03 17:01:22 +0200
committerMroik <mroik@delayed.space>2026-04-13 06:55:26 +0200
commit6514efe4a5a9cae3707c334290817f628e9c013d (patch)
treec809fe872f5ca57c9765abfa46f05770237869ec /src/list.rs
parenteda31c4e25979e20f814510b5142ce79c8a9d24e (diff)
Refactor to avoid double checks on types
The various Query enums limit themselves to checking which variant they are before choosing a which function to call to process the request. Because they are enums with multiple variants, to unpack we have to check again which variant they are. Unpack before the call and modify function signatures to receive the already unpacked values. Signed-off-by: Mroik <mroik@delayed.space>
Diffstat (limited to 'src/list.rs')
-rw-r--r--src/list.rs142
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(),
XMR address: 854DmXNrxULU3ZFJVs4Wc8PFhbq29RhqHhY8W6cdWrtFN3qmooKyyeYPcDzZTNRxphhJ5UzASQfAdEMwSteVqymk28aLhqj