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