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}