vantage_sql/primitives/
concat.rs1use std::fmt::{Debug, Display};
2
3use vantage_core::util::IntoVec;
4use vantage_expressions::{Expression, Expressive};
5
6#[derive(Debug, Clone)]
24pub struct Concat<T: Debug + Display + Clone> {
25 parts: Vec<Expression<T>>,
26 separator: Option<Expression<T>>,
27}
28
29impl<T: Debug + Display + Clone> Concat<T> {
30 pub fn new(parts: impl IntoVec<Expression<T>>) -> Self {
31 Self {
32 parts: parts.into_vec(),
33 separator: None,
34 }
35 }
36
37 pub fn ws(mut self, separator: impl Expressive<T>) -> Self {
39 self.separator = Some(separator.expr());
40 self
41 }
42}
43
44#[macro_export]
57macro_rules! concat_ {
58 ($($part:expr),+ $(,)?) => {
59 $crate::primitives::concat::Concat::new(vec![
60 $({
61 #[allow(unused_imports)]
62 use vantage_expressions::Expressive;
63 ($part).expr()
64 }),+
65 ])
66 };
67}
68
69#[cfg(feature = "sqlite")]
70impl Expressive<crate::sqlite::types::AnySqliteType>
71 for Concat<crate::sqlite::types::AnySqliteType>
72{
73 fn expr(&self) -> Expression<crate::sqlite::types::AnySqliteType> {
74 if let Some(sep) = &self.separator {
75 let mut interleaved = Vec::with_capacity(self.parts.len() * 2 - 1);
76 for (i, part) in self.parts.iter().enumerate() {
77 if i > 0 {
78 interleaved.push(sep.clone());
79 }
80 interleaved.push(part.clone());
81 }
82 Expression::from_vec(interleaved, " || ")
83 } else {
84 Expression::from_vec(self.parts.clone(), " || ")
85 }
86 }
87}
88
89#[cfg(feature = "mysql")]
90impl Expressive<crate::mysql::types::AnyMysqlType> for Concat<crate::mysql::types::AnyMysqlType> {
91 fn expr(&self) -> Expression<crate::mysql::types::AnyMysqlType> {
92 use vantage_expressions::ExpressiveEnum;
93
94 if let Some(sep) = &self.separator {
95 let mut all = vec![sep.clone()];
96 all.extend(self.parts.clone());
97 let args = Expression::from_vec(all, ", ");
98 Expression::new("CONCAT_WS({})", vec![ExpressiveEnum::Nested(args)])
99 } else {
100 let args = Expression::from_vec(self.parts.clone(), ", ");
101 Expression::new("CONCAT({})", vec![ExpressiveEnum::Nested(args)])
102 }
103 }
104}
105
106#[cfg(feature = "postgres")]
107impl Expressive<crate::postgres::types::AnyPostgresType>
108 for Concat<crate::postgres::types::AnyPostgresType>
109{
110 fn expr(&self) -> Expression<crate::postgres::types::AnyPostgresType> {
111 use vantage_expressions::ExpressiveEnum;
112
113 if let Some(sep) = &self.separator {
114 let mut all = vec![sep.clone()];
115 all.extend(self.parts.clone());
116 let args = Expression::from_vec(all, ", ");
117 Expression::new("CONCAT_WS({})", vec![ExpressiveEnum::Nested(args)])
118 } else {
119 Expression::from_vec(self.parts.clone(), " || ")
120 }
121 }
122}