Skip to main content

graphrecords_python/graphrecord/querying/
values.rs

1use crate::graphrecord::{errors::PyGraphRecordError, value::PyGraphRecordValue};
2use graphrecords_core::{
3    errors::GraphRecordError,
4    graphrecord::{
5        GraphRecordValue,
6        querying::{
7            DeepClone,
8            edges::EdgeOperand,
9            group_by::GroupOperand,
10            nodes::NodeOperand,
11            values::{
12                MultipleValuesComparisonOperand, MultipleValuesWithIndexOperand,
13                MultipleValuesWithoutIndexOperand, SingleValueComparisonOperand,
14                SingleValueWithIndexOperand, SingleValueWithoutIndexOperand,
15            },
16            wrapper::Wrapper,
17        },
18    },
19};
20use pyo3::{
21    Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, pyclass, pymethods,
22    types::{PyAnyMethods, PyFunction},
23};
24use std::ops::Deref;
25
26#[repr(transparent)]
27pub struct PySingleValueComparisonOperand(SingleValueComparisonOperand);
28
29impl From<SingleValueComparisonOperand> for PySingleValueComparisonOperand {
30    fn from(operand: SingleValueComparisonOperand) -> Self {
31        Self(operand)
32    }
33}
34
35impl From<PySingleValueComparisonOperand> for SingleValueComparisonOperand {
36    fn from(operand: PySingleValueComparisonOperand) -> Self {
37        operand.0
38    }
39}
40
41impl FromPyObject<'_, '_> for PySingleValueComparisonOperand {
42    type Error = PyErr;
43
44    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
45        match ob.extract::<PyGraphRecordValue>() {
46            Ok(value) => Ok(SingleValueComparisonOperand::Value(value.into()).into()),
47            _ => match ob.extract::<PyNodeSingleValueWithIndexOperand>() {
48                Ok(operand) => Ok(Self(operand.0.into())),
49                _ => match ob.extract::<PyNodeSingleValueWithoutIndexOperand>() {
50                    Ok(operand) => Ok(Self(operand.0.into())),
51                    _ => match ob.extract::<PyEdgeSingleValueWithIndexOperand>() {
52                        Ok(operand) => Ok(Self(operand.0.into())),
53                        _ => match ob.extract::<PyEdgeSingleValueWithoutIndexOperand>() {
54                            Ok(operand) => Ok(Self(operand.0.into())),
55                            _ => Err(PyGraphRecordError::from(GraphRecordError::ConversionError(
56                                format!(
57                    "Failed to convert {} into GraphRecordValue or SingleValueOperand",
58                    ob.to_owned()
59                ),
60                            ))
61                            .into()),
62                        },
63                    },
64                },
65            },
66        }
67    }
68}
69
70#[repr(transparent)]
71pub struct PyMultipleValuesComparisonOperand(MultipleValuesComparisonOperand);
72
73impl From<MultipleValuesComparisonOperand> for PyMultipleValuesComparisonOperand {
74    fn from(operand: MultipleValuesComparisonOperand) -> Self {
75        Self(operand)
76    }
77}
78
79impl From<PyMultipleValuesComparisonOperand> for MultipleValuesComparisonOperand {
80    fn from(operand: PyMultipleValuesComparisonOperand) -> Self {
81        operand.0
82    }
83}
84
85impl FromPyObject<'_, '_> for PyMultipleValuesComparisonOperand {
86    type Error = PyErr;
87
88    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
89        match ob.extract::<Vec<PyGraphRecordValue>>() {
90            Ok(values) => Ok(MultipleValuesComparisonOperand::Values(
91                values.into_iter().map(GraphRecordValue::from).collect(),
92            )
93            .into()),
94            _ => match ob.extract::<PyNodeMultipleValuesWithIndexOperand>() {
95                Ok(operand) => Ok(Self(operand.0.into())),
96                _ => match ob.extract::<PyNodeMultipleValuesWithoutIndexOperand>() {
97                    Ok(operand) => Ok(Self(operand.0.into())),
98                    _ => match ob.extract::<PyEdgeMultipleValuesWithIndexOperand>() {
99                        Ok(operand) => Ok(Self(operand.0.into())),
100                        _ => match ob.extract::<PyEdgeMultipleValuesWithoutIndexOperand>() {
101                            Ok(operand) => Ok(Self(operand.0.into())),
102                            _ => Err(PyGraphRecordError::from(GraphRecordError::ConversionError(
103                                format!(
104                    "Failed to convert {} into List[GraphRecordValue] or MultipleValuesOperand",
105                    ob.to_owned()
106                ),
107                            ))
108                            .into()),
109                        },
110                    },
111                },
112            },
113        }
114    }
115}
116
117macro_rules! implement_multiple_values_operand {
118    ($name:ident, $kind:ident, $generic:ty, $py_single_value_with_index_operand:ty, $py_single_value_without_index_operand:ty) => {
119        #[pyclass(frozen)]
120        #[repr(transparent)]
121        #[derive(Clone)]
122        pub struct $name(Wrapper<$kind<$generic>>);
123
124        impl From<Wrapper<$kind<$generic>>> for $name {
125            fn from(operand: Wrapper<$kind<$generic>>) -> Self {
126                Self(operand)
127            }
128        }
129
130        impl From<$name> for Wrapper<$kind<$generic>> {
131            fn from(operand: $name) -> Self {
132                operand.0
133            }
134        }
135
136        impl Deref for $name {
137            type Target = Wrapper<$kind<$generic>>;
138
139            fn deref(&self) -> &Self::Target {
140                &self.0
141            }
142        }
143
144        #[pymethods]
145        impl $name {
146            pub fn max(&self) -> $py_single_value_with_index_operand {
147                self.0.max().into()
148            }
149
150            pub fn min(&self) -> $py_single_value_with_index_operand {
151                self.0.min().into()
152            }
153
154            pub fn mean(&self) -> $py_single_value_without_index_operand {
155                self.0.mean().into()
156            }
157
158            pub fn median(&self) -> $py_single_value_without_index_operand {
159                self.0.median().into()
160            }
161
162            pub fn mode(&self) -> $py_single_value_without_index_operand {
163                self.0.mode().into()
164            }
165
166            pub fn std(&self) -> $py_single_value_without_index_operand {
167                self.0.std().into()
168            }
169
170            pub fn var(&self) -> $py_single_value_without_index_operand {
171                self.0.var().into()
172            }
173
174            pub fn count(&self) -> $py_single_value_without_index_operand {
175                self.0.count().into()
176            }
177
178            pub fn sum(&self) -> $py_single_value_without_index_operand {
179                self.0.sum().into()
180            }
181
182            pub fn random(&self) -> $py_single_value_with_index_operand {
183                self.0.random().into()
184            }
185
186            pub fn greater_than(&self, value: PySingleValueComparisonOperand) {
187                self.0.greater_than(value);
188            }
189
190            pub fn greater_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
191                self.0.greater_than_or_equal_to(value);
192            }
193
194            pub fn less_than(&self, value: PySingleValueComparisonOperand) {
195                self.0.less_than(value);
196            }
197
198            pub fn less_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
199                self.0.less_than_or_equal_to(value);
200            }
201
202            pub fn equal_to(&self, value: PySingleValueComparisonOperand) {
203                self.0.equal_to(value);
204            }
205
206            pub fn not_equal_to(&self, value: PySingleValueComparisonOperand) {
207                self.0.not_equal_to(value);
208            }
209
210            pub fn starts_with(&self, value: PySingleValueComparisonOperand) {
211                self.0.starts_with(value);
212            }
213
214            pub fn ends_with(&self, value: PySingleValueComparisonOperand) {
215                self.0.ends_with(value);
216            }
217
218            pub fn contains(&self, value: PySingleValueComparisonOperand) {
219                self.0.contains(value);
220            }
221
222            pub fn is_in(&self, values: PyMultipleValuesComparisonOperand) {
223                self.0.is_in(values);
224            }
225
226            pub fn is_not_in(&self, values: PyMultipleValuesComparisonOperand) {
227                self.0.is_not_in(values);
228            }
229
230            pub fn add(&self, value: PySingleValueComparisonOperand) {
231                self.0.add(value);
232            }
233
234            pub fn sub(&self, value: PySingleValueComparisonOperand) {
235                self.0.sub(value);
236            }
237
238            pub fn mul(&self, value: PySingleValueComparisonOperand) {
239                self.0.mul(value);
240            }
241
242            pub fn div(&self, value: PySingleValueComparisonOperand) {
243                self.0.div(value);
244            }
245
246            pub fn pow(&self, value: PySingleValueComparisonOperand) {
247                self.0.pow(value);
248            }
249
250            pub fn r#mod(&self, value: PySingleValueComparisonOperand) {
251                self.0.r#mod(value);
252            }
253
254            pub fn round(&self) {
255                self.0.round();
256            }
257
258            pub fn ceil(&self) {
259                self.0.ceil();
260            }
261
262            pub fn floor(&self) {
263                self.0.floor();
264            }
265
266            pub fn abs(&self) {
267                self.0.abs();
268            }
269
270            pub fn sqrt(&self) {
271                self.0.sqrt();
272            }
273
274            pub fn trim(&self) {
275                self.0.trim();
276            }
277
278            pub fn trim_start(&self) {
279                self.0.trim_start();
280            }
281
282            pub fn trim_end(&self) {
283                self.0.trim_end();
284            }
285
286            pub fn lowercase(&self) {
287                self.0.lowercase();
288            }
289
290            pub fn uppercase(&self) {
291                self.0.uppercase();
292            }
293
294            pub fn slice(&self, start: usize, end: usize) {
295                self.0.slice(start, end);
296            }
297
298            pub fn is_string(&self) {
299                self.0.is_string();
300            }
301
302            pub fn is_int(&self) {
303                self.0.is_int();
304            }
305
306            pub fn is_float(&self) {
307                self.0.is_float();
308            }
309
310            pub fn is_bool(&self) {
311                self.0.is_bool();
312            }
313
314            pub fn is_datetime(&self) {
315                self.0.is_datetime();
316            }
317
318            pub fn is_duration(&self) {
319                self.0.is_duration();
320            }
321
322            pub fn is_null(&self) {
323                self.0.is_null();
324            }
325
326            pub fn is_max(&self) {
327                self.0.is_max();
328            }
329
330            pub fn is_min(&self) {
331                self.0.is_min();
332            }
333
334            pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
335                self.0.either_or(
336                    |operand| {
337                        either
338                            .call1(($name::from(operand.clone()),))
339                            .expect("Call must succeed");
340                    },
341                    |operand| {
342                        or.call1(($name::from(operand.clone()),))
343                            .expect("Call must succeed");
344                    },
345                );
346            }
347
348            pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
349                self.0.exclude(|operand| {
350                    query
351                        .call1(($name::from(operand.clone()),))
352                        .expect("Call must succeed");
353                });
354            }
355
356            pub fn deep_clone(&self) -> $name {
357                self.0.deep_clone().into()
358            }
359        }
360    };
361}
362
363implement_multiple_values_operand!(
364    PyNodeMultipleValuesWithIndexOperand,
365    MultipleValuesWithIndexOperand,
366    NodeOperand,
367    PyNodeSingleValueWithIndexOperand,
368    PyNodeSingleValueWithoutIndexOperand
369);
370implement_multiple_values_operand!(
371    PyNodeMultipleValuesWithoutIndexOperand,
372    MultipleValuesWithoutIndexOperand,
373    NodeOperand,
374    PyNodeSingleValueWithoutIndexOperand,
375    PyNodeSingleValueWithoutIndexOperand
376);
377implement_multiple_values_operand!(
378    PyEdgeMultipleValuesWithIndexOperand,
379    MultipleValuesWithIndexOperand,
380    EdgeOperand,
381    PyEdgeSingleValueWithIndexOperand,
382    PyEdgeSingleValueWithoutIndexOperand
383);
384implement_multiple_values_operand!(
385    PyEdgeMultipleValuesWithoutIndexOperand,
386    MultipleValuesWithoutIndexOperand,
387    EdgeOperand,
388    PyEdgeSingleValueWithoutIndexOperand,
389    PyEdgeSingleValueWithoutIndexOperand
390);
391
392macro_rules! implement_multiple_values_grouped_operand {
393    ($name:ident, $ungrouped_name:ident, $kind:ident, $generic:ty, $py_single_value_with_index_operand:ty, $py_single_value_without_index_operand:ty) => {
394        #[pyclass(frozen)]
395        #[repr(transparent)]
396        #[derive(Clone)]
397        pub struct $name(Wrapper<GroupOperand<$kind<$generic>>>);
398
399        impl From<Wrapper<GroupOperand<$kind<$generic>>>> for $name {
400            fn from(operand: Wrapper<GroupOperand<$kind<$generic>>>) -> Self {
401                Self(operand)
402            }
403        }
404
405        impl From<$name> for Wrapper<GroupOperand<$kind<$generic>>> {
406            fn from(operand: $name) -> Self {
407                operand.0
408            }
409        }
410
411        impl Deref for $name {
412            type Target = Wrapper<GroupOperand<$kind<$generic>>>;
413
414            fn deref(&self) -> &Self::Target {
415                &self.0
416            }
417        }
418
419        #[pymethods]
420        impl $name {
421            pub fn max(&self) -> $py_single_value_with_index_operand {
422                self.0.max().into()
423            }
424
425            pub fn min(&self) -> $py_single_value_with_index_operand {
426                self.0.min().into()
427            }
428
429            pub fn mean(&self) -> $py_single_value_without_index_operand {
430                self.0.mean().into()
431            }
432
433            pub fn median(&self) -> $py_single_value_without_index_operand {
434                self.0.median().into()
435            }
436
437            pub fn mode(&self) -> $py_single_value_without_index_operand {
438                self.0.mode().into()
439            }
440
441            pub fn std(&self) -> $py_single_value_without_index_operand {
442                self.0.std().into()
443            }
444
445            pub fn var(&self) -> $py_single_value_without_index_operand {
446                self.0.var().into()
447            }
448
449            pub fn count(&self) -> $py_single_value_without_index_operand {
450                self.0.count().into()
451            }
452
453            pub fn sum(&self) -> $py_single_value_without_index_operand {
454                self.0.sum().into()
455            }
456
457            pub fn random(&self) -> $py_single_value_with_index_operand {
458                self.0.random().into()
459            }
460
461            pub fn greater_than(&self, value: PySingleValueComparisonOperand) {
462                self.0.greater_than(value);
463            }
464
465            pub fn greater_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
466                self.0.greater_than_or_equal_to(value);
467            }
468
469            pub fn less_than(&self, value: PySingleValueComparisonOperand) {
470                self.0.less_than(value);
471            }
472
473            pub fn less_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
474                self.0.less_than_or_equal_to(value);
475            }
476
477            pub fn equal_to(&self, value: PySingleValueComparisonOperand) {
478                self.0.equal_to(value);
479            }
480
481            pub fn not_equal_to(&self, value: PySingleValueComparisonOperand) {
482                self.0.not_equal_to(value);
483            }
484
485            pub fn starts_with(&self, value: PySingleValueComparisonOperand) {
486                self.0.starts_with(value);
487            }
488
489            pub fn ends_with(&self, value: PySingleValueComparisonOperand) {
490                self.0.ends_with(value);
491            }
492
493            pub fn contains(&self, value: PySingleValueComparisonOperand) {
494                self.0.contains(value);
495            }
496
497            pub fn is_in(&self, values: PyMultipleValuesComparisonOperand) {
498                self.0.is_in(values);
499            }
500
501            pub fn is_not_in(&self, values: PyMultipleValuesComparisonOperand) {
502                self.0.is_not_in(values);
503            }
504
505            pub fn add(&self, value: PySingleValueComparisonOperand) {
506                self.0.add(value);
507            }
508
509            pub fn sub(&self, value: PySingleValueComparisonOperand) {
510                self.0.sub(value);
511            }
512
513            pub fn mul(&self, value: PySingleValueComparisonOperand) {
514                self.0.mul(value);
515            }
516
517            pub fn div(&self, value: PySingleValueComparisonOperand) {
518                self.0.div(value);
519            }
520
521            pub fn pow(&self, value: PySingleValueComparisonOperand) {
522                self.0.pow(value);
523            }
524
525            pub fn r#mod(&self, value: PySingleValueComparisonOperand) {
526                self.0.r#mod(value);
527            }
528
529            pub fn round(&self) {
530                self.0.round();
531            }
532
533            pub fn ceil(&self) {
534                self.0.ceil();
535            }
536
537            pub fn floor(&self) {
538                self.0.floor();
539            }
540
541            pub fn abs(&self) {
542                self.0.abs();
543            }
544
545            pub fn sqrt(&self) {
546                self.0.sqrt();
547            }
548
549            pub fn trim(&self) {
550                self.0.trim();
551            }
552
553            pub fn trim_start(&self) {
554                self.0.trim_start();
555            }
556
557            pub fn trim_end(&self) {
558                self.0.trim_end();
559            }
560
561            pub fn lowercase(&self) {
562                self.0.lowercase();
563            }
564
565            pub fn uppercase(&self) {
566                self.0.uppercase();
567            }
568
569            pub fn slice(&self, start: usize, end: usize) {
570                self.0.slice(start, end);
571            }
572
573            pub fn is_string(&self) {
574                self.0.is_string();
575            }
576
577            pub fn is_int(&self) {
578                self.0.is_int();
579            }
580
581            pub fn is_float(&self) {
582                self.0.is_float();
583            }
584
585            pub fn is_bool(&self) {
586                self.0.is_bool();
587            }
588
589            pub fn is_datetime(&self) {
590                self.0.is_datetime();
591            }
592
593            pub fn is_duration(&self) {
594                self.0.is_duration();
595            }
596
597            pub fn is_null(&self) {
598                self.0.is_null();
599            }
600
601            pub fn is_max(&self) {
602                self.0.is_max();
603            }
604
605            pub fn is_min(&self) {
606                self.0.is_min();
607            }
608
609            pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
610                self.0.either_or(
611                    |operand| {
612                        either
613                            .call1(($ungrouped_name::from(operand.clone()),))
614                            .expect("Call must succeed");
615                    },
616                    |operand| {
617                        or.call1(($ungrouped_name::from(operand.clone()),))
618                            .expect("Call must succeed");
619                    },
620                );
621            }
622
623            pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
624                self.0.exclude(|operand| {
625                    query
626                        .call1(($ungrouped_name::from(operand.clone()),))
627                        .expect("Call must succeed");
628                });
629            }
630
631            pub fn ungroup(&self) -> $ungrouped_name {
632                self.0.ungroup().into()
633            }
634
635            pub fn deep_clone(&self) -> $name {
636                self.0.deep_clone().into()
637            }
638        }
639    };
640}
641
642implement_multiple_values_grouped_operand!(
643    PyNodeMultipleValuesWithIndexGroupOperand,
644    PyNodeMultipleValuesWithIndexOperand,
645    MultipleValuesWithIndexOperand,
646    NodeOperand,
647    PyNodeSingleValueWithIndexGroupOperand,
648    PyNodeSingleValueWithoutIndexGroupOperand
649);
650implement_multiple_values_grouped_operand!(
651    PyEdgeMultipleValuesWithIndexGroupOperand,
652    PyEdgeMultipleValuesWithIndexOperand,
653    MultipleValuesWithIndexOperand,
654    EdgeOperand,
655    PyEdgeSingleValueWithIndexGroupOperand,
656    PyEdgeSingleValueWithoutIndexGroupOperand
657);
658
659macro_rules! implement_single_value_operand {
660    ($name:ident, $kind:ident, $generic:ty) => {
661        #[pyclass(frozen)]
662        #[repr(transparent)]
663        #[derive(Clone)]
664        pub struct $name(Wrapper<$kind<$generic>>);
665
666        impl From<Wrapper<$kind<$generic>>> for $name {
667            fn from(operand: Wrapper<$kind<$generic>>) -> Self {
668                Self(operand)
669            }
670        }
671
672        impl From<$name> for Wrapper<$kind<$generic>> {
673            fn from(operand: $name) -> Self {
674                operand.0
675            }
676        }
677
678        impl Deref for $name {
679            type Target = Wrapper<$kind<$generic>>;
680
681            fn deref(&self) -> &Self::Target {
682                &self.0
683            }
684        }
685
686        #[pymethods]
687        impl $name {
688            pub fn greater_than(&self, value: PySingleValueComparisonOperand) {
689                self.0.greater_than(value);
690            }
691
692            pub fn greater_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
693                self.0.greater_than_or_equal_to(value);
694            }
695
696            pub fn less_than(&self, value: PySingleValueComparisonOperand) {
697                self.0.less_than(value);
698            }
699
700            pub fn less_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
701                self.0.less_than_or_equal_to(value);
702            }
703
704            pub fn equal_to(&self, value: PySingleValueComparisonOperand) {
705                self.0.equal_to(value);
706            }
707
708            pub fn not_equal_to(&self, value: PySingleValueComparisonOperand) {
709                self.0.not_equal_to(value);
710            }
711
712            pub fn starts_with(&self, value: PySingleValueComparisonOperand) {
713                self.0.starts_with(value);
714            }
715
716            pub fn ends_with(&self, value: PySingleValueComparisonOperand) {
717                self.0.ends_with(value);
718            }
719
720            pub fn contains(&self, value: PySingleValueComparisonOperand) {
721                self.0.contains(value);
722            }
723
724            pub fn is_in(&self, values: PyMultipleValuesComparisonOperand) {
725                self.0.is_in(values);
726            }
727
728            pub fn is_not_in(&self, values: PyMultipleValuesComparisonOperand) {
729                self.0.is_not_in(values);
730            }
731
732            pub fn add(&self, value: PySingleValueComparisonOperand) {
733                self.0.add(value);
734            }
735
736            pub fn sub(&self, value: PySingleValueComparisonOperand) {
737                self.0.sub(value);
738            }
739
740            pub fn mul(&self, value: PySingleValueComparisonOperand) {
741                self.0.mul(value);
742            }
743
744            pub fn div(&self, value: PySingleValueComparisonOperand) {
745                self.0.div(value);
746            }
747
748            pub fn pow(&self, value: PySingleValueComparisonOperand) {
749                self.0.pow(value);
750            }
751
752            pub fn r#mod(&self, value: PySingleValueComparisonOperand) {
753                self.0.r#mod(value);
754            }
755
756            pub fn round(&self) {
757                self.0.round();
758            }
759
760            pub fn ceil(&self) {
761                self.0.ceil();
762            }
763
764            pub fn floor(&self) {
765                self.0.floor();
766            }
767
768            pub fn abs(&self) {
769                self.0.abs();
770            }
771
772            pub fn sqrt(&self) {
773                self.0.sqrt();
774            }
775
776            pub fn trim(&self) {
777                self.0.trim();
778            }
779
780            pub fn trim_start(&self) {
781                self.0.trim_start();
782            }
783
784            pub fn trim_end(&self) {
785                self.0.trim_end();
786            }
787
788            pub fn lowercase(&self) {
789                self.0.lowercase();
790            }
791
792            pub fn uppercase(&self) {
793                self.0.uppercase();
794            }
795
796            pub fn slice(&self, start: usize, end: usize) {
797                self.0.slice(start, end);
798            }
799
800            pub fn is_string(&self) {
801                self.0.is_string();
802            }
803
804            pub fn is_int(&self) {
805                self.0.is_int();
806            }
807
808            pub fn is_float(&self) {
809                self.0.is_float();
810            }
811
812            pub fn is_bool(&self) {
813                self.0.is_bool();
814            }
815
816            pub fn is_datetime(&self) {
817                self.0.is_datetime();
818            }
819
820            pub fn is_duration(&self) {
821                self.0.is_duration();
822            }
823
824            pub fn is_null(&self) {
825                self.0.is_null();
826            }
827
828            pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
829                self.0.either_or(
830                    |operand| {
831                        either
832                            .call1(($name::from(operand.clone()),))
833                            .expect("Call must succeed");
834                    },
835                    |operand| {
836                        or.call1(($name::from(operand.clone()),))
837                            .expect("Call must succeed");
838                    },
839                );
840            }
841
842            pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
843                self.0.exclude(|operand| {
844                    query
845                        .call1(($name::from(operand.clone()),))
846                        .expect("Call must succeed");
847                });
848            }
849
850            pub fn deep_clone(&self) -> $name {
851                self.0.deep_clone().into()
852            }
853        }
854    };
855}
856
857implement_single_value_operand!(
858    PyNodeSingleValueWithIndexOperand,
859    SingleValueWithIndexOperand,
860    NodeOperand
861);
862implement_single_value_operand!(
863    PyEdgeSingleValueWithIndexOperand,
864    SingleValueWithIndexOperand,
865    EdgeOperand
866);
867implement_single_value_operand!(
868    PyNodeSingleValueWithoutIndexOperand,
869    SingleValueWithoutIndexOperand,
870    NodeOperand
871);
872implement_single_value_operand!(
873    PyEdgeSingleValueWithoutIndexOperand,
874    SingleValueWithoutIndexOperand,
875    EdgeOperand
876);
877
878macro_rules! implement_single_value_group_operand {
879    ($name:ident, $ungrouped_name:ident, $ungrouped_operand_name:ident, $kind:ident, $generic:ty) => {
880        #[pyclass(frozen)]
881        #[repr(transparent)]
882        #[derive(Clone)]
883        pub struct $name(Wrapper<GroupOperand<$kind<$generic>>>);
884
885        impl From<Wrapper<GroupOperand<$kind<$generic>>>> for $name {
886            fn from(operand: Wrapper<GroupOperand<$kind<$generic>>>) -> Self {
887                Self(operand)
888            }
889        }
890
891        impl From<$name> for Wrapper<GroupOperand<$kind<$generic>>> {
892            fn from(operand: $name) -> Self {
893                operand.0
894            }
895        }
896
897        impl Deref for $name {
898            type Target = Wrapper<GroupOperand<$kind<$generic>>>;
899
900            fn deref(&self) -> &Self::Target {
901                &self.0
902            }
903        }
904
905        #[pymethods]
906        impl $name {
907            pub fn greater_than(&self, value: PySingleValueComparisonOperand) {
908                self.0.greater_than(value);
909            }
910
911            pub fn greater_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
912                self.0.greater_than_or_equal_to(value);
913            }
914
915            pub fn less_than(&self, value: PySingleValueComparisonOperand) {
916                self.0.less_than(value);
917            }
918
919            pub fn less_than_or_equal_to(&self, value: PySingleValueComparisonOperand) {
920                self.0.less_than_or_equal_to(value);
921            }
922
923            pub fn equal_to(&self, value: PySingleValueComparisonOperand) {
924                self.0.equal_to(value);
925            }
926
927            pub fn not_equal_to(&self, value: PySingleValueComparisonOperand) {
928                self.0.not_equal_to(value);
929            }
930
931            pub fn starts_with(&self, value: PySingleValueComparisonOperand) {
932                self.0.starts_with(value);
933            }
934
935            pub fn ends_with(&self, value: PySingleValueComparisonOperand) {
936                self.0.ends_with(value);
937            }
938
939            pub fn contains(&self, value: PySingleValueComparisonOperand) {
940                self.0.contains(value);
941            }
942
943            pub fn is_in(&self, values: PyMultipleValuesComparisonOperand) {
944                self.0.is_in(values);
945            }
946
947            pub fn is_not_in(&self, values: PyMultipleValuesComparisonOperand) {
948                self.0.is_not_in(values);
949            }
950
951            pub fn add(&self, value: PySingleValueComparisonOperand) {
952                self.0.add(value);
953            }
954
955            pub fn sub(&self, value: PySingleValueComparisonOperand) {
956                self.0.sub(value);
957            }
958
959            pub fn mul(&self, value: PySingleValueComparisonOperand) {
960                self.0.mul(value);
961            }
962
963            pub fn div(&self, value: PySingleValueComparisonOperand) {
964                self.0.div(value);
965            }
966
967            pub fn pow(&self, value: PySingleValueComparisonOperand) {
968                self.0.pow(value);
969            }
970
971            pub fn r#mod(&self, value: PySingleValueComparisonOperand) {
972                self.0.r#mod(value);
973            }
974
975            pub fn round(&self) {
976                self.0.round();
977            }
978
979            pub fn ceil(&self) {
980                self.0.ceil();
981            }
982
983            pub fn floor(&self) {
984                self.0.floor();
985            }
986
987            pub fn abs(&self) {
988                self.0.abs();
989            }
990
991            pub fn sqrt(&self) {
992                self.0.sqrt();
993            }
994
995            pub fn trim(&self) {
996                self.0.trim();
997            }
998
999            pub fn trim_start(&self) {
1000                self.0.trim_start();
1001            }
1002
1003            pub fn trim_end(&self) {
1004                self.0.trim_end();
1005            }
1006
1007            pub fn lowercase(&self) {
1008                self.0.lowercase();
1009            }
1010
1011            pub fn uppercase(&self) {
1012                self.0.uppercase();
1013            }
1014
1015            pub fn slice(&self, start: usize, end: usize) {
1016                self.0.slice(start, end);
1017            }
1018
1019            pub fn is_string(&self) {
1020                self.0.is_string();
1021            }
1022
1023            pub fn is_int(&self) {
1024                self.0.is_int();
1025            }
1026
1027            pub fn is_float(&self) {
1028                self.0.is_float();
1029            }
1030
1031            pub fn is_bool(&self) {
1032                self.0.is_bool();
1033            }
1034
1035            pub fn is_datetime(&self) {
1036                self.0.is_datetime();
1037            }
1038
1039            pub fn is_duration(&self) {
1040                self.0.is_duration();
1041            }
1042
1043            pub fn is_null(&self) {
1044                self.0.is_null();
1045            }
1046
1047            pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
1048                self.0.either_or(
1049                    |operand| {
1050                        either
1051                            .call1(($ungrouped_name::from(operand.clone()),))
1052                            .expect("Call must succeed");
1053                    },
1054                    |operand| {
1055                        or.call1(($ungrouped_name::from(operand.clone()),))
1056                            .expect("Call must succeed");
1057                    },
1058                );
1059            }
1060
1061            pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
1062                self.0.exclude(|operand| {
1063                    query
1064                        .call1(($ungrouped_name::from(operand.clone()),))
1065                        .expect("Call must succeed");
1066                });
1067            }
1068
1069            pub fn ungroup(&self) -> $ungrouped_operand_name {
1070                self.0.ungroup().into()
1071            }
1072
1073            pub fn deep_clone(&self) -> $name {
1074                self.0.deep_clone().into()
1075            }
1076        }
1077    };
1078}
1079
1080implement_single_value_group_operand!(
1081    PyNodeSingleValueWithIndexGroupOperand,
1082    PyNodeSingleValueWithIndexOperand,
1083    PyNodeMultipleValuesWithIndexOperand,
1084    SingleValueWithIndexOperand,
1085    NodeOperand
1086);
1087implement_single_value_group_operand!(
1088    PyEdgeSingleValueWithIndexGroupOperand,
1089    PyEdgeSingleValueWithIndexOperand,
1090    PyEdgeMultipleValuesWithIndexOperand,
1091    SingleValueWithIndexOperand,
1092    EdgeOperand
1093);
1094implement_single_value_group_operand!(
1095    PyNodeSingleValueWithoutIndexGroupOperand,
1096    PyNodeSingleValueWithoutIndexOperand,
1097    PyNodeMultipleValuesWithoutIndexOperand,
1098    SingleValueWithoutIndexOperand,
1099    NodeOperand
1100);
1101implement_single_value_group_operand!(
1102    PyEdgeSingleValueWithoutIndexGroupOperand,
1103    PyEdgeSingleValueWithoutIndexOperand,
1104    PyEdgeMultipleValuesWithoutIndexOperand,
1105    SingleValueWithoutIndexOperand,
1106    EdgeOperand
1107);