risingwave_common/array/
decimal_array.rs1use super::{PrimitiveArray, PrimitiveArrayBuilder};
16use crate::types::Decimal;
17
18pub type DecimalArray = PrimitiveArray<Decimal>;
19pub type DecimalArrayBuilder = PrimitiveArrayBuilder<Decimal>;
20
21#[cfg(test)]
22mod tests {
23 use std::hash::Hash;
24 use std::str::FromStr;
25
26 use itertools::Itertools;
27
28 use super::*;
29 use crate::array::{Array, ArrayBuilder, ArrayImpl, NULL_VAL_FOR_HASH};
30 use crate::util::iter_util::ZipEqFast;
31
32 #[test]
33 fn test_decimal_builder() {
34 let v = (0..1000).map(Decimal::from).collect_vec();
35 let mut builder = DecimalArrayBuilder::new(0);
36 for i in &v {
37 builder.append(Some(*i));
38 }
39 let a = builder.finish();
40 let res = v.iter().zip_eq_fast(a.iter()).all(|(a, b)| Some(*a) == b);
41 assert!(res);
42 }
43
44 #[test]
45 fn test_decimal_array_to_protobuf() {
46 let input = vec![
47 Some(Decimal::from_str("1.01").unwrap()),
48 Some(Decimal::from_str("2.02").unwrap()),
49 None,
50 Some(Decimal::from_str("4.04").unwrap()),
51 None,
52 Some(Decimal::NegativeInf),
53 Some(Decimal::PositiveInf),
54 Some(Decimal::NaN),
55 ];
56
57 let array = DecimalArray::from_iter(&input);
58 let prost_array = array.to_protobuf();
59
60 assert_eq!(prost_array.values.len(), 1);
61
62 let decoded_array = ArrayImpl::from_protobuf(&prost_array, 8)
63 .unwrap()
64 .into_decimal();
65
66 assert!(array.iter().eq(decoded_array.iter()));
67 }
68
69 #[test]
70 fn test_decimal_array_hash() {
71 use std::hash::BuildHasher;
72
73 use super::super::test_util::{hash_finish, test_hash};
74
75 const ARR_NUM: usize = 3;
76 const ARR_LEN: usize = 270;
77 let vecs: [Vec<Option<Decimal>>; ARR_NUM] = [
78 (0..ARR_LEN)
79 .map(|x| match x % 2 {
80 0 => Some(Decimal::from(0)),
81 1 => None,
82 _ => unreachable!(),
83 })
84 .collect_vec(),
85 (0..ARR_LEN)
86 .map(|x| match x % 3 {
87 0 => Some(Decimal::from(0)),
88 #[expect(clippy::approx_constant)]
89 1 => Decimal::try_from(3.14).ok(),
90 2 => None,
91 _ => unreachable!(),
92 })
93 .collect_vec(),
94 (0..ARR_LEN)
95 .map(|x| match x % 5 {
96 0 => Some(Decimal::from(0)),
97 1 => Some(Decimal::from(123)),
98 #[expect(clippy::approx_constant)]
99 2 => Decimal::try_from(3.1415926).ok(),
100 #[expect(clippy::approx_constant)]
101 3 => Decimal::try_from(3.14).ok(),
102 4 => None,
103 _ => unreachable!(),
104 })
105 .collect_vec(),
106 ];
107
108 let arrs = vecs
109 .iter()
110 .map(|v| {
111 let mut builder = DecimalArrayBuilder::new(0);
112 for i in v {
113 builder.append(*i);
114 }
115 builder.finish()
116 })
117 .collect_vec();
118
119 let hasher_builder = twox_hash::xxhash64::RandomState::default();
120 let mut states = vec![hasher_builder.build_hasher(); ARR_LEN];
121 vecs.iter().for_each(|v| {
122 v.iter()
123 .zip_eq_fast(&mut states)
124 .for_each(|(x, state)| match x {
125 Some(inner) => inner.hash(state),
126 None => NULL_VAL_FOR_HASH.hash(state),
127 })
128 });
129 let hashes = hash_finish(&states[..]);
130
131 let count = hashes.iter().counts().len();
132 assert_eq!(count, 30);
133
134 test_hash(arrs, hashes, hasher_builder);
135 }
136}