1use postrust_core::api_request::{
7 Field, Filter, LogicOperator, LogicTree, OpExpr, Operation, QuantOperator,
8};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13pub struct StringFilterInput {
14 pub eq: Option<String>,
16 pub neq: Option<String>,
18 pub like: Option<String>,
20 pub ilike: Option<String>,
22 #[serde(rename = "in")]
24 pub in_list: Option<Vec<String>>,
25 #[serde(rename = "isNull")]
27 pub is_null: Option<bool>,
28 #[serde(rename = "startsWith")]
30 pub starts_with: Option<String>,
31 #[serde(rename = "endsWith")]
33 pub ends_with: Option<String>,
34 pub contains: Option<String>,
36}
37
38impl StringFilterInput {
39 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
41 let mut filters = Vec::new();
42 let field = Field::simple(field_name);
43
44 if let Some(ref value) = self.eq {
45 filters.push(Filter::new(
46 field.clone(),
47 OpExpr::new(Operation::Quant {
48 op: QuantOperator::Equal,
49 quantifier: None,
50 value: value.clone(),
51 }),
52 ));
53 }
54
55 if let Some(ref value) = self.neq {
56 filters.push(Filter::new(
57 field.clone(),
58 OpExpr::new(Operation::Quant {
59 op: QuantOperator::Equal,
60 quantifier: None,
61 value: value.clone(),
62 })
63 .with_negated(true),
64 ));
65 }
66
67 if let Some(ref value) = self.like {
68 filters.push(Filter::new(
69 field.clone(),
70 OpExpr::new(Operation::Quant {
71 op: QuantOperator::Like,
72 quantifier: None,
73 value: value.clone(),
74 }),
75 ));
76 }
77
78 if let Some(ref value) = self.ilike {
79 filters.push(Filter::new(
80 field.clone(),
81 OpExpr::new(Operation::Quant {
82 op: QuantOperator::ILike,
83 quantifier: None,
84 value: value.clone(),
85 }),
86 ));
87 }
88
89 if let Some(ref values) = self.in_list {
90 filters.push(Filter::new(
91 field.clone(),
92 OpExpr::new(Operation::In(values.clone())),
93 ));
94 }
95
96 if let Some(is_null) = self.is_null {
97 let op_expr = OpExpr::new(Operation::Is(postrust_core::api_request::IsValue::Null));
98 filters.push(Filter::new(
99 field.clone(),
100 if is_null {
101 op_expr
102 } else {
103 op_expr.with_negated(true)
104 },
105 ));
106 }
107
108 if let Some(ref value) = self.starts_with {
109 filters.push(Filter::new(
110 field.clone(),
111 OpExpr::new(Operation::Quant {
112 op: QuantOperator::Like,
113 quantifier: None,
114 value: format!("{}%", value),
115 }),
116 ));
117 }
118
119 if let Some(ref value) = self.ends_with {
120 filters.push(Filter::new(
121 field.clone(),
122 OpExpr::new(Operation::Quant {
123 op: QuantOperator::Like,
124 quantifier: None,
125 value: format!("%{}", value),
126 }),
127 ));
128 }
129
130 if let Some(ref value) = self.contains {
131 filters.push(Filter::new(
132 field.clone(),
133 OpExpr::new(Operation::Quant {
134 op: QuantOperator::Like,
135 quantifier: None,
136 value: format!("%{}%", value),
137 }),
138 ));
139 }
140
141 filters
142 }
143
144 pub fn is_empty(&self) -> bool {
146 self.eq.is_none()
147 && self.neq.is_none()
148 && self.like.is_none()
149 && self.ilike.is_none()
150 && self.in_list.is_none()
151 && self.is_null.is_none()
152 && self.starts_with.is_none()
153 && self.ends_with.is_none()
154 && self.contains.is_none()
155 }
156}
157
158#[derive(Debug, Clone, Default, Serialize, Deserialize)]
160pub struct IntFilterInput {
161 pub eq: Option<i64>,
163 pub neq: Option<i64>,
165 pub gt: Option<i64>,
167 pub gte: Option<i64>,
169 pub lt: Option<i64>,
171 pub lte: Option<i64>,
173 #[serde(rename = "in")]
175 pub in_list: Option<Vec<i64>>,
176 #[serde(rename = "isNull")]
178 pub is_null: Option<bool>,
179}
180
181impl IntFilterInput {
182 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
184 let mut filters = Vec::new();
185 let field = Field::simple(field_name);
186
187 if let Some(value) = self.eq {
188 filters.push(Filter::new(
189 field.clone(),
190 OpExpr::new(Operation::Quant {
191 op: QuantOperator::Equal,
192 quantifier: None,
193 value: value.to_string(),
194 }),
195 ));
196 }
197
198 if let Some(value) = self.neq {
199 filters.push(Filter::new(
200 field.clone(),
201 OpExpr::new(Operation::Quant {
202 op: QuantOperator::Equal,
203 quantifier: None,
204 value: value.to_string(),
205 })
206 .with_negated(true),
207 ));
208 }
209
210 if let Some(value) = self.gt {
211 filters.push(Filter::new(
212 field.clone(),
213 OpExpr::new(Operation::Quant {
214 op: QuantOperator::GreaterThan,
215 quantifier: None,
216 value: value.to_string(),
217 }),
218 ));
219 }
220
221 if let Some(value) = self.gte {
222 filters.push(Filter::new(
223 field.clone(),
224 OpExpr::new(Operation::Quant {
225 op: QuantOperator::GreaterThanEqual,
226 quantifier: None,
227 value: value.to_string(),
228 }),
229 ));
230 }
231
232 if let Some(value) = self.lt {
233 filters.push(Filter::new(
234 field.clone(),
235 OpExpr::new(Operation::Quant {
236 op: QuantOperator::LessThan,
237 quantifier: None,
238 value: value.to_string(),
239 }),
240 ));
241 }
242
243 if let Some(value) = self.lte {
244 filters.push(Filter::new(
245 field.clone(),
246 OpExpr::new(Operation::Quant {
247 op: QuantOperator::LessThanEqual,
248 quantifier: None,
249 value: value.to_string(),
250 }),
251 ));
252 }
253
254 if let Some(ref values) = self.in_list {
255 filters.push(Filter::new(
256 field.clone(),
257 OpExpr::new(Operation::In(
258 values.iter().map(|v| v.to_string()).collect(),
259 )),
260 ));
261 }
262
263 if let Some(is_null) = self.is_null {
264 let op_expr = OpExpr::new(Operation::Is(postrust_core::api_request::IsValue::Null));
265 filters.push(Filter::new(
266 field.clone(),
267 if is_null {
268 op_expr
269 } else {
270 op_expr.with_negated(true)
271 },
272 ));
273 }
274
275 filters
276 }
277
278 pub fn is_empty(&self) -> bool {
280 self.eq.is_none()
281 && self.neq.is_none()
282 && self.gt.is_none()
283 && self.gte.is_none()
284 && self.lt.is_none()
285 && self.lte.is_none()
286 && self.in_list.is_none()
287 && self.is_null.is_none()
288 }
289}
290
291#[derive(Debug, Clone, Default, Serialize, Deserialize)]
293pub struct FloatFilterInput {
294 pub eq: Option<f64>,
296 pub neq: Option<f64>,
298 pub gt: Option<f64>,
300 pub gte: Option<f64>,
302 pub lt: Option<f64>,
304 pub lte: Option<f64>,
306 #[serde(rename = "isNull")]
308 pub is_null: Option<bool>,
309}
310
311impl FloatFilterInput {
312 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
314 let mut filters = Vec::new();
315 let field = Field::simple(field_name);
316
317 if let Some(value) = self.eq {
318 filters.push(Filter::new(
319 field.clone(),
320 OpExpr::new(Operation::Quant {
321 op: QuantOperator::Equal,
322 quantifier: None,
323 value: value.to_string(),
324 }),
325 ));
326 }
327
328 if let Some(value) = self.neq {
329 filters.push(Filter::new(
330 field.clone(),
331 OpExpr::new(Operation::Quant {
332 op: QuantOperator::Equal,
333 quantifier: None,
334 value: value.to_string(),
335 })
336 .with_negated(true),
337 ));
338 }
339
340 if let Some(value) = self.gt {
341 filters.push(Filter::new(
342 field.clone(),
343 OpExpr::new(Operation::Quant {
344 op: QuantOperator::GreaterThan,
345 quantifier: None,
346 value: value.to_string(),
347 }),
348 ));
349 }
350
351 if let Some(value) = self.gte {
352 filters.push(Filter::new(
353 field.clone(),
354 OpExpr::new(Operation::Quant {
355 op: QuantOperator::GreaterThanEqual,
356 quantifier: None,
357 value: value.to_string(),
358 }),
359 ));
360 }
361
362 if let Some(value) = self.lt {
363 filters.push(Filter::new(
364 field.clone(),
365 OpExpr::new(Operation::Quant {
366 op: QuantOperator::LessThan,
367 quantifier: None,
368 value: value.to_string(),
369 }),
370 ));
371 }
372
373 if let Some(value) = self.lte {
374 filters.push(Filter::new(
375 field.clone(),
376 OpExpr::new(Operation::Quant {
377 op: QuantOperator::LessThanEqual,
378 quantifier: None,
379 value: value.to_string(),
380 }),
381 ));
382 }
383
384 if let Some(is_null) = self.is_null {
385 let op_expr = OpExpr::new(Operation::Is(postrust_core::api_request::IsValue::Null));
386 filters.push(Filter::new(
387 field.clone(),
388 if is_null {
389 op_expr
390 } else {
391 op_expr.with_negated(true)
392 },
393 ));
394 }
395
396 filters
397 }
398
399 pub fn is_empty(&self) -> bool {
401 self.eq.is_none()
402 && self.neq.is_none()
403 && self.gt.is_none()
404 && self.gte.is_none()
405 && self.lt.is_none()
406 && self.lte.is_none()
407 && self.is_null.is_none()
408 }
409}
410
411#[derive(Debug, Clone, Default, Serialize, Deserialize)]
413pub struct BooleanFilterInput {
414 pub eq: Option<bool>,
416 #[serde(rename = "isNull")]
418 pub is_null: Option<bool>,
419}
420
421impl BooleanFilterInput {
422 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
424 let mut filters = Vec::new();
425 let field = Field::simple(field_name);
426
427 if let Some(value) = self.eq {
428 filters.push(Filter::new(
429 field.clone(),
430 OpExpr::new(Operation::Is(if value {
431 postrust_core::api_request::IsValue::True
432 } else {
433 postrust_core::api_request::IsValue::False
434 })),
435 ));
436 }
437
438 if let Some(is_null) = self.is_null {
439 let op_expr = OpExpr::new(Operation::Is(postrust_core::api_request::IsValue::Null));
440 filters.push(Filter::new(
441 field.clone(),
442 if is_null {
443 op_expr
444 } else {
445 op_expr.with_negated(true)
446 },
447 ));
448 }
449
450 filters
451 }
452
453 pub fn is_empty(&self) -> bool {
455 self.eq.is_none() && self.is_null.is_none()
456 }
457}
458
459#[derive(Debug, Clone, Default, Serialize, Deserialize)]
461pub struct UuidFilterInput {
462 pub eq: Option<String>,
464 pub neq: Option<String>,
466 #[serde(rename = "in")]
468 pub in_list: Option<Vec<String>>,
469 #[serde(rename = "isNull")]
471 pub is_null: Option<bool>,
472}
473
474impl UuidFilterInput {
475 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
477 let mut filters = Vec::new();
478 let field = Field::simple(field_name);
479
480 if let Some(ref value) = self.eq {
481 filters.push(Filter::new(
482 field.clone(),
483 OpExpr::new(Operation::Quant {
484 op: QuantOperator::Equal,
485 quantifier: None,
486 value: value.clone(),
487 }),
488 ));
489 }
490
491 if let Some(ref value) = self.neq {
492 filters.push(Filter::new(
493 field.clone(),
494 OpExpr::new(Operation::Quant {
495 op: QuantOperator::Equal,
496 quantifier: None,
497 value: value.clone(),
498 })
499 .with_negated(true),
500 ));
501 }
502
503 if let Some(ref values) = self.in_list {
504 filters.push(Filter::new(
505 field.clone(),
506 OpExpr::new(Operation::In(values.clone())),
507 ));
508 }
509
510 if let Some(is_null) = self.is_null {
511 let op_expr = OpExpr::new(Operation::Is(postrust_core::api_request::IsValue::Null));
512 filters.push(Filter::new(
513 field.clone(),
514 if is_null {
515 op_expr
516 } else {
517 op_expr.with_negated(true)
518 },
519 ));
520 }
521
522 filters
523 }
524
525 pub fn is_empty(&self) -> bool {
527 self.eq.is_none() && self.neq.is_none() && self.in_list.is_none() && self.is_null.is_none()
528 }
529}
530
531pub fn filters_to_logic_tree(filters: Vec<Filter>) -> Option<LogicTree> {
533 if filters.is_empty() {
534 return None;
535 }
536
537 if filters.len() == 1 {
538 return Some(LogicTree::Stmt(filters.into_iter().next().unwrap()));
539 }
540
541 Some(LogicTree::Expr {
542 negated: false,
543 op: LogicOperator::And,
544 children: filters.into_iter().map(LogicTree::Stmt).collect(),
545 })
546}
547
548pub fn combine_with_and(trees: Vec<LogicTree>) -> Option<LogicTree> {
550 if trees.is_empty() {
551 return None;
552 }
553
554 if trees.len() == 1 {
555 return Some(trees.into_iter().next().unwrap());
556 }
557
558 Some(LogicTree::Expr {
559 negated: false,
560 op: LogicOperator::And,
561 children: trees,
562 })
563}
564
565pub fn combine_with_or(trees: Vec<LogicTree>) -> Option<LogicTree> {
567 if trees.is_empty() {
568 return None;
569 }
570
571 if trees.len() == 1 {
572 return Some(trees.into_iter().next().unwrap());
573 }
574
575 Some(LogicTree::Expr {
576 negated: false,
577 op: LogicOperator::Or,
578 children: trees,
579 })
580}
581
582pub fn negate_tree(tree: LogicTree) -> LogicTree {
584 match tree {
585 LogicTree::Expr {
586 negated,
587 op,
588 children,
589 } => LogicTree::Expr {
590 negated: !negated,
591 op,
592 children,
593 },
594 LogicTree::Stmt(filter) => {
595 let negated_expr = OpExpr {
596 negated: !filter.op_expr.negated,
597 operation: filter.op_expr.operation,
598 };
599 LogicTree::Stmt(Filter::new(filter.field, negated_expr))
600 }
601 }
602}
603
604trait OpExprExt {
606 fn with_negated(self, negated: bool) -> Self;
607}
608
609impl OpExprExt for OpExpr {
610 fn with_negated(mut self, negated: bool) -> Self {
611 self.negated = negated;
612 self
613 }
614}
615
616#[cfg(test)]
617mod tests {
618 use super::*;
619 use pretty_assertions::assert_eq;
620
621 #[test]
626 fn test_string_filter_eq() {
627 let filter = StringFilterInput {
628 eq: Some("test".to_string()),
629 ..Default::default()
630 };
631
632 let filters = filter.to_filters("name");
633 assert_eq!(filters.len(), 1);
634 assert_eq!(filters[0].field.name, "name");
635
636 match &filters[0].op_expr.operation {
637 Operation::Quant { op, value, .. } => {
638 assert_eq!(*op, QuantOperator::Equal);
639 assert_eq!(value, "test");
640 }
641 _ => panic!("Expected Quant operation"),
642 }
643 assert!(!filters[0].op_expr.negated);
644 }
645
646 #[test]
647 fn test_string_filter_neq() {
648 let filter = StringFilterInput {
649 neq: Some("test".to_string()),
650 ..Default::default()
651 };
652
653 let filters = filter.to_filters("name");
654 assert_eq!(filters.len(), 1);
655
656 match &filters[0].op_expr.operation {
657 Operation::Quant { op, value, .. } => {
658 assert_eq!(*op, QuantOperator::Equal);
659 assert_eq!(value, "test");
660 }
661 _ => panic!("Expected Quant operation"),
662 }
663 assert!(filters[0].op_expr.negated);
664 }
665
666 #[test]
667 fn test_string_filter_like() {
668 let filter = StringFilterInput {
669 like: Some("%test%".to_string()),
670 ..Default::default()
671 };
672
673 let filters = filter.to_filters("name");
674 assert_eq!(filters.len(), 1);
675
676 match &filters[0].op_expr.operation {
677 Operation::Quant { op, value, .. } => {
678 assert_eq!(*op, QuantOperator::Like);
679 assert_eq!(value, "%test%");
680 }
681 _ => panic!("Expected Quant operation"),
682 }
683 }
684
685 #[test]
686 fn test_string_filter_ilike() {
687 let filter = StringFilterInput {
688 ilike: Some("%TEST%".to_string()),
689 ..Default::default()
690 };
691
692 let filters = filter.to_filters("name");
693 assert_eq!(filters.len(), 1);
694
695 match &filters[0].op_expr.operation {
696 Operation::Quant { op, value, .. } => {
697 assert_eq!(*op, QuantOperator::ILike);
698 assert_eq!(value, "%TEST%");
699 }
700 _ => panic!("Expected Quant operation"),
701 }
702 }
703
704 #[test]
705 fn test_string_filter_in() {
706 let filter = StringFilterInput {
707 in_list: Some(vec!["a".to_string(), "b".to_string(), "c".to_string()]),
708 ..Default::default()
709 };
710
711 let filters = filter.to_filters("status");
712 assert_eq!(filters.len(), 1);
713
714 match &filters[0].op_expr.operation {
715 Operation::In(values) => {
716 assert_eq!(values.len(), 3);
717 assert_eq!(values[0], "a");
718 assert_eq!(values[1], "b");
719 assert_eq!(values[2], "c");
720 }
721 _ => panic!("Expected In operation"),
722 }
723 }
724
725 #[test]
726 fn test_string_filter_is_null_true() {
727 let filter = StringFilterInput {
728 is_null: Some(true),
729 ..Default::default()
730 };
731
732 let filters = filter.to_filters("name");
733 assert_eq!(filters.len(), 1);
734
735 match &filters[0].op_expr.operation {
736 Operation::Is(postrust_core::api_request::IsValue::Null) => {}
737 _ => panic!("Expected Is Null operation"),
738 }
739 assert!(!filters[0].op_expr.negated);
740 }
741
742 #[test]
743 fn test_string_filter_is_null_false() {
744 let filter = StringFilterInput {
745 is_null: Some(false),
746 ..Default::default()
747 };
748
749 let filters = filter.to_filters("name");
750 assert_eq!(filters.len(), 1);
751
752 match &filters[0].op_expr.operation {
753 Operation::Is(postrust_core::api_request::IsValue::Null) => {}
754 _ => panic!("Expected Is Null operation"),
755 }
756 assert!(filters[0].op_expr.negated);
757 }
758
759 #[test]
760 fn test_string_filter_starts_with() {
761 let filter = StringFilterInput {
762 starts_with: Some("hello".to_string()),
763 ..Default::default()
764 };
765
766 let filters = filter.to_filters("name");
767 assert_eq!(filters.len(), 1);
768
769 match &filters[0].op_expr.operation {
770 Operation::Quant { op, value, .. } => {
771 assert_eq!(*op, QuantOperator::Like);
772 assert_eq!(value, "hello%");
773 }
774 _ => panic!("Expected Quant operation"),
775 }
776 }
777
778 #[test]
779 fn test_string_filter_ends_with() {
780 let filter = StringFilterInput {
781 ends_with: Some("world".to_string()),
782 ..Default::default()
783 };
784
785 let filters = filter.to_filters("name");
786 assert_eq!(filters.len(), 1);
787
788 match &filters[0].op_expr.operation {
789 Operation::Quant { op, value, .. } => {
790 assert_eq!(*op, QuantOperator::Like);
791 assert_eq!(value, "%world");
792 }
793 _ => panic!("Expected Quant operation"),
794 }
795 }
796
797 #[test]
798 fn test_string_filter_contains() {
799 let filter = StringFilterInput {
800 contains: Some("foo".to_string()),
801 ..Default::default()
802 };
803
804 let filters = filter.to_filters("name");
805 assert_eq!(filters.len(), 1);
806
807 match &filters[0].op_expr.operation {
808 Operation::Quant { op, value, .. } => {
809 assert_eq!(*op, QuantOperator::Like);
810 assert_eq!(value, "%foo%");
811 }
812 _ => panic!("Expected Quant operation"),
813 }
814 }
815
816 #[test]
817 fn test_string_filter_multiple() {
818 let filter = StringFilterInput {
819 eq: Some("test".to_string()),
820 starts_with: Some("t".to_string()),
821 ..Default::default()
822 };
823
824 let filters = filter.to_filters("name");
825 assert_eq!(filters.len(), 2);
826 }
827
828 #[test]
829 fn test_string_filter_is_empty() {
830 let filter = StringFilterInput::default();
831 assert!(filter.is_empty());
832
833 let filter = StringFilterInput {
834 eq: Some("test".to_string()),
835 ..Default::default()
836 };
837 assert!(!filter.is_empty());
838 }
839
840 #[test]
845 fn test_int_filter_eq() {
846 let filter = IntFilterInput {
847 eq: Some(42),
848 ..Default::default()
849 };
850
851 let filters = filter.to_filters("age");
852 assert_eq!(filters.len(), 1);
853
854 match &filters[0].op_expr.operation {
855 Operation::Quant { op, value, .. } => {
856 assert_eq!(*op, QuantOperator::Equal);
857 assert_eq!(value, "42");
858 }
859 _ => panic!("Expected Quant operation"),
860 }
861 }
862
863 #[test]
864 fn test_int_filter_neq() {
865 let filter = IntFilterInput {
866 neq: Some(42),
867 ..Default::default()
868 };
869
870 let filters = filter.to_filters("age");
871 assert_eq!(filters.len(), 1);
872 assert!(filters[0].op_expr.negated);
873 }
874
875 #[test]
876 fn test_int_filter_gt() {
877 let filter = IntFilterInput {
878 gt: Some(18),
879 ..Default::default()
880 };
881
882 let filters = filter.to_filters("age");
883 assert_eq!(filters.len(), 1);
884
885 match &filters[0].op_expr.operation {
886 Operation::Quant { op, value, .. } => {
887 assert_eq!(*op, QuantOperator::GreaterThan);
888 assert_eq!(value, "18");
889 }
890 _ => panic!("Expected Quant operation"),
891 }
892 }
893
894 #[test]
895 fn test_int_filter_gte() {
896 let filter = IntFilterInput {
897 gte: Some(18),
898 ..Default::default()
899 };
900
901 let filters = filter.to_filters("age");
902 assert_eq!(filters.len(), 1);
903
904 match &filters[0].op_expr.operation {
905 Operation::Quant { op, value, .. } => {
906 assert_eq!(*op, QuantOperator::GreaterThanEqual);
907 assert_eq!(value, "18");
908 }
909 _ => panic!("Expected Quant operation"),
910 }
911 }
912
913 #[test]
914 fn test_int_filter_lt() {
915 let filter = IntFilterInput {
916 lt: Some(65),
917 ..Default::default()
918 };
919
920 let filters = filter.to_filters("age");
921 assert_eq!(filters.len(), 1);
922
923 match &filters[0].op_expr.operation {
924 Operation::Quant { op, value, .. } => {
925 assert_eq!(*op, QuantOperator::LessThan);
926 assert_eq!(value, "65");
927 }
928 _ => panic!("Expected Quant operation"),
929 }
930 }
931
932 #[test]
933 fn test_int_filter_lte() {
934 let filter = IntFilterInput {
935 lte: Some(65),
936 ..Default::default()
937 };
938
939 let filters = filter.to_filters("age");
940 assert_eq!(filters.len(), 1);
941
942 match &filters[0].op_expr.operation {
943 Operation::Quant { op, value, .. } => {
944 assert_eq!(*op, QuantOperator::LessThanEqual);
945 assert_eq!(value, "65");
946 }
947 _ => panic!("Expected Quant operation"),
948 }
949 }
950
951 #[test]
952 fn test_int_filter_in() {
953 let filter = IntFilterInput {
954 in_list: Some(vec![1, 2, 3]),
955 ..Default::default()
956 };
957
958 let filters = filter.to_filters("id");
959 assert_eq!(filters.len(), 1);
960
961 match &filters[0].op_expr.operation {
962 Operation::In(values) => {
963 assert_eq!(values.len(), 3);
964 assert_eq!(values[0], "1");
965 assert_eq!(values[1], "2");
966 assert_eq!(values[2], "3");
967 }
968 _ => panic!("Expected In operation"),
969 }
970 }
971
972 #[test]
973 fn test_int_filter_range() {
974 let filter = IntFilterInput {
975 gte: Some(18),
976 lte: Some(65),
977 ..Default::default()
978 };
979
980 let filters = filter.to_filters("age");
981 assert_eq!(filters.len(), 2);
982 }
983
984 #[test]
985 fn test_int_filter_is_empty() {
986 let filter = IntFilterInput::default();
987 assert!(filter.is_empty());
988
989 let filter = IntFilterInput {
990 eq: Some(42),
991 ..Default::default()
992 };
993 assert!(!filter.is_empty());
994 }
995
996 #[test]
1001 fn test_boolean_filter_eq_true() {
1002 let filter = BooleanFilterInput {
1003 eq: Some(true),
1004 ..Default::default()
1005 };
1006
1007 let filters = filter.to_filters("active");
1008 assert_eq!(filters.len(), 1);
1009
1010 match &filters[0].op_expr.operation {
1011 Operation::Is(postrust_core::api_request::IsValue::True) => {}
1012 _ => panic!("Expected Is True operation"),
1013 }
1014 }
1015
1016 #[test]
1017 fn test_boolean_filter_eq_false() {
1018 let filter = BooleanFilterInput {
1019 eq: Some(false),
1020 ..Default::default()
1021 };
1022
1023 let filters = filter.to_filters("active");
1024 assert_eq!(filters.len(), 1);
1025
1026 match &filters[0].op_expr.operation {
1027 Operation::Is(postrust_core::api_request::IsValue::False) => {}
1028 _ => panic!("Expected Is False operation"),
1029 }
1030 }
1031
1032 #[test]
1033 fn test_boolean_filter_is_empty() {
1034 let filter = BooleanFilterInput::default();
1035 assert!(filter.is_empty());
1036
1037 let filter = BooleanFilterInput {
1038 eq: Some(true),
1039 ..Default::default()
1040 };
1041 assert!(!filter.is_empty());
1042 }
1043
1044 #[test]
1049 fn test_float_filter_eq() {
1050 let filter = FloatFilterInput {
1051 eq: Some(1.5),
1052 ..Default::default()
1053 };
1054
1055 let filters = filter.to_filters("price");
1056 assert_eq!(filters.len(), 1);
1057
1058 match &filters[0].op_expr.operation {
1059 Operation::Quant { op, value, .. } => {
1060 assert_eq!(*op, QuantOperator::Equal);
1061 assert_eq!(value, "1.5");
1062 }
1063 _ => panic!("Expected Quant operation"),
1064 }
1065 }
1066
1067 #[test]
1068 fn test_float_filter_gt() {
1069 let filter = FloatFilterInput {
1070 gt: Some(100.0),
1071 ..Default::default()
1072 };
1073
1074 let filters = filter.to_filters("price");
1075 assert_eq!(filters.len(), 1);
1076
1077 match &filters[0].op_expr.operation {
1078 Operation::Quant { op, value, .. } => {
1079 assert_eq!(*op, QuantOperator::GreaterThan);
1080 assert_eq!(value, "100");
1081 }
1082 _ => panic!("Expected Quant operation"),
1083 }
1084 }
1085
1086 #[test]
1087 fn test_float_filter_is_empty() {
1088 let filter = FloatFilterInput::default();
1089 assert!(filter.is_empty());
1090 }
1091
1092 #[test]
1097 fn test_uuid_filter_eq() {
1098 let filter = UuidFilterInput {
1099 eq: Some("550e8400-e29b-41d4-a716-446655440000".to_string()),
1100 ..Default::default()
1101 };
1102
1103 let filters = filter.to_filters("id");
1104 assert_eq!(filters.len(), 1);
1105
1106 match &filters[0].op_expr.operation {
1107 Operation::Quant { op, value, .. } => {
1108 assert_eq!(*op, QuantOperator::Equal);
1109 assert_eq!(value, "550e8400-e29b-41d4-a716-446655440000");
1110 }
1111 _ => panic!("Expected Quant operation"),
1112 }
1113 }
1114
1115 #[test]
1116 fn test_uuid_filter_in() {
1117 let filter = UuidFilterInput {
1118 in_list: Some(vec![
1119 "550e8400-e29b-41d4-a716-446655440000".to_string(),
1120 "550e8400-e29b-41d4-a716-446655440001".to_string(),
1121 ]),
1122 ..Default::default()
1123 };
1124
1125 let filters = filter.to_filters("id");
1126 assert_eq!(filters.len(), 1);
1127
1128 match &filters[0].op_expr.operation {
1129 Operation::In(values) => {
1130 assert_eq!(values.len(), 2);
1131 }
1132 _ => panic!("Expected In operation"),
1133 }
1134 }
1135
1136 #[test]
1137 fn test_uuid_filter_is_empty() {
1138 let filter = UuidFilterInput::default();
1139 assert!(filter.is_empty());
1140 }
1141
1142 #[test]
1147 fn test_filters_to_logic_tree_empty() {
1148 let tree = filters_to_logic_tree(vec![]);
1149 assert!(tree.is_none());
1150 }
1151
1152 #[test]
1153 fn test_filters_to_logic_tree_single() {
1154 let filter = Filter::new(
1155 Field::simple("name"),
1156 OpExpr::new(Operation::Quant {
1157 op: QuantOperator::Equal,
1158 quantifier: None,
1159 value: "test".to_string(),
1160 }),
1161 );
1162
1163 let tree = filters_to_logic_tree(vec![filter]).unwrap();
1164 match tree {
1165 LogicTree::Stmt(_) => {}
1166 _ => panic!("Expected Stmt for single filter"),
1167 }
1168 }
1169
1170 #[test]
1171 fn test_filters_to_logic_tree_multiple() {
1172 let filter1 = Filter::new(
1173 Field::simple("name"),
1174 OpExpr::new(Operation::Quant {
1175 op: QuantOperator::Equal,
1176 quantifier: None,
1177 value: "test".to_string(),
1178 }),
1179 );
1180 let filter2 = Filter::new(
1181 Field::simple("age"),
1182 OpExpr::new(Operation::Quant {
1183 op: QuantOperator::GreaterThan,
1184 quantifier: None,
1185 value: "18".to_string(),
1186 }),
1187 );
1188
1189 let tree = filters_to_logic_tree(vec![filter1, filter2]).unwrap();
1190 match tree {
1191 LogicTree::Expr { op, children, .. } => {
1192 assert_eq!(op, LogicOperator::And);
1193 assert_eq!(children.len(), 2);
1194 }
1195 _ => panic!("Expected Expr for multiple filters"),
1196 }
1197 }
1198
1199 #[test]
1200 fn test_combine_with_and() {
1201 let filter1 = Filter::new(
1202 Field::simple("a"),
1203 OpExpr::new(Operation::Quant {
1204 op: QuantOperator::Equal,
1205 quantifier: None,
1206 value: "1".to_string(),
1207 }),
1208 );
1209 let filter2 = Filter::new(
1210 Field::simple("b"),
1211 OpExpr::new(Operation::Quant {
1212 op: QuantOperator::Equal,
1213 quantifier: None,
1214 value: "2".to_string(),
1215 }),
1216 );
1217
1218 let tree1 = LogicTree::Stmt(filter1);
1219 let tree2 = LogicTree::Stmt(filter2);
1220
1221 let combined = combine_with_and(vec![tree1, tree2]).unwrap();
1222 match combined {
1223 LogicTree::Expr { op, children, .. } => {
1224 assert_eq!(op, LogicOperator::And);
1225 assert_eq!(children.len(), 2);
1226 }
1227 _ => panic!("Expected Expr"),
1228 }
1229 }
1230
1231 #[test]
1232 fn test_combine_with_or() {
1233 let filter1 = Filter::new(
1234 Field::simple("a"),
1235 OpExpr::new(Operation::Quant {
1236 op: QuantOperator::Equal,
1237 quantifier: None,
1238 value: "1".to_string(),
1239 }),
1240 );
1241 let filter2 = Filter::new(
1242 Field::simple("b"),
1243 OpExpr::new(Operation::Quant {
1244 op: QuantOperator::Equal,
1245 quantifier: None,
1246 value: "2".to_string(),
1247 }),
1248 );
1249
1250 let tree1 = LogicTree::Stmt(filter1);
1251 let tree2 = LogicTree::Stmt(filter2);
1252
1253 let combined = combine_with_or(vec![tree1, tree2]).unwrap();
1254 match combined {
1255 LogicTree::Expr { op, children, .. } => {
1256 assert_eq!(op, LogicOperator::Or);
1257 assert_eq!(children.len(), 2);
1258 }
1259 _ => panic!("Expected Expr"),
1260 }
1261 }
1262
1263 #[test]
1264 fn test_negate_tree_stmt() {
1265 let filter = Filter::new(
1266 Field::simple("a"),
1267 OpExpr::new(Operation::Quant {
1268 op: QuantOperator::Equal,
1269 quantifier: None,
1270 value: "1".to_string(),
1271 }),
1272 );
1273
1274 let tree = LogicTree::Stmt(filter);
1275 let negated = negate_tree(tree);
1276
1277 match negated {
1278 LogicTree::Stmt(f) => {
1279 assert!(f.op_expr.negated);
1280 }
1281 _ => panic!("Expected Stmt"),
1282 }
1283 }
1284
1285 #[test]
1286 fn test_negate_tree_expr() {
1287 let filter = Filter::new(
1288 Field::simple("a"),
1289 OpExpr::new(Operation::Quant {
1290 op: QuantOperator::Equal,
1291 quantifier: None,
1292 value: "1".to_string(),
1293 }),
1294 );
1295
1296 let tree = LogicTree::Expr {
1297 negated: false,
1298 op: LogicOperator::And,
1299 children: vec![LogicTree::Stmt(filter)],
1300 };
1301
1302 let negated = negate_tree(tree);
1303
1304 match negated {
1305 LogicTree::Expr { negated, .. } => {
1306 assert!(negated);
1307 }
1308 _ => panic!("Expected Expr"),
1309 }
1310 }
1311}