reinhardt_query/expr/
condition.rs1use super::simple_expr::SimpleExpr;
7use crate::types::LogicalChainOper;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11pub enum ConditionType {
12 #[default]
14 All,
15 Any,
17}
18
19#[derive(Debug, Clone)]
21pub enum ConditionExpression {
22 SimpleExpr(SimpleExpr),
24 Condition(Condition),
26}
27
28#[derive(Debug, Clone, Default)]
53pub struct Condition {
54 pub condition_type: ConditionType,
56 pub negate: bool,
58 pub conditions: Vec<ConditionExpression>,
60}
61
62impl Condition {
63 pub fn new(condition_type: ConditionType) -> Self {
65 Self {
66 condition_type,
67 negate: false,
68 conditions: Vec::new(),
69 }
70 }
71
72 pub fn all() -> Self {
74 Self::new(ConditionType::All)
75 }
76
77 pub fn any() -> Self {
79 Self::new(ConditionType::Any)
80 }
81
82 #[must_use]
84 #[allow(clippy::should_implement_trait)]
86 pub fn add<C>(mut self, condition: C) -> Self
87 where
88 C: IntoCondition,
89 {
90 self.conditions.push(condition.into_condition_expression());
91 self
92 }
93
94 #[must_use]
96 pub fn add_option<C>(self, condition: Option<C>) -> Self
97 where
98 C: IntoCondition,
99 {
100 if let Some(c) = condition {
101 self.add(c)
102 } else {
103 self
104 }
105 }
106
107 #[must_use]
109 #[allow(clippy::should_implement_trait)]
111 pub fn not(mut self) -> Self {
112 self.negate = !self.negate;
113 self
114 }
115
116 pub fn is_empty(&self) -> bool {
118 self.conditions.is_empty()
119 }
120
121 pub fn len(&self) -> usize {
123 self.conditions.len()
124 }
125
126 pub fn logical_oper(&self) -> LogicalChainOper {
128 match self.condition_type {
129 ConditionType::All => LogicalChainOper::And,
130 ConditionType::Any => LogicalChainOper::Or,
131 }
132 }
133}
134
135pub struct Cond;
139
140impl Cond {
141 pub fn all() -> Condition {
153 Condition::all()
154 }
155
156 pub fn any() -> Condition {
168 Condition::any()
169 }
170}
171
172pub trait IntoCondition {
174 fn into_condition_expression(self) -> ConditionExpression;
176
177 fn into_condition(self) -> Condition
179 where
180 Self: Sized,
181 {
182 let expr = self.into_condition_expression();
183 match expr {
184 ConditionExpression::Condition(c) => c,
185 ConditionExpression::SimpleExpr(e) => Condition::all().add(e),
186 }
187 }
188}
189
190impl IntoCondition for Condition {
191 fn into_condition_expression(self) -> ConditionExpression {
192 ConditionExpression::Condition(self)
193 }
194
195 fn into_condition(self) -> Condition {
196 self
197 }
198}
199
200impl IntoCondition for SimpleExpr {
201 fn into_condition_expression(self) -> ConditionExpression {
202 ConditionExpression::SimpleExpr(self)
203 }
204}
205
206impl IntoCondition for super::expr::Expr {
207 fn into_condition_expression(self) -> ConditionExpression {
208 ConditionExpression::SimpleExpr(self.into_simple_expr())
209 }
210}
211
212#[derive(Debug, Clone, Default)]
216pub struct ConditionHolder {
217 pub conditions: Vec<ConditionExpression>,
219}
220
221impl ConditionHolder {
222 pub fn new() -> Self {
224 Self::default()
225 }
226
227 pub fn add_and<C>(&mut self, condition: C)
229 where
230 C: IntoCondition,
231 {
232 self.conditions.push(condition.into_condition_expression());
233 }
234
235 pub fn add_or<C>(&mut self, condition: C)
237 where
238 C: IntoCondition,
239 {
240 if !self.conditions.is_empty() {
242 let existing = std::mem::take(&mut self.conditions);
243 let mut or_cond = Condition::any();
244 for c in existing {
245 or_cond.conditions.push(c);
246 }
247 or_cond
248 .conditions
249 .push(condition.into_condition_expression());
250 self.conditions
251 .push(ConditionExpression::Condition(or_cond));
252 } else {
253 self.conditions.push(condition.into_condition_expression());
254 }
255 }
256
257 pub fn set_condition(&mut self, condition: Condition) {
259 self.conditions = vec![ConditionExpression::Condition(condition)];
260 }
261
262 pub fn is_empty(&self) -> bool {
264 self.conditions.is_empty()
265 }
266
267 pub fn len(&self) -> usize {
269 self.conditions.len()
270 }
271
272 pub fn into_condition(mut self) -> Option<Condition> {
274 if self.conditions.is_empty() {
275 return None;
276 }
277
278 if self.conditions.len() == 1 {
279 match self.conditions.pop() {
281 Some(ConditionExpression::Condition(c)) => return Some(c),
282 Some(ConditionExpression::SimpleExpr(e)) => {
283 return Some(Condition::all().add(e));
284 }
285 None => return None,
286 }
287 }
288
289 let mut cond = Condition::all();
290 cond.conditions = self.conditions;
291 Some(cond)
292 }
293}
294
295#[macro_export]
308macro_rules! all {
309 ($($expr:expr),* $(,)?) => {
310 {
311 let mut cond = $crate::expr::Cond::all();
312 $(
313 cond = cond.add($expr);
314 )*
315 cond
316 }
317 };
318}
319
320#[macro_export]
333macro_rules! any {
334 ($($expr:expr),* $(,)?) => {
335 {
336 let mut cond = $crate::expr::Cond::any();
337 $(
338 cond = cond.add($expr);
339 )*
340 cond
341 }
342 };
343}
344
345#[cfg(test)]
346mod tests {
347 use super::*;
348 use crate::expr::{Expr, ExprTrait};
349 use rstest::rstest;
350
351 #[rstest]
352 fn test_condition_all() {
353 let cond = Cond::all()
354 .add(Expr::col("active").eq(true))
355 .add(Expr::col("verified").eq(true));
356
357 assert_eq!(cond.condition_type, ConditionType::All);
358 assert_eq!(cond.len(), 2);
359 assert!(!cond.is_empty());
360 }
361
362 #[rstest]
363 fn test_condition_any() {
364 let cond = Cond::any()
365 .add(Expr::col("role").eq("admin"))
366 .add(Expr::col("role").eq("moderator"));
367
368 assert_eq!(cond.condition_type, ConditionType::Any);
369 assert_eq!(cond.len(), 2);
370 }
371
372 #[rstest]
373 fn test_condition_nested() {
374 let cond = Cond::all().add(Expr::col("verified").eq(true)).add(
375 Cond::any()
376 .add(Expr::col("role").eq("admin"))
377 .add(Expr::col("role").eq("moderator")),
378 );
379
380 assert_eq!(cond.len(), 2);
381 }
382
383 #[rstest]
384 fn test_condition_not() {
385 let cond = Cond::all().add(Expr::col("deleted").eq(true)).not();
386
387 assert!(cond.negate);
388 }
389
390 #[rstest]
391 fn test_condition_add_option() {
392 let filter_active: Option<bool> = Some(true);
393 let filter_role: Option<&str> = None;
394
395 let cond = Cond::all()
396 .add_option(filter_active.map(|v| Expr::col("active").eq(v)))
397 .add_option(filter_role.map(|v| Expr::col("role").eq(v)));
398
399 assert_eq!(cond.len(), 1); }
401
402 #[rstest]
403 fn test_condition_empty() {
404 let cond = Cond::all();
405 assert!(cond.is_empty());
406 assert_eq!(cond.len(), 0);
407 }
408
409 #[rstest]
410 fn test_condition_holder() {
411 let mut holder = ConditionHolder::new();
412 assert!(holder.is_empty());
413
414 holder.add_and(Expr::col("active").eq(true));
415 holder.add_and(Expr::col("verified").eq(true));
416
417 assert!(!holder.is_empty());
418 assert_eq!(holder.len(), 2);
419 }
420
421 #[rstest]
422 fn test_condition_holder_into_condition() {
423 let mut holder = ConditionHolder::new();
424 holder.add_and(Expr::col("active").eq(true));
425 holder.add_and(Expr::col("verified").eq(true));
426
427 let cond = holder.into_condition();
428 assert!(cond.is_some());
429 }
430
431 #[rstest]
432 fn test_all_macro() {
433 let cond = all![Expr::col("a").eq(1), Expr::col("b").eq(2),];
434
435 assert_eq!(cond.condition_type, ConditionType::All);
436 assert_eq!(cond.len(), 2);
437 }
438
439 #[rstest]
440 fn test_any_macro() {
441 let cond = any![Expr::col("a").eq(1), Expr::col("b").eq(2),];
442
443 assert_eq!(cond.condition_type, ConditionType::Any);
444 assert_eq!(cond.len(), 2);
445 }
446
447 #[rstest]
448 fn test_logical_oper() {
449 assert_eq!(Cond::all().logical_oper(), LogicalChainOper::And);
450 assert_eq!(Cond::any().logical_oper(), LogicalChainOper::Or);
451 }
452}