use crate::data::Value; use sqlx::{FromRow, Postgres}; #[allow(async_fn_in_trait)] pub trait ExecutableQuery { fn build(&self) -> (String, Vec); async fn execute(&self) -> Result { // 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, ::Row>, >( &self, ) -> Option { 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 FromRow<'r, ::Row>>( &self, ) -> Vec { 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![] }) } }