aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2025-01-31 23:30:30 +0100
committerJoris2025-01-31 23:30:30 +0100
commit877f64b33adf32cf8495d1364d184055aab8089c (patch)
tree4e6414bf5ec4726a10faa4fe3ac66e4ffac6c04b
parent0adf5a093494bdb7f5d5c0f12913133e333ddfad (diff)
Migrate to tokio_rusqlite
-rw-r--r--src/controller/payments.rs7
-rw-r--r--src/db/payments.rs109
-rw-r--r--src/model/frequency.rs4
3 files changed, 84 insertions, 36 deletions
diff --git a/src/controller/payments.rs b/src/controller/payments.rs
index 1ffa09f..3fa85a5 100644
--- a/src/controller/payments.rs
+++ b/src/controller/payments.rs
@@ -92,7 +92,9 @@ pub async fn create(
match validation::payment::create(&form) {
Some(create_payment) => {
- match db::payments::create(&wallet.db_conn, create_payment.clone()).await {
+ match db::payments::create(&wallet.db_conn, create_payment.clone())
+ .await
+ {
Some(id) => {
let row = db::payments::get_row(
&wallet.db_conn,
@@ -234,7 +236,8 @@ pub async fn search_category(
wallet: &Wallet,
query: queries::PaymentCategory,
) -> Response<Full<Bytes>> {
- match db::payments::search_category(&wallet.db_conn, query.payment_name).await
+ match db::payments::search_category(&wallet.db_conn, query.payment_name)
+ .await
{
Some(category_id) => utils::with_headers(
Response::new(format!("{}", category_id).into()),
diff --git a/src/db/payments.rs b/src/db/payments.rs
index 540a006..4a6774c 100644
--- a/src/db/payments.rs
+++ b/src/db/payments.rs
@@ -1,6 +1,8 @@
use std::collections::HashMap;
use std::iter::FromIterator;
-use tokio_rusqlite::{Connection, Row, params_from_iter, types::ToSql, named_params};
+use tokio_rusqlite::{
+ named_params, params_from_iter, types::ToSql, Connection, Row,
+};
use crate::db::utils;
use crate::model::frequency::Frequency;
@@ -30,7 +32,7 @@ fn row_to_table(row: &Row) -> Result<payment::Table, rusqlite::Error> {
category_name: row.get(4)?,
category_color: row.get(5)?,
date: row.get(6)?,
- frequency: row.get(7)?
+ frequency: row.get(7)?,
})
}
@@ -50,7 +52,7 @@ fn row_to_form(row: &Row) -> Result<payment::Form, rusqlite::Error> {
user_id: row.get(3)?,
category_id: row.get(4)?,
date: row.get(5)?,
- frequency: row.get(6)?
+ frequency: row.get(6)?,
})
}
@@ -58,7 +60,7 @@ pub async fn count(
conn: &Connection,
payment_query: &queries::Payments,
) -> Count {
- let mut query = format!(r#"
+ let mut query = r#"
SELECT
COUNT(*) AS count,
SUM(payments.cost) AS total_cost
@@ -66,7 +68,8 @@ pub async fn count(
INNER JOIN users ON users.id = payments.user_id
INNER JOIN categories ON categories.id = payments.category_id
WHERE payments.deleted_at IS NULL
- "#);
+ "#
+ .to_string();
let mut params = Vec::<Box<dyn ToSql + Send>>::new();
complete_search_query(payment_query, &mut query, &mut params);
@@ -74,7 +77,8 @@ pub async fn count(
let res = conn
.call(move |conn| {
let mut stmt = conn.prepare(&query)?;
- let mut iter = stmt.query_map(params_from_iter(params), row_to_count)?;
+ let mut iter =
+ stmt.query_map(params_from_iter(params), row_to_count)?;
utils::one(&mut iter)
})
.await;
@@ -96,7 +100,7 @@ pub async fn list_for_table(
payment_query: &queries::Payments,
per_page: i64,
) -> Vec<payment::Table> {
- let mut query = format!(r#"
+ let mut query = r#"
SELECT
payments.id,
payments.name,
@@ -110,7 +114,8 @@ pub async fn list_for_table(
INNER JOIN users ON users.id = payments.user_id
INNER JOIN categories ON categories.id = payments.category_id
WHERE payments.deleted_at IS NULL
- "#);
+ "#
+ .to_string();
let mut params = Vec::<Box<dyn ToSql + Send>>::new();
complete_search_query(payment_query, &mut query, &mut params);
@@ -141,35 +146,62 @@ pub async fn list_for_table(
fn complete_search_query(
q: &queries::Payments,
query: &mut String,
- params: &mut Vec<Box<dyn ToSql + Send>>
+ params: &mut Vec<Box<dyn ToSql + Send>>,
) {
complete_frequency(q.frequency, query, params);
complete_name(q.name.clone(), query, params);
complete_cost(q.cost.clone(), query, params);
complete_user(q.user, query, params);
complete_category(q.category, query, params);
- complete_date("payments.date >=".to_string(), q.start_date.clone(), query, params);
- complete_date("payments.date <=".to_string(), q.end_date.clone(), query, params);
+ complete_date(
+ "payments.date >=".to_string(),
+ q.start_date.clone(),
+ query,
+ params,
+ );
+ complete_date(
+ "payments.date <=".to_string(),
+ q.end_date.clone(),
+ query,
+ params,
+ );
}
-fn complete_frequency(frequency: Option<Frequency>, query: &mut String, params: &mut Vec<Box<dyn ToSql + Send>>) {
+fn complete_frequency(
+ frequency: Option<Frequency>,
+ query: &mut String,
+ params: &mut Vec<Box<dyn ToSql + Send>>,
+) {
query.push_str("AND payments.frequency = ?");
- params.push(Box::new(frequency.unwrap_or(Frequency::Punctual).to_string()));
+ params.push(Box::new(
+ frequency.unwrap_or(Frequency::Punctual).to_string(),
+ ));
}
-fn complete_name(name: Option<String>, query: &mut String, params: &mut Vec<Box<dyn ToSql + Send>>) {
+fn complete_name(
+ name: Option<String>,
+ query: &mut String,
+ params: &mut Vec<Box<dyn ToSql + Send>>,
+) {
if let Some(name) = name {
if !name.is_empty() {
- query.push_str(format!(
- "AND {} LIKE ?",
- utils::format_key_for_search("payments.name")
- ).as_str());
+ query.push_str(
+ format!(
+ "AND {} LIKE ?",
+ utils::format_key_for_search("payments.name")
+ )
+ .as_str(),
+ );
params.push(Box::new(name));
}
}
}
-fn complete_cost(cost: Option<String>, query: &mut String, params: &mut Vec<Box<dyn ToSql + Send>>) {
+fn complete_cost(
+ cost: Option<String>,
+ query: &mut String,
+ params: &mut Vec<Box<dyn ToSql + Send>>,
+) {
if let Some(cost) = cost {
if !cost.is_empty() {
query.push_str("AND payments.cost = ?");
@@ -178,14 +210,22 @@ fn complete_cost(cost: Option<String>, query: &mut String, params: &mut Vec<Box<
}
}
-fn complete_user(user: Option<i64>, query: &mut String, params: &mut Vec<Box<dyn ToSql + Send>>) {
+fn complete_user(
+ user: Option<i64>,
+ query: &mut String,
+ params: &mut Vec<Box<dyn ToSql + Send>>,
+) {
if let Some(user) = user {
query.push_str("AND payments.user_id = ?");
params.push(Box::new(user))
}
}
-fn complete_category(category: Option<i64>, query: &mut String, params: &mut Vec<Box<dyn ToSql + Send>>) {
+fn complete_category(
+ category: Option<i64>,
+ query: &mut String,
+ params: &mut Vec<Box<dyn ToSql + Send>>,
+) {
if let Some(category) = category {
query.push_str("AND payments.category_id = ?");
params.push(Box::new(category));
@@ -196,7 +236,7 @@ fn complete_date(
name_and_op: String,
date: Option<String>,
query: &mut String,
- params: &mut Vec<Box<dyn ToSql + Send>>
+ params: &mut Vec<Box<dyn ToSql + Send>>,
) {
if let Some(date) = date {
if !date.is_empty() {
@@ -224,7 +264,7 @@ pub async fn list_for_stats(conn: &Connection) -> Vec<payment::Stat> {
let res = conn
.call(move |conn| {
- let mut stmt = conn.prepare(&query)?;
+ let mut stmt = conn.prepare(query)?;
let payments = stmt
.query_map([], row_to_stat)?
.collect::<Result<Vec<payment::Stat>, _>>()?;
@@ -261,7 +301,7 @@ pub async fn get_row(conn: &Connection, id: i64, frequency: Frequency) -> i64 {
let mut stmt = conn.prepare(query)?;
let mut iter = stmt.query_map(
named_params![":id": id, ":frequency": frequency.to_string()],
- |row| row.get(0)
+ |row| row.get(0),
)?;
utils::one::<i64, _>(&mut iter)
})
@@ -295,7 +335,8 @@ pub async fn get_for_form(conn: &Connection, id: i64) -> Option<payment::Form> {
let res = conn
.call(move |conn| {
let mut stmt = conn.prepare(query)?;
- let mut iter = stmt.query_map(named_params![":id": id], row_to_form)?;
+ let mut iter =
+ stmt.query_map(named_params![":id": id], row_to_form)?;
utils::one(&mut iter)
})
.await;
@@ -370,7 +411,6 @@ pub async fn update(conn: &Connection, id: i64, p: payment::Update) -> bool {
})
.await;
-
match res {
Ok(_) => true,
Err(err) => {
@@ -400,14 +440,17 @@ pub async fn search_category(
conn: &Connection,
payment_name: String,
) -> Option<i64> {
- let query = format!(r#"
+ let query = format!(
+ r#"
SELECT category_id
FROM payments
WHERE
deleted_at IS NULL
AND {} LIKE :name
ORDER BY updated_at, created_at
- "#, utils::format_key_for_search("name"));
+ "#,
+ utils::format_key_for_search("name")
+ );
let payment_name_closure = payment_name.clone();
@@ -424,7 +467,9 @@ pub async fn search_category(
match res {
Ok(category) => Some(category),
- Err(tokio_rusqlite::Error::Rusqlite(rusqlite::Error::QueryReturnedNoRows)) => None,
+ Err(tokio_rusqlite::Error::Rusqlite(
+ rusqlite::Error::QueryReturnedNoRows,
+ )) => None,
Err(err) => {
log::error!(
"Error looking for the category of {}: {:?}",
@@ -448,7 +493,7 @@ pub async fn is_category_used(conn: &Connection, category_id: i64) -> bool {
let res = conn
.call(move |conn| {
- let mut stmt = conn.prepare(&query)?;
+ let mut stmt = conn.prepare(query)?;
Ok(stmt.exists(named_params![":category_id": category_id])?)
})
.await;
@@ -520,9 +565,7 @@ pub async fn create_monthly_payments(conn: &Connection) {
AND deleted_at IS NULL
"#;
- let res = conn
- .call(move |conn| Ok(conn.execute(query, [])?))
- .await;
+ let res = conn.call(move |conn| Ok(conn.execute(query, [])?)).await;
match res {
Ok(_) => (),
diff --git a/src/model/frequency.rs b/src/model/frequency.rs
index 91aab89..f96482c 100644
--- a/src/model/frequency.rs
+++ b/src/model/frequency.rs
@@ -1,7 +1,9 @@
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ValueRef};
use std::{fmt, str};
-#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq)]
+#[derive(
+ Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq,
+)]
pub enum Frequency {
Punctual,
Monthly,