Skip to main content

sql_orm/
predicate_composition.rs

1use 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}