1use super::simple_expr::{Keyword, SimpleExpr};
7use crate::types::{BinOper, UnOper};
8use crate::value::Value;
9
10#[allow(clippy::wrong_self_convention)]
32pub trait ExprTrait: Sized {
33 fn into_simple_expr(self) -> SimpleExpr;
35
36 fn eq<V>(self, v: V) -> SimpleExpr
49 where
50 V: Into<SimpleExpr>,
51 {
52 SimpleExpr::Binary(
53 Box::new(self.into_simple_expr()),
54 BinOper::Equal,
55 Box::new(v.into()),
56 )
57 }
58
59 fn ne<V>(self, v: V) -> SimpleExpr
61 where
62 V: Into<SimpleExpr>,
63 {
64 SimpleExpr::Binary(
65 Box::new(self.into_simple_expr()),
66 BinOper::NotEqual,
67 Box::new(v.into()),
68 )
69 }
70
71 fn lt<V>(self, v: V) -> SimpleExpr
73 where
74 V: Into<SimpleExpr>,
75 {
76 SimpleExpr::Binary(
77 Box::new(self.into_simple_expr()),
78 BinOper::SmallerThan,
79 Box::new(v.into()),
80 )
81 }
82
83 fn lte<V>(self, v: V) -> SimpleExpr
85 where
86 V: Into<SimpleExpr>,
87 {
88 SimpleExpr::Binary(
89 Box::new(self.into_simple_expr()),
90 BinOper::SmallerThanOrEqual,
91 Box::new(v.into()),
92 )
93 }
94
95 fn gt<V>(self, v: V) -> SimpleExpr
97 where
98 V: Into<SimpleExpr>,
99 {
100 SimpleExpr::Binary(
101 Box::new(self.into_simple_expr()),
102 BinOper::GreaterThan,
103 Box::new(v.into()),
104 )
105 }
106
107 fn gte<V>(self, v: V) -> SimpleExpr
109 where
110 V: Into<SimpleExpr>,
111 {
112 SimpleExpr::Binary(
113 Box::new(self.into_simple_expr()),
114 BinOper::GreaterThanOrEqual,
115 Box::new(v.into()),
116 )
117 }
118
119 fn is_null(self) -> SimpleExpr {
125 SimpleExpr::Binary(
126 Box::new(self.into_simple_expr()),
127 BinOper::Is,
128 Box::new(SimpleExpr::Constant(Keyword::Null)),
129 )
130 }
131
132 fn is_not_null(self) -> SimpleExpr {
134 SimpleExpr::Binary(
135 Box::new(self.into_simple_expr()),
136 BinOper::IsNot,
137 Box::new(SimpleExpr::Constant(Keyword::Null)),
138 )
139 }
140
141 fn between<A, B>(self, a: A, b: B) -> SimpleExpr
154 where
155 A: Into<SimpleExpr>,
156 B: Into<SimpleExpr>,
157 {
158 SimpleExpr::Binary(
159 Box::new(self.into_simple_expr()),
160 BinOper::Between,
161 Box::new(SimpleExpr::Tuple(vec![a.into(), b.into()])),
162 )
163 }
164
165 fn not_between<A, B>(self, a: A, b: B) -> SimpleExpr
167 where
168 A: Into<SimpleExpr>,
169 B: Into<SimpleExpr>,
170 {
171 SimpleExpr::Binary(
172 Box::new(self.into_simple_expr()),
173 BinOper::NotBetween,
174 Box::new(SimpleExpr::Tuple(vec![a.into(), b.into()])),
175 )
176 }
177
178 fn is_in<I, V>(self, values: I) -> SimpleExpr
191 where
192 I: IntoIterator<Item = V>,
193 V: Into<SimpleExpr>,
194 {
195 SimpleExpr::Binary(
196 Box::new(self.into_simple_expr()),
197 BinOper::In,
198 Box::new(SimpleExpr::Tuple(
199 values.into_iter().map(|v| v.into()).collect(),
200 )),
201 )
202 }
203
204 fn is_not_in<I, V>(self, values: I) -> SimpleExpr
206 where
207 I: IntoIterator<Item = V>,
208 V: Into<SimpleExpr>,
209 {
210 SimpleExpr::Binary(
211 Box::new(self.into_simple_expr()),
212 BinOper::NotIn,
213 Box::new(SimpleExpr::Tuple(
214 values.into_iter().map(|v| v.into()).collect(),
215 )),
216 )
217 }
218
219 fn like<V>(self, pattern: V) -> SimpleExpr
232 where
233 V: Into<SimpleExpr>,
234 {
235 SimpleExpr::Binary(
236 Box::new(self.into_simple_expr()),
237 BinOper::Like,
238 Box::new(pattern.into()),
239 )
240 }
241
242 fn not_like<V>(self, pattern: V) -> SimpleExpr
244 where
245 V: Into<SimpleExpr>,
246 {
247 SimpleExpr::Binary(
248 Box::new(self.into_simple_expr()),
249 BinOper::NotLike,
250 Box::new(pattern.into()),
251 )
252 }
253
254 fn ilike<V>(self, pattern: V) -> SimpleExpr
256 where
257 V: Into<SimpleExpr>,
258 {
259 SimpleExpr::Binary(
260 Box::new(self.into_simple_expr()),
261 BinOper::ILike,
262 Box::new(pattern.into()),
263 )
264 }
265
266 fn not_ilike<V>(self, pattern: V) -> SimpleExpr
268 where
269 V: Into<SimpleExpr>,
270 {
271 SimpleExpr::Binary(
272 Box::new(self.into_simple_expr()),
273 BinOper::NotILike,
274 Box::new(pattern.into()),
275 )
276 }
277
278 fn starts_with<S>(self, prefix: S) -> SimpleExpr
280 where
281 S: Into<String>,
282 {
283 let pattern = format!("{}%", prefix.into());
284 self.like(Value::String(Some(Box::new(pattern))))
285 }
286
287 fn ends_with<S>(self, suffix: S) -> SimpleExpr
289 where
290 S: Into<String>,
291 {
292 let pattern = format!("%{}", suffix.into());
293 self.like(Value::String(Some(Box::new(pattern))))
294 }
295
296 fn contains<S>(self, substring: S) -> SimpleExpr
298 where
299 S: Into<String>,
300 {
301 let pattern = format!("%{}%", substring.into());
302 self.like(Value::String(Some(Box::new(pattern))))
303 }
304
305 fn and<E>(self, other: E) -> SimpleExpr
311 where
312 E: Into<SimpleExpr>,
313 {
314 SimpleExpr::Binary(
315 Box::new(self.into_simple_expr()),
316 BinOper::And,
317 Box::new(other.into()),
318 )
319 }
320
321 fn or<E>(self, other: E) -> SimpleExpr
323 where
324 E: Into<SimpleExpr>,
325 {
326 SimpleExpr::Binary(
327 Box::new(self.into_simple_expr()),
328 BinOper::Or,
329 Box::new(other.into()),
330 )
331 }
332
333 fn not(self) -> SimpleExpr {
335 SimpleExpr::Unary(UnOper::Not, Box::new(self.into_simple_expr()))
336 }
337
338 fn add<V>(self, v: V) -> SimpleExpr
344 where
345 V: Into<SimpleExpr>,
346 {
347 SimpleExpr::Binary(
348 Box::new(self.into_simple_expr()),
349 BinOper::Add,
350 Box::new(v.into()),
351 )
352 }
353
354 fn sub<V>(self, v: V) -> SimpleExpr
356 where
357 V: Into<SimpleExpr>,
358 {
359 SimpleExpr::Binary(
360 Box::new(self.into_simple_expr()),
361 BinOper::Sub,
362 Box::new(v.into()),
363 )
364 }
365
366 fn mul<V>(self, v: V) -> SimpleExpr
368 where
369 V: Into<SimpleExpr>,
370 {
371 SimpleExpr::Binary(
372 Box::new(self.into_simple_expr()),
373 BinOper::Mul,
374 Box::new(v.into()),
375 )
376 }
377
378 fn div<V>(self, v: V) -> SimpleExpr
380 where
381 V: Into<SimpleExpr>,
382 {
383 SimpleExpr::Binary(
384 Box::new(self.into_simple_expr()),
385 BinOper::Div,
386 Box::new(v.into()),
387 )
388 }
389
390 fn modulo<V>(self, v: V) -> SimpleExpr
392 where
393 V: Into<SimpleExpr>,
394 {
395 SimpleExpr::Binary(
396 Box::new(self.into_simple_expr()),
397 BinOper::Mod,
398 Box::new(v.into()),
399 )
400 }
401
402 fn bit_and<V>(self, v: V) -> SimpleExpr
408 where
409 V: Into<SimpleExpr>,
410 {
411 SimpleExpr::Binary(
412 Box::new(self.into_simple_expr()),
413 BinOper::BitAnd,
414 Box::new(v.into()),
415 )
416 }
417
418 fn bit_or<V>(self, v: V) -> SimpleExpr
420 where
421 V: Into<SimpleExpr>,
422 {
423 SimpleExpr::Binary(
424 Box::new(self.into_simple_expr()),
425 BinOper::BitOr,
426 Box::new(v.into()),
427 )
428 }
429
430 fn left_shift<V>(self, v: V) -> SimpleExpr
432 where
433 V: Into<SimpleExpr>,
434 {
435 SimpleExpr::Binary(
436 Box::new(self.into_simple_expr()),
437 BinOper::LShift,
438 Box::new(v.into()),
439 )
440 }
441
442 fn right_shift<V>(self, v: V) -> SimpleExpr
444 where
445 V: Into<SimpleExpr>,
446 {
447 SimpleExpr::Binary(
448 Box::new(self.into_simple_expr()),
449 BinOper::RShift,
450 Box::new(v.into()),
451 )
452 }
453
454 fn cast_as<T>(self, type_name: T) -> SimpleExpr
467 where
468 T: crate::types::IntoIden,
469 {
470 SimpleExpr::Cast(Box::new(self.into_simple_expr()), type_name.into_iden())
471 }
472
473 fn as_enum<T>(self, type_name: T) -> SimpleExpr
475 where
476 T: crate::types::IntoIden,
477 {
478 SimpleExpr::AsEnum(type_name.into_iden(), Box::new(self.into_simple_expr()))
479 }
480}
481
482impl ExprTrait for SimpleExpr {
484 fn into_simple_expr(self) -> SimpleExpr {
485 self
486 }
487}
488
489impl ExprTrait for super::expr::Expr {
491 fn into_simple_expr(self) -> SimpleExpr {
492 self.into_simple_expr()
493 }
494}
495
496#[cfg(test)]
497mod tests {
498 use super::*;
499 use crate::expr::Expr;
500 use rstest::rstest;
501
502 #[rstest]
503 fn test_eq() {
504 let expr = Expr::col("name").eq("Alice");
505 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Equal, _)));
506 }
507
508 #[rstest]
509 fn test_ne() {
510 let expr = Expr::col("name").ne("Bob");
511 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::NotEqual, _)));
512 }
513
514 #[rstest]
515 fn test_lt() {
516 let expr = Expr::col("age").lt(18);
517 assert!(matches!(
518 expr,
519 SimpleExpr::Binary(_, BinOper::SmallerThan, _)
520 ));
521 }
522
523 #[rstest]
524 fn test_lte() {
525 let expr = Expr::col("age").lte(65);
526 assert!(matches!(
527 expr,
528 SimpleExpr::Binary(_, BinOper::SmallerThanOrEqual, _)
529 ));
530 }
531
532 #[rstest]
533 fn test_gt() {
534 let expr = Expr::col("age").gt(18);
535 assert!(matches!(
536 expr,
537 SimpleExpr::Binary(_, BinOper::GreaterThan, _)
538 ));
539 }
540
541 #[rstest]
542 fn test_gte() {
543 let expr = Expr::col("age").gte(18);
544 assert!(matches!(
545 expr,
546 SimpleExpr::Binary(_, BinOper::GreaterThanOrEqual, _)
547 ));
548 }
549
550 #[rstest]
551 fn test_is_null() {
552 let expr = Expr::col("deleted_at").is_null();
553 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Is, _)));
554 }
555
556 #[rstest]
557 fn test_is_not_null() {
558 let expr = Expr::col("name").is_not_null();
559 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::IsNot, _)));
560 }
561
562 #[rstest]
563 fn test_between() {
564 let expr = Expr::col("age").between(18, 65);
565 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Between, _)));
566 }
567
568 #[rstest]
569 fn test_not_between() {
570 let expr = Expr::col("age").not_between(0, 17);
571 assert!(matches!(
572 expr,
573 SimpleExpr::Binary(_, BinOper::NotBetween, _)
574 ));
575 }
576
577 #[rstest]
578 fn test_is_in() {
579 let expr = Expr::col("status").is_in(["active", "pending"]);
580 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::In, _)));
581 }
582
583 #[rstest]
584 fn test_is_not_in() {
585 let expr = Expr::col("status").is_not_in(["deleted", "banned"]);
586 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::NotIn, _)));
587 }
588
589 #[rstest]
590 fn test_like() {
591 let expr = Expr::col("name").like("%john%");
592 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Like, _)));
593 }
594
595 #[rstest]
596 fn test_not_like() {
597 let expr = Expr::col("name").not_like("%admin%");
598 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::NotLike, _)));
599 }
600
601 #[rstest]
602 fn test_starts_with() {
603 let expr = Expr::col("name").starts_with("John");
604 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Like, _)));
605 }
606
607 #[rstest]
608 fn test_ends_with() {
609 let expr = Expr::col("email").ends_with("@example.com");
610 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Like, _)));
611 }
612
613 #[rstest]
614 fn test_contains() {
615 let expr = Expr::col("description").contains("important");
616 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Like, _)));
617 }
618
619 #[rstest]
620 fn test_and() {
621 let expr = Expr::col("active")
622 .eq(true)
623 .and(Expr::col("verified").eq(true));
624 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::And, _)));
625 }
626
627 #[rstest]
628 fn test_or() {
629 let expr = Expr::col("role")
630 .eq("admin")
631 .or(Expr::col("role").eq("moderator"));
632 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Or, _)));
633 }
634
635 #[rstest]
636 fn test_not() {
637 let expr = Expr::col("deleted").not();
638 assert!(matches!(expr, SimpleExpr::Unary(UnOper::Not, _)));
639 }
640
641 #[rstest]
642 fn test_add() {
643 let expr = Expr::col("price").add(10);
644 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Add, _)));
645 }
646
647 #[rstest]
648 fn test_sub() {
649 let expr = Expr::col("quantity").sub(1);
650 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Sub, _)));
651 }
652
653 #[rstest]
654 fn test_mul() {
655 let expr = Expr::col("price").mul(Expr::col("quantity"));
656 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Mul, _)));
657 }
658
659 #[rstest]
660 fn test_div() {
661 let expr = Expr::col("total").div(Expr::col("count"));
662 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Div, _)));
663 }
664
665 #[rstest]
666 fn test_modulo() {
667 let expr = Expr::col("value").modulo(2);
668 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::Mod, _)));
669 }
670
671 #[rstest]
672 fn test_cast_as() {
673 let expr = Expr::col("age").cast_as("TEXT");
674 assert!(matches!(expr, SimpleExpr::Cast(_, _)));
675 }
676
677 #[rstest]
678 fn test_chained_operations() {
679 let expr = Expr::col("age")
681 .gte(18)
682 .and(Expr::col("active").eq(true))
683 .and(Expr::col("verified").is_not_null());
684
685 assert!(matches!(expr, SimpleExpr::Binary(_, BinOper::And, _)));
686 }
687}