Skip to main content

graphrecords_query/operations/conversion/
expand_to.rs

1use crate::{
2    ExpandedIndex, ExpandedIndexReference, Explain, IndexDomain, Indexed, Labeled, Operand,
3    QueryResult, ValueDomain,
4    element::{Pipeline, Retention},
5    execution::EvaluationCache,
6    operations::{
7        Apply, ArgumentSource, ElementKernel, ElementPipeline, Keyed, Operation, OperationContext,
8        Prepare,
9    },
10    optimizer::{OperationInputs, OptimizerHints, PlanIdentity, PlanInputs},
11    registry::{describe::ArgumentRetention, operation_manifest},
12    traits::ExpandTo,
13};
14use graphrecords_core::GraphRecord;
15
16#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
17#[operation(scope = Element)]
18#[explain(label = "ExpandTo")]
19#[plan(optimizer_hints(empty = if_all))]
20pub struct ExpandToOperation<S> {
21    #[argument]
22    parent: S,
23}
24
25impl<S: Prepare> Prepare for ExpandToOperation<S> {
26    type Prepared<'a>
27        = S::Prepared<'a>
28    where
29        Self: 'a;
30
31    fn prepare<'a>(
32        &'a self,
33        graphrecord: &'a GraphRecord,
34        cache: &'a EvaluationCache<'a>,
35    ) -> QueryResult<Self::Prepared<'a>> {
36        self.parent.prepare(graphrecord, cache)
37    }
38}
39
40impl<P, C, W, S> ElementKernel<Indexed<ExpandedIndex<P, C>, W>> for ExpandToOperation<S>
41where
42    P: IndexDomain,
43    C: IndexDomain,
44    W: ValueDomain,
45    S: ArgumentSource<Keyed<P>> + Clone,
46{
47    type Emission = S::Retention;
48    type OutShape = Indexed<ExpandedIndex<P, C>, S::ValueDomain>;
49
50    fn pipeline<'a>(
51        _graphrecord: &'a GraphRecord,
52        prepared: Self::Prepared<'a>,
53    ) -> QueryResult<ElementPipeline<'a, Indexed<ExpandedIndex<P, C>, W>, Self>> {
54        Ok(Pipeline::keyed(
55            move |address: ExpandedIndexReference<'_, _, _>, template_outcome| {
56                match template_outcome {
57                    Err(failure) => Self::Emission::keep(Err(failure)),
58                    Ok(_) => S::resolve(&prepared, address.parent_index(), Self::LABEL),
59                }
60            },
61        ))
62    }
63}
64
65impl<S, T> ExpandTo<T> for S
66where
67    S: Clone,
68    T: Apply<ExpandToOperation<S>>,
69    ExpandToOperation<S>: Operation,
70{
71    type ReturnOperand = T::Output;
72
73    fn expand_to(&self, template: &T) -> Self::ReturnOperand {
74        Self::ReturnOperand::new(OperationContext::new(
75            template.clone(),
76            ExpandToOperation {
77                parent: self.clone(),
78            },
79        ))
80    }
81}
82
83operation_manifest! {
84    ExpandToOperation<S> {
85        method: ExpandTo::expand_to;
86        scope: element;
87
88        kernel {
89            parameters: <P: IndexDomain, C: IndexDomain, W: ValueDomain, X: ValueDomain>;
90            argument: S: ArgumentSource<Keyed<P>, X>;
91            receiver: S;
92            input: Indexed<ExpandedIndex<P, C>, W>;
93            output: Indexed<ExpandedIndex<P, C>, X>;
94            emission: ArgumentRetention;
95        }
96    }
97}