reifydb_engine/function/math/aggregate/
min.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use std::collections::HashMap;
5
6use reifydb_core::value::column::ColumnData;
7use reifydb_type::Value;
8
9use crate::function::{AggregateFunction, AggregateFunctionContext};
10
11pub struct Min {
12	pub mins: HashMap<Vec<Value>, f64>,
13}
14
15impl Min {
16	pub fn new() -> Self {
17		Self {
18			mins: HashMap::new(),
19		}
20	}
21}
22
23impl AggregateFunction for Min {
24	fn aggregate(&mut self, ctx: AggregateFunctionContext) -> crate::Result<()> {
25		let column = ctx.column;
26		let groups = &ctx.groups;
27
28		match &column.data() {
29			ColumnData::Float8(container) => {
30				for (group, indices) in groups.iter() {
31					let min_val = indices
32						.iter()
33						.filter_map(|&i| container.get(i))
34						.min_by(|a, b| a.partial_cmp(b).unwrap());
35
36					if let Some(min_val) = min_val {
37						self.mins
38							.entry(group.clone())
39							.and_modify(|v| *v = f64::min(*v, *min_val))
40							.or_insert(*min_val);
41					}
42				}
43				Ok(())
44			}
45			ColumnData::Float4(container) => {
46				for (group, indices) in groups.iter() {
47					let min_val = indices
48						.iter()
49						.filter_map(|&i| container.get(i))
50						.min_by(|a, b| a.partial_cmp(b).unwrap());
51
52					if let Some(min_val) = min_val {
53						self.mins
54							.entry(group.clone())
55							.and_modify(|v| *v = f64::min(*v, *min_val as f64))
56							.or_insert(*min_val as f64);
57					}
58				}
59				Ok(())
60			}
61			ColumnData::Int2(container) => {
62				for (group, indices) in groups.iter() {
63					let min_val = indices
64						.iter()
65						.filter_map(|&i| container.get(i))
66						.min_by(|a, b| a.partial_cmp(b).unwrap());
67
68					if let Some(min_val) = min_val {
69						self.mins
70							.entry(group.clone())
71							.and_modify(|v| *v = f64::min(*v, *min_val as f64))
72							.or_insert(*min_val as f64);
73					}
74				}
75				Ok(())
76			}
77			ColumnData::Int4(container) => {
78				for (group, indices) in groups.iter() {
79					let min_val = indices
80						.iter()
81						.filter_map(|&i| container.get(i))
82						.min_by(|a, b| a.partial_cmp(b).unwrap());
83
84					if let Some(min_val) = min_val {
85						self.mins
86							.entry(group.clone())
87							.and_modify(|v| *v = f64::min(*v, *min_val as f64))
88							.or_insert(*min_val as f64);
89					}
90				}
91				Ok(())
92			}
93			_ => unimplemented!(),
94		}
95	}
96
97	fn finalize(&mut self) -> crate::Result<(Vec<Vec<Value>>, ColumnData)> {
98		let mut keys = Vec::with_capacity(self.mins.len());
99		let mut data = ColumnData::float8_with_capacity(self.mins.len());
100
101		for (key, min) in std::mem::take(&mut self.mins) {
102			keys.push(key);
103			data.push_value(Value::float8(min));
104		}
105
106		Ok((keys, data))
107	}
108}