vortex_array/arrays/varbin/compute/
min_max.rs1use itertools::Itertools;
2use vortex_dtype::DType;
3use vortex_error::VortexResult;
4use vortex_scalar::Scalar;
5
6use crate::accessor::ArrayAccessor;
7use crate::arrays::{VarBinArray, VarBinVTable};
8use crate::compute::{MinMaxKernel, MinMaxKernelAdapter, MinMaxResult};
9use crate::register_kernel;
10
11impl MinMaxKernel for VarBinVTable {
12 fn min_max(&self, array: &VarBinArray) -> VortexResult<Option<MinMaxResult>> {
13 compute_min_max(array, array.dtype())
14 }
15}
16
17register_kernel!(MinMaxKernelAdapter(VarBinVTable).lift());
18
19pub fn compute_min_max<T: ArrayAccessor<[u8]>>(
21 array: &T,
22 dtype: &DType,
23) -> VortexResult<Option<MinMaxResult>> {
24 let minmax = array.with_iterator(|iter| match iter.flatten().minmax() {
25 itertools::MinMaxResult::NoElements => None,
26 itertools::MinMaxResult::OneElement(value) => {
27 let scalar = make_scalar(dtype, value);
28 Some(MinMaxResult {
29 min: scalar.clone(),
30 max: scalar,
31 })
32 }
33 itertools::MinMaxResult::MinMax(min, max) => Some(MinMaxResult {
34 min: make_scalar(dtype, min),
35 max: make_scalar(dtype, max),
36 }),
37 })?;
38
39 Ok(minmax)
40}
41
42fn make_scalar(dtype: &DType, value: &[u8]) -> Scalar {
44 match dtype {
45 DType::Binary(_) => Scalar::new(dtype.clone(), value.into()),
46 DType::Utf8(_) => {
47 let value = unsafe { str::from_utf8_unchecked(value) };
50 Scalar::new(dtype.clone(), value.into())
51 }
52 _ => unreachable!(),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use vortex_buffer::BufferString;
59 use vortex_dtype::DType::Utf8;
60 use vortex_dtype::Nullability::Nullable;
61 use vortex_scalar::Scalar;
62
63 use crate::arrays::VarBinArray;
64 use crate::compute::{MinMaxResult, min_max};
65 use crate::stats::{Stat, StatsProvider};
66
67 #[test]
68 fn some_nulls() {
69 let array = VarBinArray::from_iter(
70 vec![
71 Some("hello world"),
72 None,
73 Some("hello world this is a long string"),
74 None,
75 ],
76 Utf8(Nullable),
77 );
78 let MinMaxResult { min, max } = min_max(array.as_ref()).unwrap().unwrap();
79
80 assert_eq!(
81 min,
82 Scalar::new(
83 Utf8(Nullable),
84 BufferString::from("hello world".to_string()).into(),
85 )
86 );
87 assert_eq!(
88 max,
89 Scalar::new(
90 Utf8(Nullable),
91 BufferString::from("hello world this is a long string".to_string()).into()
92 )
93 );
94 }
95
96 #[test]
97 fn all_nulls() {
98 let array = VarBinArray::from_iter(vec![Option::<&str>::None, None, None], Utf8(Nullable));
99 let stats = array.statistics();
100 assert!(stats.get(Stat::Min).is_none());
101 assert!(stats.get(Stat::Max).is_none());
102 }
103}