107 lines
4.0 KiB
Rust
107 lines
4.0 KiB
Rust
use crate::data::Value;
|
|
use sqlx::{FromRow, Postgres};
|
|
|
|
#[allow(async_fn_in_trait)]
|
|
pub trait ExecutableQuery {
|
|
fn build(&self) -> (String, Vec<Value>);
|
|
|
|
async fn execute(&self) -> Result<sqlx::postgres::PgQueryResult, sqlx::Error> {
|
|
// Build the SQL query and its values
|
|
let (query_string, values) = self.build();
|
|
|
|
// Start constructing the query
|
|
let mut query = sqlx::query(&query_string);
|
|
|
|
// Bind each value to its respective placeholder
|
|
for value in values {
|
|
match value {
|
|
Value::Int(n) => query = query.bind(n),
|
|
Value::OptionalInt(n) => query = query.bind(n),
|
|
Value::BigInt(n) => query = query.bind(n),
|
|
Value::OptionalBigInt(n) => query = query.bind(n),
|
|
Value::Float(n) => query = query.bind(n),
|
|
Value::OptionalFloat(n) => query = query.bind(n),
|
|
Value::Double(n) => query = query.bind(n),
|
|
Value::OptionalDouble(n) => query = query.bind(n),
|
|
Value::Bool(n) => query = query.bind(n),
|
|
Value::OptionalBool(n) => query = query.bind(n),
|
|
Value::Text(n) => query = query.bind(n),
|
|
Value::OptionalText(n) => query = query.bind(n),
|
|
Value::DateTime(n) => query = query.bind(n),
|
|
Value::OptionalDateTime(n) => query = query.bind(n),
|
|
}
|
|
}
|
|
|
|
let pool = crate::data::pool();
|
|
query.execute(pool).await
|
|
}
|
|
|
|
async fn fetch_optional<
|
|
T: Send + Unpin + for<'r> FromRow<'r, <Postgres as sqlx::Database>::Row>,
|
|
>(
|
|
&self,
|
|
) -> Option<T> {
|
|
let (query_string, values) = self.build();
|
|
let mut query_as = sqlx::query_as(&query_string);
|
|
for value in values {
|
|
match value {
|
|
Value::Int(n) => query_as = query_as.bind(n),
|
|
Value::OptionalInt(n) => query_as = query_as.bind(n),
|
|
Value::BigInt(n) => query_as = query_as.bind(n),
|
|
Value::OptionalBigInt(n) => query_as = query_as.bind(n),
|
|
Value::Float(n) => query_as = query_as.bind(n),
|
|
Value::OptionalFloat(n) => query_as = query_as.bind(n),
|
|
Value::Double(n) => query_as = query_as.bind(n),
|
|
Value::OptionalDouble(n) => query_as = query_as.bind(n),
|
|
Value::Bool(n) => query_as = query_as.bind(n),
|
|
Value::OptionalBool(n) => query_as = query_as.bind(n),
|
|
Value::Text(n) => query_as = query_as.bind(n),
|
|
Value::OptionalText(n) => query_as = query_as.bind(n),
|
|
Value::DateTime(n) => query_as = query_as.bind(n),
|
|
Value::OptionalDateTime(n) => query_as = query_as.bind(n),
|
|
}
|
|
}
|
|
|
|
let pool = crate::data::pool();
|
|
query_as.fetch_optional(pool).await.unwrap_or_else(|err| {
|
|
log::error!(
|
|
"Unable to fetch optional on query '{}': {}",
|
|
query_string,
|
|
err
|
|
);
|
|
None
|
|
})
|
|
}
|
|
|
|
async fn fetch_all<T: Send + Unpin + for<'r> FromRow<'r, <Postgres as sqlx::Database>::Row>>(
|
|
&self,
|
|
) -> Vec<T> {
|
|
let (query_string, values) = self.build();
|
|
let mut query_as = sqlx::query_as(&query_string);
|
|
for value in values {
|
|
match value {
|
|
Value::Int(n) => query_as = query_as.bind(n),
|
|
Value::OptionalInt(n) => query_as = query_as.bind(n),
|
|
Value::BigInt(n) => query_as = query_as.bind(n),
|
|
Value::OptionalBigInt(n) => query_as = query_as.bind(n),
|
|
Value::Float(n) => query_as = query_as.bind(n),
|
|
Value::OptionalFloat(n) => query_as = query_as.bind(n),
|
|
Value::Double(n) => query_as = query_as.bind(n),
|
|
Value::OptionalDouble(n) => query_as = query_as.bind(n),
|
|
Value::Bool(n) => query_as = query_as.bind(n),
|
|
Value::OptionalBool(n) => query_as = query_as.bind(n),
|
|
Value::Text(n) => query_as = query_as.bind(n),
|
|
Value::OptionalText(n) => query_as = query_as.bind(n),
|
|
Value::DateTime(n) => query_as = query_as.bind(n),
|
|
Value::OptionalDateTime(n) => query_as = query_as.bind(n),
|
|
}
|
|
}
|
|
|
|
let pool = crate::data::pool();
|
|
query_as.fetch_all(pool).await.unwrap_or_else(|err| {
|
|
log::error!("Unable to fetch all on query '{}': {}", query_string, err);
|
|
vec![]
|
|
})
|
|
}
|
|
}
|