use std::collections::HashMap;
use sqlx::PgPool;
use crate::api::gateway::contracts::GatewayRequestCondition;
use crate::drivers::postgresql::column_resolver::resolve_information_schema_targets;
use crate::drivers::postgresql::schema_cache::get_table_column_types;
use crate::parser::query_builder::Condition;
use crate::utils::format::normalize_column_name;
use crate::utils::postgres_types::where_cast_for_column;
pub type RequestCondition = GatewayRequestCondition;
#[allow(dead_code)]
pub fn to_query_conditions(
conditions: &[RequestCondition],
convert_camel_case: bool,
auto_cast_uuid_filter_values_to_text: bool,
) -> Vec<Condition> {
to_query_conditions_with_types(
conditions,
convert_camel_case,
auto_cast_uuid_filter_values_to_text,
None,
)
}
pub fn to_query_conditions_with_types(
conditions: &[RequestCondition],
convert_camel_case: bool,
auto_cast_uuid_filter_values_to_text: bool,
column_types: Option<&HashMap<String, String>>,
) -> Vec<Condition> {
conditions
.iter()
.map(|condition: &RequestCondition| {
let column_name: String =
normalize_column_name(&condition.eq_column, convert_camel_case);
let cast: Option<&'static str> = where_cast_for_column(&column_name, column_types);
Condition::eq(column_name, condition.eq_value.clone())
.with_uuid_value_text_cast(auto_cast_uuid_filter_values_to_text)
.with_pg_cast(cast)
})
.collect()
}
pub async fn resolve_where_column_types(
pool: &PgPool,
table_name: &str,
allow_schema_names_prefixed_as_table_name: bool,
) -> Option<HashMap<String, String>> {
let (schema_name, relation_name) =
resolve_information_schema_targets(table_name, allow_schema_names_prefixed_as_table_name)
.ok()?;
get_table_column_types(pool, &schema_name, &relation_name)
.await
.ok()
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn forced_normalization_converts_camel_case_condition_columns() {
let conditions = vec![
RequestCondition::new(
"organizationId".into(),
json!("544d9c97-1c3f-4742-a100-e5430bd79b7f"),
),
RequestCondition::new("userId".into(), json!("aXHOWHWj5btNEhmZ53XAhDvIaS7n1nxt")),
];
let pg: Vec<Condition> = to_query_conditions(&conditions, true, false);
assert_eq!(pg[0].column, "organization_id");
assert_eq!(pg[1].column, "user_id");
}
#[test]
fn without_forcing_conditions_keep_original_names() {
let conditions = vec![RequestCondition::new("organizationId".into(), json!("x"))];
let pg: Vec<Condition> = to_query_conditions(&conditions, false, false);
assert_eq!(pg[0].column, "organizationId");
}
}