use std::fmt::{Debug, Display};
use vantage_core::util::IntoVec;
use vantage_expressions::{Expression, Expressive};
#[derive(Debug, Clone)]
pub struct Concat<T: Debug + Display + Clone> {
parts: Vec<Expression<T>>,
separator: Option<Expression<T>>,
}
impl<T: Debug + Display + Clone> Concat<T> {
pub fn new(parts: impl IntoVec<Expression<T>>) -> Self {
Self {
parts: parts.into_vec(),
separator: None,
}
}
pub fn ws(mut self, separator: impl Expressive<T>) -> Self {
self.separator = Some(separator.expr());
self
}
}
#[macro_export]
macro_rules! concat_ {
($($part:expr),+ $(,)?) => {
$crate::primitives::concat::Concat::new(vec![
$({
#[allow(unused_imports)]
use vantage_expressions::Expressive;
($part).expr()
}),+
])
};
}
#[cfg(feature = "sqlite")]
impl Expressive<crate::sqlite::types::AnySqliteType>
for Concat<crate::sqlite::types::AnySqliteType>
{
fn expr(&self) -> Expression<crate::sqlite::types::AnySqliteType> {
if let Some(sep) = &self.separator {
let mut interleaved = Vec::with_capacity(self.parts.len() * 2 - 1);
for (i, part) in self.parts.iter().enumerate() {
if i > 0 {
interleaved.push(sep.clone());
}
interleaved.push(part.clone());
}
Expression::from_vec(interleaved, " || ")
} else {
Expression::from_vec(self.parts.clone(), " || ")
}
}
}
#[cfg(feature = "mysql")]
impl Expressive<crate::mysql::types::AnyMysqlType> for Concat<crate::mysql::types::AnyMysqlType> {
fn expr(&self) -> Expression<crate::mysql::types::AnyMysqlType> {
use vantage_expressions::ExpressiveEnum;
if let Some(sep) = &self.separator {
let mut all = vec![sep.clone()];
all.extend(self.parts.clone());
let args = Expression::from_vec(all, ", ");
Expression::new("CONCAT_WS({})", vec![ExpressiveEnum::Nested(args)])
} else {
let args = Expression::from_vec(self.parts.clone(), ", ");
Expression::new("CONCAT({})", vec![ExpressiveEnum::Nested(args)])
}
}
}
#[cfg(feature = "postgres")]
impl Expressive<crate::postgres::types::AnyPostgresType>
for Concat<crate::postgres::types::AnyPostgresType>
{
fn expr(&self) -> Expression<crate::postgres::types::AnyPostgresType> {
use vantage_expressions::ExpressiveEnum;
if let Some(sep) = &self.separator {
let mut all = vec![sep.clone()];
all.extend(self.parts.clone());
let args = Expression::from_vec(all, ", ");
Expression::new("CONCAT_WS({})", vec![ExpressiveEnum::Nested(args)])
} else {
Expression::from_vec(self.parts.clone(), " || ")
}
}
}