sql_orm/
predicate_composition.rs1use sql_orm_query::Predicate;
2
3pub trait PredicateCompositionExt {
4 fn and(self, other: Predicate) -> Predicate;
5
6 fn or(self, other: Predicate) -> Predicate;
7
8 fn not(self) -> Predicate;
9}
10
11impl PredicateCompositionExt for Predicate {
12 fn and(self, other: Predicate) -> Predicate {
13 match (self, other) {
14 (Predicate::And(mut left), Predicate::And(right)) => {
15 left.extend(right);
16 Predicate::and(left)
17 }
18 (Predicate::And(mut left), right) => {
19 left.push(right);
20 Predicate::and(left)
21 }
22 (left, Predicate::And(mut right)) => {
23 let mut predicates = vec![left];
24 predicates.append(&mut right);
25 Predicate::and(predicates)
26 }
27 (left, right) => Predicate::and(vec![left, right]),
28 }
29 }
30
31 fn or(self, other: Predicate) -> Predicate {
32 match (self, other) {
33 (Predicate::Or(mut left), Predicate::Or(right)) => {
34 left.extend(right);
35 Predicate::or(left)
36 }
37 (Predicate::Or(mut left), right) => {
38 left.push(right);
39 Predicate::or(left)
40 }
41 (left, Predicate::Or(mut right)) => {
42 let mut predicates = vec![left];
43 predicates.append(&mut right);
44 Predicate::or(predicates)
45 }
46 (left, right) => Predicate::or(vec![left, right]),
47 }
48 }
49
50 fn not(self) -> Predicate {
51 Predicate::negate(self)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::PredicateCompositionExt;
58 use sql_orm_core::SqlValue;
59 use sql_orm_query::{Expr, Predicate};
60
61 #[test]
62 fn and_combines_two_predicates() {
63 let left = Predicate::eq(
64 Expr::value(SqlValue::Bool(true)),
65 Expr::value(SqlValue::Bool(true)),
66 );
67 let right = Predicate::gt(
68 Expr::value(SqlValue::I64(10)),
69 Expr::value(SqlValue::I64(5)),
70 );
71
72 assert_eq!(
73 left.clone().and(right.clone()),
74 Predicate::and(vec![left, right])
75 );
76 }
77
78 #[test]
79 fn and_flattens_existing_and_groups() {
80 let first = Predicate::eq(Expr::value(SqlValue::I64(1)), Expr::value(SqlValue::I64(1)));
81 let second = Predicate::eq(Expr::value(SqlValue::I64(2)), Expr::value(SqlValue::I64(2)));
82 let third = Predicate::eq(Expr::value(SqlValue::I64(3)), Expr::value(SqlValue::I64(3)));
83
84 assert_eq!(
85 Predicate::and(vec![first.clone(), second.clone()]).and(third.clone()),
86 Predicate::and(vec![first, second, third])
87 );
88 }
89
90 #[test]
91 fn or_combines_and_flattens_predicates() {
92 let first = Predicate::eq(Expr::value(SqlValue::I64(1)), Expr::value(SqlValue::I64(1)));
93 let second = Predicate::eq(Expr::value(SqlValue::I64(2)), Expr::value(SqlValue::I64(2)));
94 let third = Predicate::eq(Expr::value(SqlValue::I64(3)), Expr::value(SqlValue::I64(3)));
95
96 assert_eq!(
97 Predicate::or(vec![first.clone(), second.clone()]).or(third.clone()),
98 Predicate::or(vec![first, second, third])
99 );
100 }
101
102 #[test]
103 fn not_wraps_predicate_in_negation() {
104 let predicate = Predicate::eq(
105 Expr::value(SqlValue::Bool(true)),
106 Expr::value(SqlValue::Bool(false)),
107 );
108
109 assert_eq!(predicate.clone().not(), Predicate::negate(predicate));
110 }
111}