graphrecords_query/operations/indexing/
expanded.rs1use crate::{
2 Bare, ExpandedIndex, ExpandedIndexOwned, Explain, Failure, IndexDomain, IndexValue, Indexed,
3 Labeled, Operand, QueryResult,
4 element::{Pipeline, Preserving},
5 error::index::NoChildIndex,
6 execution::EvaluationCache,
7 operations::{Apply, ElementKernel, ElementPipeline, Operation, OperationContext, Prepare},
8 optimizer::{OperationInputs, OptimizerHints, PlanIdentity, PlanInputs},
9 registry::operation_manifest,
10 traits::{ChildIndex, ParentIndex},
11};
12use graphrecords_core::GraphRecord;
13
14#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
15#[operation(scope = Element)]
16#[explain(label = "ParentIndex")]
17#[plan(optimizer_hints(commutes_with_filter, allows_limit_pushdown, empty = if_any))]
18pub struct ParentIndexOperation;
19
20impl Prepare for ParentIndexOperation {
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<I: IndexDomain, P: IndexDomain, C: IndexDomain>
33 ElementKernel<Indexed<I, IndexValue<ExpandedIndex<P, C>>>> for ParentIndexOperation
34{
35 type Emission = Preserving;
36 type OutShape = Indexed<I, IndexValue<P>>;
37
38 fn pipeline<'a>(
39 _graphrecord: &'a GraphRecord,
40 _prepared: Self::Prepared<'a>,
41 ) -> QueryResult<ElementPipeline<'a, Indexed<I, IndexValue<ExpandedIndex<P, C>>>, Self>> {
42 Ok(Pipeline::unkeyed(
43 |outcome: QueryResult<ExpandedIndexOwned<_, _>>| {
44 outcome.map(|address| address.into_parts().0)
45 },
46 ))
47 }
48}
49
50impl<P: IndexDomain, C: IndexDomain> ElementKernel<Bare<IndexValue<ExpandedIndex<P, C>>>>
51 for ParentIndexOperation
52{
53 type Emission = Preserving;
54 type OutShape = Bare<IndexValue<P>>;
55
56 fn pipeline<'a>(
57 _graphrecord: &'a GraphRecord,
58 _prepared: Self::Prepared<'a>,
59 ) -> QueryResult<ElementPipeline<'a, Bare<IndexValue<ExpandedIndex<P, C>>>, Self>> {
60 Ok(Pipeline::new(
61 |outcome: QueryResult<ExpandedIndexOwned<_, _>>| {
62 outcome.map(|address| address.into_parts().0)
63 },
64 ))
65 }
66}
67
68impl<O: Apply<ParentIndexOperation>> ParentIndex for O {
69 type ReturnOperand = O::Output;
70
71 fn parent_index(&self) -> Self::ReturnOperand {
72 Self::ReturnOperand::new(OperationContext::new(self.clone(), ParentIndexOperation))
73 }
74}
75
76pub(super) mod parent_index {
77 use super::{
78 Bare, ExpandedIndex, IndexValue, Indexed, ParentIndex, ParentIndexOperation, Preserving,
79 operation_manifest,
80 };
81
82 operation_manifest! {
83 ParentIndexOperation {
84 method: ParentIndex::parent_index;
85 scope: element;
86
87 kernel {
88 parameters: <I: IndexDomain, P: IndexDomain, C: IndexDomain>;
89 input: Indexed<I, IndexValue<ExpandedIndex<P, C>>>;
90 output: Indexed<I, IndexValue<P>>;
91 emission: Preserving;
92 }
93 kernel {
94 parameters: <P: IndexDomain, C: IndexDomain>;
95 input: Bare<IndexValue<ExpandedIndex<P, C>>>;
96 output: Bare<IndexValue<P>>;
97 emission: Preserving;
98 }
99 }
100 }
101}
102
103#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
104#[operation(scope = Element)]
105#[explain(label = "ChildIndex")]
106#[plan(optimizer_hints(allows_limit_pushdown, empty = if_any))]
107pub struct ChildIndexOperation;
108
109impl Prepare for ChildIndexOperation {
110 type Prepared<'a> = ();
111
112 fn prepare<'a>(
113 &'a self,
114 _graphrecord: &'a GraphRecord,
115 _cache: &'a EvaluationCache<'a>,
116 ) -> QueryResult<Self::Prepared<'a>> {
117 Ok(())
118 }
119}
120
121impl<I: IndexDomain, P: IndexDomain, C: IndexDomain>
122 ElementKernel<Indexed<I, IndexValue<ExpandedIndex<P, C>>>> for ChildIndexOperation
123{
124 type Emission = Preserving;
125 type OutShape = Indexed<I, IndexValue<C>>;
126
127 fn pipeline<'a>(
128 _graphrecord: &'a GraphRecord,
129 _prepared: Self::Prepared<'a>,
130 ) -> QueryResult<ElementPipeline<'a, Indexed<I, IndexValue<ExpandedIndex<P, C>>>, Self>> {
131 Ok(Pipeline::keyed(
132 |lane_index, outcome: QueryResult<ExpandedIndexOwned<_, _>>| {
133 let (parent, child) = outcome?.into_parts();
134
135 child.ok_or_else(|| {
136 Failure::new_at::<I, _>(
137 Self::LABEL,
138 NoChildIndex::<P>::new(parent),
139 &lane_index,
140 )
141 })
142 },
143 ))
144 }
145}
146
147impl<P: IndexDomain, C: IndexDomain> ElementKernel<Bare<IndexValue<ExpandedIndex<P, C>>>>
148 for ChildIndexOperation
149{
150 type Emission = Preserving;
151 type OutShape = Bare<IndexValue<C>>;
152
153 fn pipeline<'a>(
154 _graphrecord: &'a GraphRecord,
155 _prepared: Self::Prepared<'a>,
156 ) -> QueryResult<ElementPipeline<'a, Bare<IndexValue<ExpandedIndex<P, C>>>, Self>> {
157 Ok(Pipeline::new(
158 |outcome: QueryResult<ExpandedIndexOwned<_, _>>| {
159 let (parent, child) = outcome?.into_parts();
160
161 child.ok_or_else(|| Failure::new(Self::LABEL, NoChildIndex::<P>::new(parent)))
162 },
163 ))
164 }
165}
166
167impl<O: Apply<ChildIndexOperation>> ChildIndex for O {
168 type ReturnOperand = O::Output;
169
170 fn child_index(&self) -> Self::ReturnOperand {
171 Self::ReturnOperand::new(OperationContext::new(self.clone(), ChildIndexOperation))
172 }
173}
174
175pub(super) mod child_index {
176 use super::{
177 Bare, ChildIndex, ChildIndexOperation, ExpandedIndex, IndexValue, Indexed, Preserving,
178 operation_manifest,
179 };
180
181 operation_manifest! {
182 ChildIndexOperation {
183 method: ChildIndex::child_index;
184 scope: element;
185
186 kernel {
187 parameters: <I: IndexDomain, P: IndexDomain, C: IndexDomain>;
188 input: Indexed<I, IndexValue<ExpandedIndex<P, C>>>;
189 output: Indexed<I, IndexValue<C>>;
190 emission: Preserving;
191 }
192 kernel {
193 parameters: <P: IndexDomain, C: IndexDomain>;
194 input: Bare<IndexValue<ExpandedIndex<P, C>>>;
195 output: Bare<IndexValue<C>>;
196 emission: Preserving;
197 }
198 }
199 }
200}