aboutsummaryrefslogtreecommitdiff
path: root/src/db
diff options
context:
space:
mode:
authorJoris2021-10-10 19:27:22 +0200
committerJoris2021-10-10 21:21:34 +0200
commit6e695bf7a0253b4f6d1db78fa4310616d8a1357f (patch)
treea5b9f30b74a6914336993f93504df3b42fccb933 /src/db
parent8ccd762bfc3d7da2716749d709cf5cc216882a23 (diff)
downloadbudget-6e695bf7a0253b4f6d1db78fa4310616d8a1357f.tar.gz
budget-6e695bf7a0253b4f6d1db78fa4310616d8a1357f.tar.bz2
budget-6e695bf7a0253b4f6d1db78fa4310616d8a1357f.zip
Search by name, cost and user
Diffstat (limited to 'src/db')
-rw-r--r--src/db/payments.rs142
1 files changed, 94 insertions, 48 deletions
diff --git a/src/db/payments.rs b/src/db/payments.rs
index 3b85dab..25d1cbb 100644
--- a/src/db/payments.rs
+++ b/src/db/payments.rs
@@ -23,8 +23,6 @@ pub async fn count(
pool: &SqlitePool,
payment_query: &queries::Payments,
) -> Count {
- let search = payment_query.search.clone().unwrap_or("".to_string());
-
let query = format!(
r#"
SELECT
@@ -39,18 +37,26 @@ INNER JOIN
WHERE
payments.deleted_at IS NULL
AND payments.frequency = ?
- {}
- {}
+ {} {} {} {}
"#,
- search_query(search.clone()),
+ name_query(payment_query.name.clone()),
+ cost_query(payment_query.cost.clone()),
+ user_query(payment_query.user),
category_query(payment_query.category)
);
let res = bind_category(
- bind_search(
- sqlx::query_as::<_, Count>(&query)
- .bind(payment_query.frequency.unwrap_or(Frequency::Punctual)),
- search,
+ bind_user(
+ bind_cost(
+ bind_name(
+ sqlx::query_as::<_, Count>(&query).bind(
+ payment_query.frequency.unwrap_or(Frequency::Punctual),
+ ),
+ payment_query.name.clone(),
+ ),
+ payment_query.cost.clone(),
+ ),
+ payment_query.user,
),
payment_query.category,
)
@@ -75,7 +81,6 @@ pub async fn list_for_table(
per_page: i64,
) -> Vec<payment::Table> {
let offset = (payment_query.page.unwrap_or(1) - 1) * per_page;
- let search = payment_query.search.clone().unwrap_or("".to_string());
let query = format!(
r#"
@@ -97,22 +102,30 @@ INNER JOIN
WHERE
payments.deleted_at IS NULL
AND payments.frequency = ?
- {}
- {}
+ {} {} {} {}
ORDER BY
payments.date DESC
LIMIT ?
OFFSET ?
"#,
- search_query(search.clone()),
+ name_query(payment_query.name.clone()),
+ cost_query(payment_query.cost.clone()),
+ user_query(payment_query.user),
category_query(payment_query.category)
);
let res = bind_category(
- bind_search(
- sqlx::query_as::<_, payment::Table>(&query)
- .bind(payment_query.frequency.unwrap_or(Frequency::Punctual)),
- search,
+ bind_user(
+ bind_cost(
+ bind_name(
+ sqlx::query_as::<_, payment::Table>(&query).bind(
+ payment_query.frequency.unwrap_or(Frequency::Punctual),
+ ),
+ payment_query.name.clone(),
+ ),
+ payment_query.cost.clone(),
+ ),
+ payment_query.user,
),
payment_query.category,
)
@@ -130,45 +143,78 @@ OFFSET ?
}
}
-fn search_query(search: String) -> String {
- let payments_name = utils::format_key_for_search("payments.name");
- let users_name = utils::format_key_for_search("users.name");
-
- search
- .split_ascii_whitespace()
- .map(|_| {
- format!(
- r#"
-AND (
- {} LIKE ?
- OR payments.cost LIKE ?
- OR {} LIKE ?
- OR strftime('%d/%m/%Y', date) LIKE ?
-)
- "#,
- payments_name, users_name
- )
- })
- .collect::<Vec<String>>()
- .join(" ")
+fn name_query(name: Option<String>) -> String {
+ if name.map_or_else(|| false, |str| !str.is_empty()) {
+ format!(
+ "AND {} LIKE ?",
+ utils::format_key_for_search("payments.name")
+ )
+ } else {
+ "".to_string()
+ }
+}
+
+fn bind_name<'a, Row: FromRow<'a, SqliteRow>>(
+ query: sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>>,
+ name: Option<String>,
+) -> sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>> {
+ match name {
+ Some(str) => {
+ if str.is_empty() {
+ query
+ } else {
+ query.bind(text::format_search(&str))
+ }
+ }
+ _ => query,
+ }
+}
+
+fn cost_query(cost: Option<String>) -> String {
+ if cost.map_or_else(|| false, |str| !str.is_empty()) {
+ "AND payments.cost = ?".to_string()
+ } else {
+ "".to_string()
+ }
+}
+
+fn bind_cost<'a, Row: FromRow<'a, SqliteRow>>(
+ query: sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>>,
+ cost: Option<String>,
+) -> sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>> {
+ match cost {
+ Some(str) => {
+ if str.is_empty() {
+ query
+ } else {
+ query.bind(str)
+ }
+ }
+ _ => query,
+ }
}
-fn bind_search<'a, Row: FromRow<'a, SqliteRow>>(
+fn user_query(user: Option<i64>) -> String {
+ if user.is_some() {
+ "AND payments.user_id = ?".to_string()
+ } else {
+ "".to_string()
+ }
+}
+
+fn bind_user<'a, Row: FromRow<'a, SqliteRow>>(
query: sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>>,
- search: String,
+ user: Option<i64>,
) -> sqlx::query::QueryAs<'a, Sqlite, Row, SqliteArguments<'a>> {
- search.split_ascii_whitespace().fold(query, |q, word| {
- let s = format!("%{}%", text::format_search(&word.to_string()));
- q.bind(s.clone())
- .bind(s.clone())
- .bind(s.clone())
- .bind(s.clone())
- })
+ match user {
+ Some(id) => query.bind(id),
+ _ => query,
+ }
}
fn category_query(category: Option<i64>) -> String {
if category.is_some() {
- "AND category_id = ?".to_string()
+ "AND payments.category_id = ?".to_string()
} else {
"".to_string()
}