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