1use vantage_expressions::traits::expressive::ExpressiveEnum;
19use vantage_expressions::{Expression, Expressive};
20
21use crate::primitives::fx::Fx;
22use crate::primitives::identifier::Identifier;
23
24macro_rules! define_sql_condition {
25 ($name:ident, $any_type:ty) => {
26 #[derive(Debug, Clone)]
28 pub struct $name(pub Expression<$any_type>);
29
30 impl $name {
31 pub fn into_expr(self) -> Expression<$any_type> {
32 self.0
33 }
34
35 pub fn from_typed<F>(expr: Expression<F>) -> Self
39 where
40 F: Into<$any_type> + Send + Clone + 'static,
41 {
42 use vantage_expressions::ExpressionMap;
43 Self(expr.map())
44 }
45 }
46
47 impl<F> From<Expression<F>> for $name
48 where
49 F: Into<$any_type> + Send + Clone + 'static,
50 {
51 fn from(expr: Expression<F>) -> Self {
52 Self::from_typed(expr)
53 }
54 }
55
56 impl From<Identifier> for $name {
57 fn from(id: Identifier) -> Self {
58 use vantage_expressions::Expressive;
59 Self(id.expr())
60 }
61 }
62
63 impl From<$name> for Expression<$any_type> {
64 fn from(cond: $name) -> Self {
65 cond.0
66 }
67 }
68
69 impl From<Fx<$any_type>> for $name {
70 fn from(fx: Fx<$any_type>) -> Self {
71 Self(fx.into())
72 }
73 }
74 };
75}
76
77#[cfg(feature = "sqlite")]
78define_sql_condition!(SqliteCondition, crate::sqlite::types::AnySqliteType);
79
80#[cfg(feature = "postgres")]
81define_sql_condition!(PostgresCondition, crate::postgres::types::AnyPostgresType);
82
83#[cfg(feature = "mysql")]
84define_sql_condition!(MysqlCondition, crate::mysql::types::AnyMysqlType);
85
86#[cfg(feature = "mysql")]
87impl From<crate::mysql::statements::primitives::FulltextMatch> for MysqlCondition {
88 fn from(fm: crate::mysql::statements::primitives::FulltextMatch) -> Self {
89 Self(fm.into())
90 }
91}
92
93pub(crate) fn in_values<V, C>(column: &impl Expressive<V>, values: &[V]) -> C
97where
98 V: Clone + Send + Sync + 'static,
99 C: From<Expression<V>>,
100{
101 let list = if values.is_empty() {
102 Expression::new("NULL", vec![])
103 } else {
104 let items = values
105 .iter()
106 .map(|v| Expression::new("{}", vec![ExpressiveEnum::Scalar(v.clone())]))
107 .collect();
108 Expression::from_vec(items, ", ")
109 };
110 Expression::new(
111 "{} IN ({})",
112 vec![
113 ExpressiveEnum::Nested(column.expr()),
114 ExpressiveEnum::Nested(list),
115 ],
116 )
117 .into()
118}
119
120#[macro_export]
126macro_rules! define_typed_ident {
127 ($struct_name:ident, $fn_name:ident, $any_type:ty, $condition:ty) => {
128 #[derive(Debug, Clone)]
129 pub struct $struct_name($crate::primitives::identifier::Identifier);
130
131 impl $struct_name {
132 pub fn new(name: impl Into<String>) -> Self {
133 Self($crate::primitives::identifier::ident(name))
134 }
135
136 pub fn dot_of(mut self, prefix: impl Into<String>) -> Self {
137 self.0 = self.0.dot_of(prefix);
138 self
139 }
140
141 pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
142 self.0 = self.0.with_alias(alias);
143 self
144 }
145
146 pub fn name(&self) -> String {
147 self.0.name()
148 }
149
150 pub fn alias(&self) -> Option<&str> {
151 self.0.alias()
152 }
153 }
154
155 impl $crate::vantage_expressions::Expressive<$any_type> for $struct_name {
156 fn expr(&self) -> $crate::vantage_expressions::Expression<$any_type> {
157 $crate::vantage_expressions::Expressive::<$any_type>::expr(&self.0)
158 }
159 }
160
161 impl From<$struct_name> for $crate::vantage_expressions::Expression<$any_type> {
162 fn from(id: $struct_name) -> Self {
163 $crate::vantage_expressions::Expressive::<$any_type>::expr(&id.0)
164 }
165 }
166
167 impl From<$struct_name> for $condition {
168 fn from(id: $struct_name) -> Self {
169 Self::from_typed($crate::vantage_expressions::Expressive::<$any_type>::expr(
170 &id.0,
171 ))
172 }
173 }
174
175 pub fn $fn_name(name: impl Into<String>) -> $struct_name {
177 $struct_name::new(name)
178 }
179 };
180}
181
182#[macro_export]
183macro_rules! define_sql_operation {
184 ($trait_name:ident, $condition:ident, $any_type:ty) => {
185 pub trait $trait_name<T>: $crate::vantage_expressions::Expressive<T>
191 where
192 T: Into<$any_type> + Send + Clone + 'static,
193 {
194 fn or_(
207 &self,
208 other: impl $crate::vantage_expressions::Expressive<T>,
209 ) -> $crate::primitives::ConditionGroup<T>
210 where
211 Self: Sized,
212 {
213 $crate::primitives::or_(self.expr(), other.expr())
214 }
215
216 fn and_(
222 &self,
223 other: impl $crate::vantage_expressions::Expressive<T>,
224 ) -> $crate::primitives::ConditionGroup<T>
225 where
226 Self: Sized,
227 {
228 $crate::primitives::and_(self.expr(), other.expr())
229 }
230
231 fn eq(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
233 where
234 Self: Sized,
235 {
236 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
237 self, value, "{} = {}",
238 )
239 }
240
241 fn ne(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
243 where
244 Self: Sized,
245 {
246 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
247 self, value, "{} != {}",
248 )
249 }
250
251 fn gt(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
253 where
254 Self: Sized,
255 {
256 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
257 self, value, "{} > {}",
258 )
259 }
260
261 fn gte(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
263 where
264 Self: Sized,
265 {
266 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
267 self, value, "{} >= {}",
268 )
269 }
270
271 fn lt(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
273 where
274 Self: Sized,
275 {
276 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
277 self, value, "{} < {}",
278 )
279 }
280
281 fn lte(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
283 where
284 Self: Sized,
285 {
286 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
287 self, value, "{} <= {}",
288 )
289 }
290
291 fn in_(&self, values: impl $crate::vantage_expressions::Expressive<T>) -> $condition
293 where
294 Self: Sized,
295 {
296 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
297 self,
298 values,
299 "{} IN ({})",
300 )
301 }
302
303 fn in_list<V: Into<T> + Clone>(&self, values: &[V]) -> $condition
305 where
306 Self: Sized,
307 T: Clone,
308 {
309 use $crate::vantage_expressions::Expression;
310 use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
311 let params: Vec<Expression<T>> = values
312 .iter()
313 .map(|v| Expression::new("{}", vec![ExpressiveEnum::Scalar(v.clone().into())]))
314 .collect();
315 let expr: Expression<T> = Expression::new(
316 "{} IN ({})",
317 vec![
318 ExpressiveEnum::Nested(self.expr()),
319 ExpressiveEnum::Nested(Expression::from_vec(params, ", ")),
320 ],
321 );
322 $condition::from_typed(expr)
323 }
324
325 fn not_in(&self, values: impl $crate::vantage_expressions::Expressive<T>) -> $condition
327 where
328 Self: Sized,
329 {
330 $crate::condition::build_sql_binary::<T, $any_type, $condition>(
331 self,
332 values,
333 "{} NOT IN ({})",
334 )
335 }
336
337 fn not_in_list<V: Into<T> + Clone>(&self, values: &[V]) -> $condition
339 where
340 Self: Sized,
341 T: Clone,
342 {
343 use $crate::vantage_expressions::Expression;
344 use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
345 let params: Vec<Expression<T>> = values
346 .iter()
347 .map(|v| Expression::new("{}", vec![ExpressiveEnum::Scalar(v.clone().into())]))
348 .collect();
349 let expr: Expression<T> = Expression::new(
350 "{} NOT IN ({})",
351 vec![
352 ExpressiveEnum::Nested(self.expr()),
353 ExpressiveEnum::Nested(Expression::from_vec(params, ", ")),
354 ],
355 );
356 $condition::from_typed(expr)
357 }
358
359 fn cast(&self, type_name: &str) -> $condition
361 where
362 Self: Sized,
363 {
364 use $crate::vantage_expressions::Expression;
365 use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
366 let expr: Expression<T> = Expression::new(
367 format!("CAST({{}} AS {type_name})"),
368 vec![ExpressiveEnum::Nested(self.expr())],
369 );
370 $condition::from_typed(expr)
371 }
372
373 fn is_null(&self) -> $condition
375 where
376 Self: Sized,
377 {
378 use $crate::vantage_expressions::Expression;
379 use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
380 let expr: Expression<T> =
381 Expression::new("{} IS NULL", vec![ExpressiveEnum::Nested(self.expr())]);
382 $condition::from_typed(expr)
383 }
384
385 fn is_not_null(&self) -> $condition
387 where
388 Self: Sized,
389 {
390 use $crate::vantage_expressions::Expression;
391 use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
392 let expr: Expression<T> =
393 Expression::new("{} IS NOT NULL", vec![ExpressiveEnum::Nested(self.expr())]);
394 $condition::from_typed(expr)
395 }
396 }
397
398 impl<T, S> $trait_name<T> for S
401 where
402 S: $crate::vantage_expressions::Expressive<T>,
403 T: Into<$any_type> + Send + Clone + 'static,
404 {
405 }
406
407 impl $crate::vantage_expressions::Expressive<$any_type> for $condition {
411 fn expr(&self) -> $crate::vantage_expressions::Expression<$any_type> {
412 self.0.clone()
413 }
414 }
415 };
416}
417
418pub fn build_sql_binary<T, AnyType, Cond>(
422 lhs: &(impl Expressive<T> + ?Sized),
423 rhs: impl Expressive<T>,
424 template: &str,
425) -> Cond
426where
427 T: Into<AnyType> + Send + Clone + 'static,
428 Cond: From<Expression<T>>,
429{
430 let expr: Expression<T> = Expression::new(
431 template,
432 vec![
433 ExpressiveEnum::Nested(lhs.expr()),
434 ExpressiveEnum::Nested(rhs.expr()),
435 ],
436 );
437 Cond::from(expr)
438}