use serde::Serialize;
use serde_json::{Map, Value};
#[macro_export]
macro_rules! cast_mapmember {
($mapmem:ident, $dtype:ty) => {
serde_json::from_value::<$dtype>($mapmem.to_owned())
.map_err(|e| restrepo::persistence::MappingError::ArgumentError(e.to_string()))
};
}
pub fn prefixed_attribute(prefix: &str, attr: &str) -> String {
let mut p_clean = String::default();
p_clean.extend(prefix.chars().filter(|c| !c.is_whitespace()));
if !p_clean.is_empty() {
p_clean.push('_')
};
format!("{p_clean}{attr}")
}
#[derive(Clone, Debug, Default)]
pub struct ColumnAliasMapper {
alias: Option<String>,
table: String,
columns: Vec<String>,
}
impl ColumnAliasMapper {
pub fn set_table_name(mut self, name: &str) -> Self {
name.clone_into(&mut self.table);
self
}
pub fn set_alias_prefix(mut self, alias: &str) -> Self {
self.alias = Some(alias.to_owned());
self
}
pub fn set_column_names(mut self, names: Vec<String>) -> Self {
self.columns = names
.iter()
.map(|entry| entry.chars().filter(|c| !c.is_whitespace()).collect())
.collect();
self
}
pub fn build_map(&self) -> String {
let mut res = String::default();
let mut prefix = String::default();
let column_count = self.columns.len() - 1;
if let Some(ap) = self.alias.as_ref() {
prefix = format!("{ap}_");
}
for (i, n) in self.columns.iter().enumerate() {
let comma = if i != column_count { ", " } else { "" };
res += format!("{table}.{n} as {prefix}{n}{comma}", table = self.table).as_str();
}
res
}
}
pub struct UpdateStatementBuilder {
query: String,
data_map: Map<String, Value>,
}
impl UpdateStatementBuilder {
pub fn new(data: &impl Serialize, table: &str) -> Result<Self, super::error::MappingError> {
let data_map = serde_json::from_value::<Map<String, Value>>(serde_json::to_value(data)?)?;
let column_binds = data_map
.keys()
.enumerate()
.map(|(i, k)| format!("{} = ${}", k, i + 1))
.collect::<Vec<String>>()
.join(",");
let id_arg_pos = data_map.len() + 1;
let sql_template =
format!("UPDATE {table} SET {column_binds} WHERE id = ${id_arg_pos} RETURNING *");
Ok(Self {
query: sql_template,
data_map,
})
}
#[must_use]
pub fn query(&self) -> &str {
self.query.as_ref()
}
#[must_use]
pub fn data_map(&self) -> &Map<String, Value> {
&self.data_map
}
}