Skip to main content

graphrecords_query/operations/grouping/
inspection.rs

1use crate::{
2    Arity, Bare, Definite, ElementShape, EvaluateOperand, Explain, IndexDomain, Indexed, Labeled,
3    Multiple, Operand, QueryResult, Single, Unordered,
4    execution::EvaluationCache,
5    index::GroupKey,
6    operands::{FailuresOperand, OperandHandle, Partition},
7    operations::{Apply, BucketFailureArity, GroupKernel, Operation, OperationContext, Prepare},
8    optimizer::{OperationInputs, OptimizerHints, PlanIdentity, PlanInputs},
9    registry::operation_manifest,
10    traits::{BucketErrors, KeyErrors},
11};
12use graphrecords_core::GraphRecord;
13
14#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
15#[operation(scope = Group)]
16#[explain(label = "BucketErrors")]
17#[plan(optimizer_hints(empty = if_any))]
18pub struct BucketErrorsOperation;
19
20impl Prepare for BucketErrorsOperation {
21    type Prepared<'a> = ();
22
23    fn prepare<'a>(
24        &'a self,
25        _graphrecord: &'a GraphRecord,
26        _cache: &'a EvaluationCache<'a>,
27    ) -> QueryResult<Self::Prepared<'a>> {
28        Ok(())
29    }
30}
31
32impl<M: IndexDomain, K: GroupKey, S: ElementShape, C: BucketFailureArity<S>>
33    GroupKernel<M, K, OperandHandle<S, C>> for BucketErrorsOperation
34{
35    type Output = FailuresOperand<K, Unordered>;
36
37    fn execute<'a>(
38        graphrecord: &'a GraphRecord,
39        partition: Partition<'a, M, K, OperandHandle<S, C>>,
40        _prepared: Self::Prepared<'a>,
41    ) -> QueryResult<<Self::Output as EvaluateOperand>::ReturnValue<'a>> {
42        let elements: Vec<_> = partition
43            .buckets()
44            .filter_map(|bucket| {
45                C::bucket_failure(bucket.payload()).map(|failure| {
46                    let index = K::resolve_key(Self::LABEL, graphrecord, bucket.key())?;
47
48                    Ok((index, Ok(failure.clone())))
49                })
50            })
51            .collect::<QueryResult<_>>()?;
52
53        Ok(Box::new(elements.into_iter()))
54    }
55}
56
57impl<O: Apply<BucketErrorsOperation>> BucketErrors for O {
58    type ReturnOperand = O::Output;
59
60    fn bucket_errors(&self) -> Self::ReturnOperand {
61        Self::ReturnOperand::new(OperationContext::new(self.clone(), BucketErrorsOperation))
62    }
63}
64
65pub(super) mod bucket_errors {
66    use super::{
67        Bare, BucketErrors, BucketErrorsOperation, Definite, FailuresOperand, Indexed, Multiple,
68        OperandHandle, Single, Unordered, operation_manifest,
69    };
70
71    operation_manifest! {
72        BucketErrorsOperation {
73            method: BucketErrors::bucket_errors;
74            scope: group;
75
76            kernel {
77                group: <M: IndexDomain, K: GroupKey>;
78                parameters: <I: IndexDomain, V: ValueDomain, O: OrderState>;
79                input: OperandHandle<Indexed<I, V>, Multiple<O>>;
80                output: FailuresOperand<K, Unordered>;
81            }
82            kernel {
83                group: <M: IndexDomain, K: GroupKey>;
84                parameters: <I: IndexDomain, V: ValueDomain>;
85                input: OperandHandle<Indexed<I, V>, Single>;
86                output: FailuresOperand<K, Unordered>;
87            }
88            kernel {
89                group: <M: IndexDomain, K: GroupKey>;
90                parameters: <I: IndexDomain, V: ValueDomain>;
91                input: OperandHandle<Indexed<I, V>, Definite>;
92                output: FailuresOperand<K, Unordered>;
93            }
94            kernel {
95                group: <M: IndexDomain, K: GroupKey>;
96                parameters: <V: BareValueDomain, O: OrderState>;
97                input: OperandHandle<Bare<V>, Multiple<O>>;
98                output: FailuresOperand<K, Unordered>;
99            }
100            kernel {
101                group: <M: IndexDomain, K: GroupKey>;
102                parameters: <V: BareValueDomain>;
103                input: OperandHandle<Bare<V>, Single>;
104                output: FailuresOperand<K, Unordered>;
105            }
106            kernel {
107                group: <M: IndexDomain, K: GroupKey>;
108                parameters: <V: BareValueDomain>;
109                input: OperandHandle<Bare<V>, Definite>;
110                output: FailuresOperand<K, Unordered>;
111            }
112        }
113    }
114}
115
116#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
117#[operation(scope = Group)]
118#[explain(label = "KeyErrors")]
119#[plan(optimizer_hints(empty = if_any))]
120pub struct KeyErrorsOperation;
121
122impl Prepare for KeyErrorsOperation {
123    type Prepared<'a> = ();
124
125    fn prepare<'a>(
126        &'a self,
127        _graphrecord: &'a GraphRecord,
128        _cache: &'a EvaluationCache<'a>,
129    ) -> QueryResult<Self::Prepared<'a>> {
130        Ok(())
131    }
132}
133
134impl<M: IndexDomain, K: GroupKey, S: ElementShape, C: Arity> GroupKernel<M, K, OperandHandle<S, C>>
135    for KeyErrorsOperation
136{
137    type Output = FailuresOperand<M, Unordered>;
138
139    fn execute<'a>(
140        _graphrecord: &'a GraphRecord,
141        partition: Partition<'a, M, K, OperandHandle<S, C>>,
142        _prepared: Self::Prepared<'a>,
143    ) -> QueryResult<<Self::Output as EvaluateOperand>::ReturnValue<'a>> {
144        let key_failures = partition.into_parts().1;
145
146        Ok(Box::new(
147            key_failures
148                .into_iter()
149                .map(|(member, failure)| (member, Ok(*failure))),
150        ))
151    }
152}
153
154impl<O: Apply<KeyErrorsOperation>> KeyErrors for O {
155    type ReturnOperand = O::Output;
156
157    fn key_errors(&self) -> Self::ReturnOperand {
158        Self::ReturnOperand::new(OperationContext::new(self.clone(), KeyErrorsOperation))
159    }
160}
161
162pub(super) mod key_errors {
163    use super::{
164        FailuresOperand, KeyErrors, KeyErrorsOperation, OperandHandle, Unordered,
165        operation_manifest,
166    };
167
168    operation_manifest! {
169        KeyErrorsOperation {
170            method: KeyErrors::key_errors;
171            scope: group;
172
173            kernel {
174                group: <M: IndexDomain, K: GroupKey>;
175                parameters: <S: ElementShape, C: Arity>;
176                input: OperandHandle<S, C>;
177                output: FailuresOperand<M, Unordered>;
178            }
179        }
180    }
181}