Skip to main content

graphrecords_query/operations/ordering/
first.rs

1use crate::{
2    Bare, BareValueDomain, EvaluateOperand, Explain, IndexDomain, Indexed, Multiple, Operand,
3    Ordered, QueryResult, Single, ValueDomain,
4    execution::EvaluationCache,
5    operands::OperandHandle,
6    operations::{
7        Apply, BareStream, KeyedStream, LaneKernel, Operation, OperationContext, Prepare,
8    },
9    optimizer::{Estimate, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs, Stats},
10    registry::operation_manifest,
11    traits::First,
12};
13use graphrecords_core::GraphRecord;
14
15#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
16#[operation(scope = Lane)]
17#[explain(label = "First")]
18#[plan(optimizer_hints(empty = if_any))]
19pub struct FirstOperation;
20
21impl Prepare for FirstOperation {
22    type Prepared<'a> = ();
23
24    fn prepare<'a>(
25        &'a self,
26        _graphrecord: &'a GraphRecord,
27        _cache: &'a EvaluationCache<'a>,
28    ) -> QueryResult<Self::Prepared<'a>> {
29        Ok(())
30    }
31}
32
33impl<I: IndexDomain, V: ValueDomain> LaneKernel<Indexed<I, V>, Multiple<Ordered>>
34    for FirstOperation
35{
36    type Output = OperandHandle<Indexed<I, V>, Single>;
37
38    fn execute<'a>(
39        _graphrecord: &'a GraphRecord,
40        mut values: KeyedStream<'a, I, V, Multiple<Ordered>>,
41        _prepared: Self::Prepared<'a>,
42    ) -> QueryResult<<Self::Output as EvaluateOperand>::ReturnValue<'a>> {
43        Ok(values.next())
44    }
45
46    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
47        input.zero_or_one()
48    }
49}
50
51impl<V: BareValueDomain> LaneKernel<Bare<V>, Multiple<Ordered>> for FirstOperation {
52    type Output = OperandHandle<Bare<V>, Single>;
53
54    fn execute<'a>(
55        _graphrecord: &'a GraphRecord,
56        mut values: BareStream<'a, V, Multiple<Ordered>>,
57        _prepared: Self::Prepared<'a>,
58    ) -> QueryResult<<Self::Output as EvaluateOperand>::ReturnValue<'a>> {
59        Ok(values.next())
60    }
61
62    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
63        input.zero_or_one()
64    }
65}
66
67impl<O: Apply<FirstOperation>> First for O {
68    type ReturnOperand = O::Output;
69
70    fn first(&self) -> Self::ReturnOperand {
71        Self::ReturnOperand::new(OperationContext::new(self.clone(), FirstOperation))
72    }
73}
74
75operation_manifest! {
76    FirstOperation {
77        method: First::first;
78        scope: lane;
79
80        kernel {
81            parameters: <I: IndexDomain, V: ValueDomain>;
82            input: (Indexed<I, V>, Multiple<Ordered>);
83            output: OperandHandle<Indexed<I, V>, Single>;
84        }
85        kernel {
86            parameters: <V: BareValueDomain>;
87            input: (Bare<V>, Multiple<Ordered>);
88            output: OperandHandle<Bare<V>, Single>;
89        }
90    }
91}