dojo_orm/
predicates.rs

1use std::borrow::Cow;
2
3use crate::types::ToSql;
4
5#[derive(Debug, Copy, Clone)]
6pub enum ExprValueType {
7    Value,
8    Array,
9}
10
11#[derive(Debug, Clone)]
12pub struct Expr<'a> {
13    pub ty: ExprValueType,
14    pub column: Cow<'a, str>,
15    pub condition: &'a str,
16    pub value: &'a (dyn ToSql + Sync),
17}
18
19#[derive(Debug, Clone)]
20pub enum Predicate<'a> {
21    Value(Expr<'a>),
22    And(&'a [Predicate<'a>]),
23    Or(&'a [Predicate<'a>]),
24    Empty
25}
26
27impl<'a> Default for Predicate<'a> {
28    fn default() -> Self {
29        Predicate::Empty
30    }
31}
32
33impl<'a> Predicate<'a> {
34    pub fn to_sql(
35        &self,
36        params_index: &mut usize,
37    ) -> (Option<String>, Vec<&'a (dyn ToSql + Sync)>) {
38        match self {
39            Predicate::Value(expr) => {
40                let query = match expr.ty {
41                    ExprValueType::Value => {
42                        format!("{} {} ${}", expr.column, expr.condition, params_index)
43                    }
44                    ExprValueType::Array => {
45                        format!("{} {} ANY(${})", expr.column, expr.condition, params_index)
46                    }
47                };
48                let params = vec![expr.value];
49                *params_index += 1;
50                (Some(query), params)
51            }
52            Predicate::And(predicates) => {
53                if predicates.is_empty() {
54                    return (None, vec![]);
55                }
56
57                let mut results = vec![];
58                let mut params = vec![];
59                for predicate in *predicates {
60                    let (q, p) = predicate.to_sql(params_index);
61                    if let Some(q) = q {
62                        results.push(q);
63                        params.extend_from_slice(&p);
64                    }
65                }
66
67                let query = format!("({})", results.join(" AND "));
68                (Some(query), params)
69            }
70            Predicate::Or(predicates) => {
71                if predicates.is_empty() {
72                    return (None, vec![]);
73                }
74
75                let mut results = vec![];
76                let mut params = vec![];
77                for predicate in *predicates {
78                    let (q, p) = predicate.to_sql(params_index);
79                    if let Some(q) = q {
80                        results.push(q);
81                        params.extend_from_slice(&p);
82                    }
83                }
84
85                let query = format!("({})", results.join(" OR "));
86                (Some(query), params)
87            }
88            Predicate::Empty => (None, vec![]),
89        }
90    }
91}
92
93pub fn and<'a>(predicates: &'a [Predicate<'a>]) -> Predicate<'a> {
94    Predicate::And(predicates)
95}
96
97pub fn or<'a>(predicates: &'a [Predicate<'a>]) -> Predicate<'a> {
98    Predicate::Or(predicates)
99}
100
101pub fn equals<'a, T: ToSql + Sync>(column: &'a str, value: &'a T) -> Predicate<'a> {
102    Predicate::Value(Expr {
103        ty: ExprValueType::Value,
104        column: column.into(),
105        condition: "=",
106        value,
107    })
108}
109
110pub fn in_list<'a, T: ToSql + Sync>(column: &'a str, values: &'a T) -> Predicate<'a> {
111    Predicate::Value(Expr {
112        ty: ExprValueType::Array,
113        column: column.into(),
114        condition: "=",
115        value: values,
116    })
117}
118
119#[cfg(test)]
120mod tests {
121    #[test]
122    fn test_and() {
123        // use super::{and, eq, in_list, Op};
124        // use crate::types::ToSql;
125        //
126        // let op = and(&[eq("foo", &1), eq("bar", &2), in_list("baz", &vec![3, 4, 5])]);
127        //
128        // match op {
129        //     Op::And(predicates) => {
130        //         assert_eq!(predicates.len(), 3);
131        //         match &predicates[0] {
132        //             Op::Value(op_value) => {
133        //                 assert_eq!(op_value.column, "foo");
134        //                 assert_eq!(op_value.op, "=");
135        //                 assert_eq!(
136        //                     op_value
137        //                         .value
138        //                         .to_sql(&crate::types::Type::INT4, &mut vec![])
139        //                         .unwrap(),
140        //                     1
141        //                 );
142        //             }
143        //             _ => panic!("Expected Op::Value"),
144        //         }
145        //         match &predicates[1] {
146        //             Op::Value(op_value) => {
147        //                 assert_eq!(op_value.column, "bar");
148        //                 assert_eq!(op_value.op, "=");
149        //                 assert_eq!(
150        //                     op_value
151        //                         .value
152        //                         .to_sql(&crate::types::Type::INT4, &mut vec![])
153        //                         .unwrap(),
154        //                     2
155        //                 );
156        //             }
157        //             _ => panic!("Expected Op::Value"),
158        //         }
159        //         match &predicates[2] {
160        //             Op::Value(op_value) => {
161        //                 assert_eq!(op_value.column, "baz");
162        //                 assert_eq!(op_value.op, "IN");
163        //                 assert_eq!(
164        //                     op_value
165        //                         .value
166        //                         .to_sql(&crate::types::Type::INT4, &mut vec![])
167        //                         .unwrap(),
168        //                     vec![3, 4, 5]
169        //                 );
170        //             }
171        //             _ => panic!("Expected Op::Value"),
172        //         }
173        //     }
174        //     _ => panic!("Expected Op::And"),
175        // }
176    }
177}