1use std::{collections::HashMap, sync::LazyLock};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11#[non_exhaustive]
12pub enum OperatorCategory {
13 Comparison,
15 String,
17 Null,
19 Array,
21 Vector,
23 Fulltext,
25 Containment,
27 Network,
29 DateRange,
31 Ltree,
33 Spatial,
35 Path,
37}
38
39#[derive(Debug, Clone)]
41pub struct OperatorInfo {
42 pub name: &'static str,
44 pub sql_op: &'static str,
46 pub category: OperatorCategory,
48 pub requires_array: bool,
50 pub jsonb_operator: bool,
52}
53
54pub static OPERATOR_REGISTRY: LazyLock<HashMap<&'static str, OperatorInfo>> = LazyLock::new(|| {
56 let mut m = HashMap::new();
57
58 m.insert(
60 "eq",
61 OperatorInfo {
62 name: "eq",
63 sql_op: "=",
64 category: OperatorCategory::Comparison,
65 requires_array: false,
66 jsonb_operator: false,
67 },
68 );
69
70 m.insert(
71 "ne",
72 OperatorInfo {
73 name: "ne",
74 sql_op: "!=",
75 category: OperatorCategory::Comparison,
76 requires_array: false,
77 jsonb_operator: false,
78 },
79 );
80
81 m.insert(
82 "gt",
83 OperatorInfo {
84 name: "gt",
85 sql_op: ">",
86 category: OperatorCategory::Comparison,
87 requires_array: false,
88 jsonb_operator: false,
89 },
90 );
91
92 m.insert(
93 "gte",
94 OperatorInfo {
95 name: "gte",
96 sql_op: ">=",
97 category: OperatorCategory::Comparison,
98 requires_array: false,
99 jsonb_operator: false,
100 },
101 );
102
103 m.insert(
104 "lt",
105 OperatorInfo {
106 name: "lt",
107 sql_op: "<",
108 category: OperatorCategory::Comparison,
109 requires_array: false,
110 jsonb_operator: false,
111 },
112 );
113
114 m.insert(
115 "lte",
116 OperatorInfo {
117 name: "lte",
118 sql_op: "<=",
119 category: OperatorCategory::Comparison,
120 requires_array: false,
121 jsonb_operator: false,
122 },
123 );
124
125 m.insert(
126 "in",
127 OperatorInfo {
128 name: "in",
129 sql_op: "IN",
130 category: OperatorCategory::Comparison,
131 requires_array: true,
132 jsonb_operator: false,
133 },
134 );
135
136 m.insert(
137 "nin",
138 OperatorInfo {
139 name: "nin",
140 sql_op: "NOT IN",
141 category: OperatorCategory::Comparison,
142 requires_array: true,
143 jsonb_operator: false,
144 },
145 );
146
147 m.insert(
149 "like",
150 OperatorInfo {
151 name: "like",
152 sql_op: "LIKE",
153 category: OperatorCategory::String,
154 requires_array: false,
155 jsonb_operator: false,
156 },
157 );
158
159 m.insert(
160 "ilike",
161 OperatorInfo {
162 name: "ilike",
163 sql_op: "ILIKE",
164 category: OperatorCategory::String,
165 requires_array: false,
166 jsonb_operator: false,
167 },
168 );
169
170 m.insert(
171 "nlike",
172 OperatorInfo {
173 name: "nlike",
174 sql_op: "NOT LIKE",
175 category: OperatorCategory::String,
176 requires_array: false,
177 jsonb_operator: false,
178 },
179 );
180
181 m.insert(
182 "nilike",
183 OperatorInfo {
184 name: "nilike",
185 sql_op: "NOT ILIKE",
186 category: OperatorCategory::String,
187 requires_array: false,
188 jsonb_operator: false,
189 },
190 );
191
192 m.insert(
193 "regex",
194 OperatorInfo {
195 name: "regex",
196 sql_op: "~",
197 category: OperatorCategory::String,
198 requires_array: false,
199 jsonb_operator: false,
200 },
201 );
202
203 m.insert(
204 "iregex",
205 OperatorInfo {
206 name: "iregex",
207 sql_op: "~*",
208 category: OperatorCategory::String,
209 requires_array: false,
210 jsonb_operator: false,
211 },
212 );
213
214 m.insert(
215 "nregex",
216 OperatorInfo {
217 name: "nregex",
218 sql_op: "!~",
219 category: OperatorCategory::String,
220 requires_array: false,
221 jsonb_operator: false,
222 },
223 );
224
225 m.insert(
226 "niregex",
227 OperatorInfo {
228 name: "niregex",
229 sql_op: "!~*",
230 category: OperatorCategory::String,
231 requires_array: false,
232 jsonb_operator: false,
233 },
234 );
235
236 m.insert(
238 "is_null",
239 OperatorInfo {
240 name: "is_null",
241 sql_op: "IS NULL",
242 category: OperatorCategory::Null,
243 requires_array: false,
244 jsonb_operator: false,
245 },
246 );
247
248 m.insert(
249 "is_not_null",
250 OperatorInfo {
251 name: "is_not_null",
252 sql_op: "IS NOT NULL",
253 category: OperatorCategory::Null,
254 requires_array: false,
255 jsonb_operator: false,
256 },
257 );
258
259 m.insert(
261 "contains",
262 OperatorInfo {
263 name: "contains",
264 sql_op: "@>",
265 category: OperatorCategory::Containment,
266 requires_array: false,
267 jsonb_operator: true,
268 },
269 );
270
271 m.insert(
272 "contained_in",
273 OperatorInfo {
274 name: "contained_in",
275 sql_op: "<@",
276 category: OperatorCategory::Containment,
277 requires_array: false,
278 jsonb_operator: true,
279 },
280 );
281
282 m.insert(
283 "has_key",
284 OperatorInfo {
285 name: "has_key",
286 sql_op: "?",
287 category: OperatorCategory::Containment,
288 requires_array: false,
289 jsonb_operator: true,
290 },
291 );
292
293 m.insert(
294 "has_any_keys",
295 OperatorInfo {
296 name: "has_any_keys",
297 sql_op: "?|",
298 category: OperatorCategory::Containment,
299 requires_array: true,
300 jsonb_operator: true,
301 },
302 );
303
304 m.insert(
305 "has_all_keys",
306 OperatorInfo {
307 name: "has_all_keys",
308 sql_op: "?&",
309 category: OperatorCategory::Containment,
310 requires_array: true,
311 jsonb_operator: true,
312 },
313 );
314
315 m.insert(
317 "array_contains",
318 OperatorInfo {
319 name: "array_contains",
320 sql_op: "@>",
321 category: OperatorCategory::Array,
322 requires_array: false,
323 jsonb_operator: false,
324 },
325 );
326
327 m.insert(
328 "array_contained_in",
329 OperatorInfo {
330 name: "array_contained_in",
331 sql_op: "<@",
332 category: OperatorCategory::Array,
333 requires_array: false,
334 jsonb_operator: false,
335 },
336 );
337
338 m.insert(
339 "array_overlaps",
340 OperatorInfo {
341 name: "array_overlaps",
342 sql_op: "&&",
343 category: OperatorCategory::Array,
344 requires_array: false,
345 jsonb_operator: false,
346 },
347 );
348
349 m.insert(
351 "cosine_distance",
352 OperatorInfo {
353 name: "cosine_distance",
354 sql_op: "<=>",
355 category: OperatorCategory::Vector,
356 requires_array: false,
357 jsonb_operator: false,
358 },
359 );
360
361 m.insert(
362 "l2_distance",
363 OperatorInfo {
364 name: "l2_distance",
365 sql_op: "<->",
366 category: OperatorCategory::Vector,
367 requires_array: false,
368 jsonb_operator: false,
369 },
370 );
371
372 m.insert(
373 "inner_product",
374 OperatorInfo {
375 name: "inner_product",
376 sql_op: "<#>",
377 category: OperatorCategory::Vector,
378 requires_array: false,
379 jsonb_operator: false,
380 },
381 );
382
383 m.insert(
384 "l1_distance",
385 OperatorInfo {
386 name: "l1_distance",
387 sql_op: "<+>",
388 category: OperatorCategory::Vector,
389 requires_array: false,
390 jsonb_operator: false,
391 },
392 );
393
394 m.insert(
395 "hamming_distance",
396 OperatorInfo {
397 name: "hamming_distance",
398 sql_op: "<~>",
399 category: OperatorCategory::Vector,
400 requires_array: false,
401 jsonb_operator: false,
402 },
403 );
404
405 m.insert(
406 "jaccard_distance",
407 OperatorInfo {
408 name: "jaccard_distance",
409 sql_op: "<%>",
410 category: OperatorCategory::Vector,
411 requires_array: false,
412 jsonb_operator: false,
413 },
414 );
415
416 m.insert(
418 "search",
419 OperatorInfo {
420 name: "search",
421 sql_op: "@@",
422 category: OperatorCategory::Fulltext,
423 requires_array: false,
424 jsonb_operator: false,
425 },
426 );
427
428 m.insert(
429 "plainto_tsquery",
430 OperatorInfo {
431 name: "plainto_tsquery",
432 sql_op: "@@",
433 category: OperatorCategory::Fulltext,
434 requires_array: false,
435 jsonb_operator: false,
436 },
437 );
438
439 m.insert(
440 "phraseto_tsquery",
441 OperatorInfo {
442 name: "phraseto_tsquery",
443 sql_op: "@@",
444 category: OperatorCategory::Fulltext,
445 requires_array: false,
446 jsonb_operator: false,
447 },
448 );
449
450 m.insert(
451 "websearch_to_tsquery",
452 OperatorInfo {
453 name: "websearch_to_tsquery",
454 sql_op: "@@",
455 category: OperatorCategory::Fulltext,
456 requires_array: false,
457 jsonb_operator: false,
458 },
459 );
460
461 m.insert(
463 "startswith",
464 OperatorInfo {
465 name: "startswith",
466 sql_op: "LIKE",
467 category: OperatorCategory::String,
468 requires_array: false,
469 jsonb_operator: false,
470 },
471 );
472
473 m.insert(
474 "istartswith",
475 OperatorInfo {
476 name: "istartswith",
477 sql_op: "ILIKE",
478 category: OperatorCategory::String,
479 requires_array: false,
480 jsonb_operator: false,
481 },
482 );
483
484 m.insert(
485 "endswith",
486 OperatorInfo {
487 name: "endswith",
488 sql_op: "LIKE",
489 category: OperatorCategory::String,
490 requires_array: false,
491 jsonb_operator: false,
492 },
493 );
494
495 m.insert(
496 "iendswith",
497 OperatorInfo {
498 name: "iendswith",
499 sql_op: "ILIKE",
500 category: OperatorCategory::String,
501 requires_array: false,
502 jsonb_operator: false,
503 },
504 );
505
506 m.insert(
507 "icontains",
508 OperatorInfo {
509 name: "icontains",
510 sql_op: "ILIKE",
511 category: OperatorCategory::String,
512 requires_array: false,
513 jsonb_operator: false,
514 },
515 );
516
517 m.insert(
518 "imatches",
519 OperatorInfo {
520 name: "imatches",
521 sql_op: "~*",
522 category: OperatorCategory::String,
523 requires_array: false,
524 jsonb_operator: false,
525 },
526 );
527
528 m.insert(
529 "not_matches",
530 OperatorInfo {
531 name: "not_matches",
532 sql_op: "!~",
533 category: OperatorCategory::String,
534 requires_array: false,
535 jsonb_operator: false,
536 },
537 );
538
539 m.insert(
541 "isIPv4",
542 OperatorInfo {
543 name: "isIPv4",
544 sql_op: "family({}) = 4",
545 category: OperatorCategory::Network,
546 requires_array: false,
547 jsonb_operator: false,
548 },
549 );
550
551 m.insert(
552 "isIPv6",
553 OperatorInfo {
554 name: "isIPv6",
555 sql_op: "family({}) = 6",
556 category: OperatorCategory::Network,
557 requires_array: false,
558 jsonb_operator: false,
559 },
560 );
561
562 m.insert(
563 "isPrivate",
564 OperatorInfo {
565 name: "isPrivate",
566 sql_op: "CIDR_RANGE_CHECK",
567 category: OperatorCategory::Network,
568 requires_array: false,
569 jsonb_operator: false,
570 },
571 );
572
573 m.insert(
574 "isPublic",
575 OperatorInfo {
576 name: "isPublic",
577 sql_op: "NOT_CIDR_RANGE_CHECK",
578 category: OperatorCategory::Network,
579 requires_array: false,
580 jsonb_operator: false,
581 },
582 );
583
584 m.insert(
585 "inSubnet",
586 OperatorInfo {
587 name: "inSubnet",
588 sql_op: "{} <<= {}",
589 category: OperatorCategory::Network,
590 requires_array: false,
591 jsonb_operator: false,
592 },
593 );
594
595 m.insert(
596 "notInSubnet",
597 OperatorInfo {
598 name: "notInSubnet",
599 sql_op: "NOT ({} <<= {})",
600 category: OperatorCategory::Network,
601 requires_array: false,
602 jsonb_operator: false,
603 },
604 );
605
606 m.insert(
607 "subnet_contains",
608 OperatorInfo {
609 name: "subnet_contains",
610 sql_op: ">>",
611 category: OperatorCategory::Network,
612 requires_array: false,
613 jsonb_operator: false,
614 },
615 );
616
617 m.insert(
618 "subnet_overlaps",
619 OperatorInfo {
620 name: "subnet_overlaps",
621 sql_op: "&&",
622 category: OperatorCategory::Network,
623 requires_array: false,
624 jsonb_operator: false,
625 },
626 );
627
628 m.insert(
630 "contains_date",
631 OperatorInfo {
632 name: "contains_date",
633 sql_op: "@>",
634 category: OperatorCategory::DateRange,
635 requires_array: false,
636 jsonb_operator: false,
637 },
638 );
639
640 m.insert(
641 "adjacent",
642 OperatorInfo {
643 name: "adjacent",
644 sql_op: "-|-",
645 category: OperatorCategory::DateRange,
646 requires_array: false,
647 jsonb_operator: false,
648 },
649 );
650
651 m.insert(
652 "strictly_left",
653 OperatorInfo {
654 name: "strictly_left",
655 sql_op: "<<",
656 category: OperatorCategory::DateRange,
657 requires_array: false,
658 jsonb_operator: false,
659 },
660 );
661
662 m.insert(
663 "strictly_right",
664 OperatorInfo {
665 name: "strictly_right",
666 sql_op: ">>",
667 category: OperatorCategory::DateRange,
668 requires_array: false,
669 jsonb_operator: false,
670 },
671 );
672
673 m.insert(
674 "not_left",
675 OperatorInfo {
676 name: "not_left",
677 sql_op: "&>",
678 category: OperatorCategory::DateRange,
679 requires_array: false,
680 jsonb_operator: false,
681 },
682 );
683
684 m.insert(
685 "not_right",
686 OperatorInfo {
687 name: "not_right",
688 sql_op: "&<",
689 category: OperatorCategory::DateRange,
690 requires_array: false,
691 jsonb_operator: false,
692 },
693 );
694
695 m.insert(
696 "overlaps",
697 OperatorInfo {
698 name: "overlaps",
699 sql_op: "&&",
700 category: OperatorCategory::DateRange,
701 requires_array: false,
702 jsonb_operator: false,
703 },
704 );
705
706 m.insert(
708 "ancestor_of",
709 OperatorInfo {
710 name: "ancestor_of",
711 sql_op: "@>",
712 category: OperatorCategory::Ltree,
713 requires_array: false,
714 jsonb_operator: false,
715 },
716 );
717
718 m.insert(
719 "descendant_of",
720 OperatorInfo {
721 name: "descendant_of",
722 sql_op: "<@",
723 category: OperatorCategory::Ltree,
724 requires_array: false,
725 jsonb_operator: false,
726 },
727 );
728
729 m.insert(
730 "matches_lquery",
731 OperatorInfo {
732 name: "matches_lquery",
733 sql_op: "~",
734 category: OperatorCategory::Ltree,
735 requires_array: false,
736 jsonb_operator: false,
737 },
738 );
739
740 m.insert(
741 "matches_ltxtquery",
742 OperatorInfo {
743 name: "matches_ltxtquery",
744 sql_op: "@",
745 category: OperatorCategory::Ltree,
746 requires_array: false,
747 jsonb_operator: false,
748 },
749 );
750
751 m.insert(
752 "matches_any_lquery",
753 OperatorInfo {
754 name: "matches_any_lquery",
755 sql_op: "?",
756 category: OperatorCategory::Ltree,
757 requires_array: true,
758 jsonb_operator: false,
759 },
760 );
761
762 m.insert(
764 "depth_eq",
765 OperatorInfo {
766 name: "depth_eq",
767 sql_op: "nlevel({}) =",
768 category: OperatorCategory::Path,
769 requires_array: false,
770 jsonb_operator: false,
771 },
772 );
773
774 m.insert(
775 "depth_gt",
776 OperatorInfo {
777 name: "depth_gt",
778 sql_op: "nlevel({}) >",
779 category: OperatorCategory::Path,
780 requires_array: false,
781 jsonb_operator: false,
782 },
783 );
784
785 m.insert(
786 "depth_lt",
787 OperatorInfo {
788 name: "depth_lt",
789 sql_op: "nlevel({}) <",
790 category: OperatorCategory::Path,
791 requires_array: false,
792 jsonb_operator: false,
793 },
794 );
795
796 m.insert(
797 "isdescendant",
798 OperatorInfo {
799 name: "isdescendant",
800 sql_op: "<@",
801 category: OperatorCategory::Path,
802 requires_array: false,
803 jsonb_operator: false,
804 },
805 );
806
807 m.insert(
809 "distance_within",
810 OperatorInfo {
811 name: "distance_within",
812 sql_op: "distance_within",
813 category: OperatorCategory::Spatial,
814 requires_array: false,
815 jsonb_operator: false,
816 },
817 );
818
819 m.insert(
821 "strictly_contains",
822 OperatorInfo {
823 name: "strictly_contains",
824 sql_op: "@>",
825 category: OperatorCategory::Containment,
826 requires_array: false,
827 jsonb_operator: true,
828 },
829 );
830
831 m.insert(
833 "neq",
834 OperatorInfo {
835 name: "neq",
836 sql_op: "!=",
837 category: OperatorCategory::Comparison,
838 requires_array: false,
839 jsonb_operator: false,
840 },
841 );
842
843 m.insert(
844 "isnull",
845 OperatorInfo {
846 name: "isnull",
847 sql_op: "IS NULL",
848 category: OperatorCategory::Null,
849 requires_array: false,
850 jsonb_operator: false,
851 },
852 );
853
854 m.insert(
855 "array_eq",
856 OperatorInfo {
857 name: "array_eq",
858 sql_op: "=",
859 category: OperatorCategory::Array,
860 requires_array: false,
861 jsonb_operator: false,
862 },
863 );
864
865 m.insert(
866 "array_neq",
867 OperatorInfo {
868 name: "array_neq",
869 sql_op: "!=",
870 category: OperatorCategory::Array,
871 requires_array: false,
872 jsonb_operator: false,
873 },
874 );
875
876 m.insert(
877 "array_contained_by",
878 OperatorInfo {
879 name: "array_contained_by",
880 sql_op: "<@",
881 category: OperatorCategory::Array,
882 requires_array: false,
883 jsonb_operator: false,
884 },
885 );
886
887 m.insert(
888 "notin",
889 OperatorInfo {
890 name: "notin",
891 sql_op: "NOT IN",
892 category: OperatorCategory::Comparison,
893 requires_array: true,
894 jsonb_operator: false,
895 },
896 );
897
898 m
899});
900
901#[must_use]
911pub fn get_operator_info(name: &str) -> Option<&'static OperatorInfo> {
912 OPERATOR_REGISTRY.get(name)
913}
914
915#[must_use]
926pub fn is_operator(name: &str) -> bool {
927 OPERATOR_REGISTRY.contains_key(name)
928}
929
930#[must_use]
940pub fn get_operators_by_category(category: OperatorCategory) -> Vec<&'static OperatorInfo> {
941 OPERATOR_REGISTRY.values().filter(|op| op.category == category).collect()
942}
943
944#[cfg(test)]
945mod tests {
946 #![allow(clippy::unwrap_used)] use super::*;
949
950 #[test]
951 fn test_operator_registry_initialized() {
952 assert!(OPERATOR_REGISTRY.len() >= 40);
954 }
955
956 #[test]
957 fn test_comparison_operators() {
958 let operators = ["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"];
959
960 for op_name in &operators {
961 let op = get_operator_info(op_name);
962 assert!(op.is_some(), "Operator {op_name} should exist");
963
964 let op = op.unwrap();
965 assert_eq!(op.category, OperatorCategory::Comparison);
966 assert!(!op.jsonb_operator);
967 }
968 }
969
970 #[test]
971 fn test_string_operators() {
972 let operators = [
973 "like", "ilike", "nlike", "nilike", "regex", "iregex", "nregex", "niregex",
974 ];
975
976 for op_name in &operators {
977 let op = get_operator_info(op_name);
978 assert!(op.is_some(), "String operator {op_name} should exist");
979
980 let op = op.unwrap();
981 assert_eq!(op.category, OperatorCategory::String);
982 }
983 }
984
985 #[test]
986 fn test_null_operators() {
987 let op1 = get_operator_info("is_null").unwrap();
988 assert_eq!(op1.sql_op, "IS NULL");
989 assert_eq!(op1.category, OperatorCategory::Null);
990
991 let op2 = get_operator_info("is_not_null").unwrap();
992 assert_eq!(op2.sql_op, "IS NOT NULL");
993 assert_eq!(op2.category, OperatorCategory::Null);
994 }
995
996 #[test]
997 fn test_containment_operators() {
998 let operators = [
999 "contains",
1000 "contained_in",
1001 "has_key",
1002 "has_any_keys",
1003 "has_all_keys",
1004 ];
1005
1006 for op_name in &operators {
1007 let op = get_operator_info(op_name);
1008 assert!(op.is_some(), "Containment operator {op_name} should exist");
1009
1010 let op = op.unwrap();
1011 assert_eq!(op.category, OperatorCategory::Containment);
1012 assert!(op.jsonb_operator, "{op_name} should be JSONB operator");
1013 }
1014 }
1015
1016 #[test]
1017 fn test_array_operators() {
1018 let operators = ["array_contains", "array_contained_in", "array_overlaps"];
1019
1020 for op_name in &operators {
1021 let op = get_operator_info(op_name);
1022 assert!(op.is_some(), "Array operator {op_name} should exist");
1023
1024 let op = op.unwrap();
1025 assert_eq!(op.category, OperatorCategory::Array);
1026 }
1027 }
1028
1029 #[test]
1030 fn test_vector_operators() {
1031 let operators = [
1032 ("cosine_distance", "<=>"),
1033 ("l2_distance", "<->"),
1034 ("inner_product", "<#>"),
1035 ("l1_distance", "<+>"),
1036 ("hamming_distance", "<~>"),
1037 ("jaccard_distance", "<%>"),
1038 ];
1039
1040 for (op_name, expected_sql) in &operators {
1041 let op = get_operator_info(op_name);
1042 assert!(op.is_some(), "Vector operator {op_name} should exist");
1043
1044 let op = op.unwrap();
1045 assert_eq!(op.category, OperatorCategory::Vector);
1046 assert_eq!(op.sql_op, *expected_sql);
1047 }
1048 }
1049
1050 #[test]
1051 fn test_fulltext_operators() {
1052 let operators = [
1053 "search",
1054 "plainto_tsquery",
1055 "phraseto_tsquery",
1056 "websearch_to_tsquery",
1057 ];
1058
1059 for op_name in &operators {
1060 let op = get_operator_info(op_name);
1061 assert!(op.is_some(), "Fulltext operator {op_name} should exist");
1062
1063 let op = op.unwrap();
1064 assert_eq!(op.category, OperatorCategory::Fulltext);
1065 assert_eq!(op.sql_op, "@@");
1066 }
1067 }
1068
1069 #[test]
1070 fn test_is_operator() {
1071 assert!(is_operator("eq"));
1072 assert!(is_operator("contains"));
1073 assert!(is_operator("cosine_distance"));
1074 assert!(!is_operator("invalid_operator"));
1075 assert!(!is_operator(""));
1076 }
1077
1078 #[test]
1079 fn test_get_operators_by_category() {
1080 let comparison_ops = get_operators_by_category(OperatorCategory::Comparison);
1081 assert!(comparison_ops.len() >= 8);
1082
1083 let vector_ops = get_operators_by_category(OperatorCategory::Vector);
1084 assert!(vector_ops.len() >= 6);
1085
1086 let fulltext_ops = get_operators_by_category(OperatorCategory::Fulltext);
1087 assert!(fulltext_ops.len() >= 4);
1088 }
1089
1090 #[test]
1091 fn test_requires_array_flag() {
1092 assert!(get_operator_info("in").unwrap().requires_array);
1094 assert!(get_operator_info("nin").unwrap().requires_array);
1095
1096 assert!(!get_operator_info("eq").unwrap().requires_array);
1098 assert!(!get_operator_info("like").unwrap().requires_array);
1099 }
1100
1101 #[test]
1102 fn test_jsonb_operator_flag() {
1103 assert!(get_operator_info("contains").unwrap().jsonb_operator);
1105 assert!(get_operator_info("has_key").unwrap().jsonb_operator);
1106
1107 assert!(!get_operator_info("eq").unwrap().jsonb_operator);
1109 assert!(!get_operator_info("like").unwrap().jsonb_operator);
1110 }
1111}