graphrecords_query/operations/conversion/
expand_to.rs1use 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}