reifydb_column/compute/
mod.rs1pub mod canonical;
5
6use reifydb_core::value::column::{array::Column, mask::RowMask};
7use reifydb_type::{Result, value::Value};
8
9use crate::encoding;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub enum CompareOp {
13 Eq,
14 Ne,
15 Lt,
16 LtEq,
17 Gt,
18 GtEq,
19}
20
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub enum SearchResult {
23 Found(usize),
24 NotFound(usize),
25}
26
27pub trait Compute: Send + Sync {
33 fn filter(&self, _array: &Column, _mask: &RowMask) -> Option<Result<Column>> {
34 None
35 }
36
37 fn take(&self, _array: &Column, _indices: &Column) -> Option<Result<Column>> {
38 None
39 }
40
41 fn slice(&self, _array: &Column, _start: usize, _end: usize) -> Option<Result<Column>> {
42 None
43 }
44
45 fn compare(&self, _array: &Column, _rhs: &Value, _op: CompareOp) -> Option<Result<Column>> {
46 None
47 }
48
49 fn search_sorted(&self, _array: &Column, _needle: &Value) -> Option<Result<SearchResult>> {
50 None
51 }
52
53 fn min_max(&self, _array: &Column) -> Option<Result<(Value, Value)>> {
54 None
55 }
56
57 fn sum(&self, _array: &Column) -> Option<Result<Value>> {
58 None
59 }
60}
61
62pub struct DefaultCompute;
63
64impl Compute for DefaultCompute {}
65
66pub fn filter(array: &Column, mask: &RowMask) -> Result<Column> {
72 if let Some(result) = specialized(array, |c| c.filter(array, mask)) {
73 return result;
74 }
75 let canon = array.to_canonical()?;
76 Ok(Column::from_canonical(canonical::filter::filter(&canon, mask)?))
77}
78
79pub fn take(array: &Column, indices: &Column) -> Result<Column> {
80 if let Some(result) = specialized(array, |c| c.take(array, indices)) {
81 return result;
82 }
83 let canon = array.to_canonical()?;
84 let idx = indices.to_canonical()?;
85 Ok(Column::from_canonical(canonical::take::take(&canon, &idx)?))
86}
87
88pub fn slice(array: &Column, start: usize, end: usize) -> Result<Column> {
89 if let Some(result) = specialized(array, |c| c.slice(array, start, end)) {
90 return result;
91 }
92 let canon = array.to_canonical()?;
93 Ok(Column::from_canonical(canonical::slice::slice(&canon, start, end)?))
94}
95
96pub fn compare(array: &Column, rhs: &Value, op: CompareOp) -> Result<Column> {
97 if let Some(result) = specialized(array, |c| c.compare(array, rhs, op)) {
98 return result;
99 }
100 let canon = array.to_canonical()?;
101 Ok(Column::from_canonical(canonical::compare::compare(&canon, rhs, op)?))
102}
103
104pub fn search_sorted(array: &Column, needle: &Value) -> Result<SearchResult> {
105 if let Some(result) = specialized(array, |c| c.search_sorted(array, needle)) {
106 return result;
107 }
108 let canon = array.to_canonical()?;
109 canonical::search_sorted::search_sorted(&canon, needle)
110}
111
112pub fn min_max(array: &Column) -> Result<(Value, Value)> {
113 if let Some(result) = specialized(array, |c| c.min_max(array)) {
114 return result;
115 }
116 let canon = array.to_canonical()?;
117 canonical::min_max::min_max(&canon)
118}
119
120pub fn sum(array: &Column) -> Result<Value> {
121 if let Some(result) = specialized(array, |c| c.sum(array)) {
122 return result;
123 }
124 let canon = array.to_canonical()?;
125 canonical::sum::sum(&canon)
126}
127
128fn specialized<T>(array: &Column, hook: impl FnOnce(&dyn Compute) -> Option<Result<T>>) -> Option<Result<T>> {
129 let registry = encoding::global();
130 let encoding = registry.get(array.encoding())?;
131 hook(encoding.compute())
132}