graphrecords_query/operations/indexing/
index.rs1use crate::{
2 EntityDomain, EntityReference, Explain, IndexDomain, IndexValue, Indexed, Operand, QueryResult,
3 Unit,
4 element::{Pipeline, Preserving},
5 execution::EvaluationCache,
6 operations::{Apply, ElementKernel, ElementPipeline, Operation, OperationContext, Prepare},
7 optimizer::{Estimate, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs, Stats},
8 registry::operation_manifest,
9 traits::Index,
10};
11use graphrecords_core::GraphRecord;
12
13#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
14#[operation(scope = Element)]
15#[explain(label = "Index")]
16#[plan(optimizer_hints(commutes_with_filter, allows_limit_pushdown, empty = if_any))]
17pub struct IndexOperation;
18
19impl Prepare for IndexOperation {
20 type Prepared<'a> = ();
21
22 fn prepare<'a>(
23 &'a self,
24 _graphrecord: &'a GraphRecord,
25 _cache: &'a EvaluationCache<'a>,
26 ) -> QueryResult<Self::Prepared<'a>> {
27 Ok(())
28 }
29}
30
31impl<K: IndexDomain> ElementKernel<Indexed<K, Unit>> for IndexOperation {
32 type Emission = Preserving;
33 type OutShape = Indexed<K, IndexValue<K>>;
34
35 fn pipeline<'a>(
36 _graphrecord: &'a GraphRecord,
37 _prepared: Self::Prepared<'a>,
38 ) -> QueryResult<ElementPipeline<'a, Indexed<K, Unit>, Self>> {
39 Ok(Pipeline::keyed(|index, value: QueryResult<_>| {
40 value.map(|()| K::to_owned(&index))
41 }))
42 }
43
44 fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
45 Estimate {
46 distinct: input.elements,
47 ..input
48 }
49 }
50}
51
52impl<E: EntityDomain, I: IndexDomain> ElementKernel<Indexed<I, EntityReference<E>>>
53 for IndexOperation
54{
55 type Emission = Preserving;
56 type OutShape = Indexed<I, IndexValue<E>>;
57
58 fn pipeline<'a>(
59 _graphrecord: &'a GraphRecord,
60 _prepared: Self::Prepared<'a>,
61 ) -> QueryResult<ElementPipeline<'a, Indexed<I, EntityReference<E>>, Self>> {
62 Ok(Pipeline::unkeyed(|reference: QueryResult<_>| {
63 reference.map(|entity| E::to_owned(&entity))
64 }))
65 }
66
67 fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
68 input
69 }
70}
71
72impl<O: Apply<IndexOperation>> Index for O {
73 type ReturnOperand = O::Output;
74
75 fn index(&self) -> Self::ReturnOperand {
76 Self::ReturnOperand::new(OperationContext::new(self.clone(), IndexOperation))
77 }
78}
79
80operation_manifest! {
81 IndexOperation {
82 method: Index::index;
83 scope: element;
84
85 kernel {
86 parameters: <K: IndexDomain>;
87 input: Indexed<K, Unit>;
88 output: Indexed<K, IndexValue<K>>;
89 emission: Preserving;
90 }
91
92 kernel {
93 parameters: <E: EntityDomain, I: IndexDomain>;
94 input: Indexed<I, EntityReference<E>>;
95 output: Indexed<I, IndexValue<E>>;
96 emission: Preserving;
97 }
98 }
99}