Skip to main content

graphrecords_query/operations/arithmetic/
add.rs

1use super::{arithmetic_bare, arithmetic_indexed};
2use crate::{
3    Bare, BareValueDomain, Explain, IndexDomain, Indexed, Labeled, Operand, QueryResult,
4    capabilities::ValueAdd,
5    execution::EvaluationCache,
6    operations::{
7        Apply, ArgumentSource, ElementKernel, ElementPipeline, Keyed, Operation, OperationContext,
8        Prepare, Unaligned,
9    },
10    optimizer::{Estimate, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs, Stats},
11    registry::{describe::ArgumentRetention, operation_manifest},
12    traits::Add,
13};
14use graphrecords_core::GraphRecord;
15
16#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
17#[operation(scope = Element)]
18#[explain(label = "Add")]
19#[plan(optimizer_hints(empty = if_all))]
20pub struct AddOperation<A> {
21    #[argument]
22    argument: A,
23}
24
25impl<A: Prepare> Prepare for AddOperation<A> {
26    type Prepared<'a>
27        = A::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.argument.prepare(graphrecord, cache)
37    }
38}
39
40impl<I, V, A> ElementKernel<Indexed<I, V>> for AddOperation<A>
41where
42    I: IndexDomain,
43    V: ValueAdd,
44    A: ArgumentSource<Keyed<I>, V>,
45{
46    type Emission = A::Retention;
47    type OutShape = Indexed<I, V>;
48
49    fn pipeline<'a>(
50        _graphrecord: &'a GraphRecord,
51        prepared: Self::Prepared<'a>,
52    ) -> QueryResult<ElementPipeline<'a, Indexed<I, V>, Self>> {
53        Ok(arithmetic_indexed::<_, V, A>(prepared, Self::LABEL, V::add))
54    }
55
56    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
57        input.with_unknown_distinct()
58    }
59}
60
61impl<V, A> ElementKernel<Bare<V>> for AddOperation<A>
62where
63    V: ValueAdd + BareValueDomain,
64    A: ArgumentSource<Unaligned, V>,
65{
66    type Emission = A::Retention;
67    type OutShape = Bare<V>;
68
69    fn pipeline<'a>(
70        _graphrecord: &'a GraphRecord,
71        prepared: Self::Prepared<'a>,
72    ) -> QueryResult<ElementPipeline<'a, Bare<V>, Self>> {
73        Ok(arithmetic_bare::<V, A>(prepared, Self::LABEL, V::add))
74    }
75
76    fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
77        input.with_unknown_distinct()
78    }
79}
80
81impl<O, A> Add<A> for O
82where
83    AddOperation<A>: Operation,
84    O: Apply<AddOperation<A>>,
85{
86    type ReturnOperand = O::Output;
87
88    fn add(&self, argument: A) -> Self::ReturnOperand {
89        Self::ReturnOperand::new(OperationContext::new(
90            self.clone(),
91            AddOperation { argument },
92        ))
93    }
94}
95
96operation_manifest! {
97    AddOperation<A> {
98        method: Add<A>::add;
99        scope: element;
100
101        kernel {
102            parameters: <I: IndexDomain, V: ValueAdd>;
103            argument: A: ArgumentSource<Keyed<I>, V>;
104            input: Indexed<I, V>;
105            output: Indexed<I, V>;
106            emission: ArgumentRetention;
107        }
108
109        kernel {
110            parameters: <V: ValueAdd + BareValueDomain>;
111            argument: A: ArgumentSource<Unaligned, V>;
112            input: Bare<V>;
113            output: Bare<V>;
114            emission: ArgumentRetention;
115        }
116    }
117}