Skip to main content

graphrecords_query/operations/numeric/
round.rs

1use super::{numeric_bare, numeric_indexed};
2use crate::{
3    Bare, BareValueDomain, Explain, IndexDomain, Indexed, Labeled, Operand, QueryResult,
4    capabilities::ValueRound,
5    element::Preserving,
6    execution::EvaluationCache,
7    operations::{Apply, ElementKernel, ElementPipeline, Operation, OperationContext, Prepare},
8    optimizer::{Estimate, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs, Stats},
9    registry::operation_manifest,
10    traits::Round,
11};
12use graphrecords_core::GraphRecord;
13
14#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
15#[operation(scope = Element)]
16#[explain(label = "Round")]
17#[plan(optimizer_hints(allows_limit_pushdown, empty = if_any))]
18pub struct RoundOperation;
19
20impl Prepare for RoundOperation {
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, V> ElementKernel<Indexed<I, V>> for RoundOperation
33where
34    I: IndexDomain,
35    V: ValueRound,
36{
37    type Emission = Preserving;
38    type OutShape = Indexed<I, V>;
39
40    fn pipeline<'a>(
41        _graphrecord: &'a GraphRecord,
42        _prepared: Self::Prepared<'a>,
43    ) -> QueryResult<ElementPipeline<'a, Indexed<I, V>, Self>> {
44        Ok(numeric_indexed::<I, V, _>(Self::LABEL, V::round))
45    }
46
47    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
48        input.with_unknown_distinct()
49    }
50}
51
52impl<V> ElementKernel<Bare<V>> for RoundOperation
53where
54    V: ValueRound + BareValueDomain,
55{
56    type Emission = Preserving;
57    type OutShape = Bare<V>;
58
59    fn pipeline<'a>(
60        _graphrecord: &'a GraphRecord,
61        _prepared: Self::Prepared<'a>,
62    ) -> QueryResult<ElementPipeline<'a, Bare<V>, Self>> {
63        Ok(numeric_bare::<V, _>(Self::LABEL, V::round))
64    }
65
66    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
67        input.with_unknown_distinct()
68    }
69}
70
71impl<O: Apply<RoundOperation>> Round for O {
72    type ReturnOperand = O::Output;
73
74    fn round(&self) -> Self::ReturnOperand {
75        Self::ReturnOperand::new(OperationContext::new(self.clone(), RoundOperation))
76    }
77}
78
79operation_manifest! {
80    RoundOperation {
81        method: Round::round;
82        scope: element;
83
84        kernel {
85            parameters: <I: IndexDomain, V: ValueRound>;
86            input: Indexed<I, V>;
87            output: Indexed<I, V>;
88            emission: Preserving;
89        }
90
91        kernel {
92            parameters: <V: ValueRound + BareValueDomain>;
93            input: Bare<V>;
94            output: Bare<V>;
95            emission: Preserving;
96        }
97    }
98}