Skip to main content

graphrecords_query/operations/string_operations/
lowercase.rs

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