1use std::any::Any;
5
6use vortex_buffer::BufferMut;
7use vortex_error::VortexExpect;
8use vortex_error::VortexResult;
9use vortex_error::vortex_ensure;
10use vortex_error::vortex_err;
11use vortex_error::vortex_panic;
12
13use crate::ArrayRef;
14use crate::ExecutionCtx;
15use crate::IntoArray;
16use crate::arrays::DecimalArray;
17use crate::builders::ArrayBuilder;
18use crate::builders::DEFAULT_BUILDER_CAPACITY;
19use crate::builders::LazyBitBufferBuilder;
20use crate::canonical::Canonical;
21use crate::dtype::BigCast;
22use crate::dtype::DType;
23use crate::dtype::DecimalDType;
24use crate::dtype::NativeDecimalType;
25use crate::dtype::Nullability;
26use crate::dtype::i256;
27use crate::match_each_decimal_value;
28use crate::match_each_decimal_value_type;
29use crate::scalar::DecimalValue;
30use crate::scalar::Scalar;
31
32pub struct DecimalBuilder {
38 dtype: DType,
39 values: DecimalBuffer,
40 nulls: LazyBitBufferBuilder,
41}
42
43enum DecimalBuffer {
49 I8(BufferMut<i8>),
50 I16(BufferMut<i16>),
51 I32(BufferMut<i32>),
52 I64(BufferMut<i64>),
53 I128(BufferMut<i128>),
54 I256(BufferMut<i256>),
55}
56
57macro_rules! delegate_fn {
58 ($self:expr, | $tname:ident, $buffer:ident | $body:block) => {{
59 #[allow(unused)]
60 match $self {
61 DecimalBuffer::I8(buffer) => {
62 type $tname = i8;
63 let $buffer = buffer;
64 $body
65 }
66 DecimalBuffer::I16(buffer) => {
67 type $tname = i16;
68 let $buffer = buffer;
69 $body
70 }
71 DecimalBuffer::I32(buffer) => {
72 type $tname = i32;
73 let $buffer = buffer;
74 $body
75 }
76 DecimalBuffer::I64(buffer) => {
77 type $tname = i64;
78 let $buffer = buffer;
79 $body
80 }
81 DecimalBuffer::I128(buffer) => {
82 type $tname = i128;
83 let $buffer = buffer;
84 $body
85 }
86 DecimalBuffer::I256(buffer) => {
87 type $tname = i256;
88 let $buffer = buffer;
89 $body
90 }
91 }
92 }};
93}
94
95impl DecimalBuilder {
96 pub fn new<T: NativeDecimalType>(decimal: DecimalDType, nullability: Nullability) -> Self {
98 Self::with_capacity::<T>(DEFAULT_BUILDER_CAPACITY, decimal, nullability)
99 }
100
101 pub fn with_capacity<T: NativeDecimalType>(
103 capacity: usize,
104 decimal: DecimalDType,
105 nullability: Nullability,
106 ) -> Self {
107 Self {
108 dtype: DType::Decimal(decimal, nullability),
109 values: match_each_decimal_value_type!(T::DECIMAL_TYPE, |D| {
110 DecimalBuffer::from(BufferMut::<D>::with_capacity(capacity))
111 }),
112 nulls: LazyBitBufferBuilder::new(capacity),
113 }
114 }
115
116 pub fn append_value<V: NativeDecimalType>(&mut self, value: V) {
118 self.values.push(value);
119 self.nulls.append_non_null();
120 }
121
122 pub fn append_n_values<V: NativeDecimalType>(&mut self, value: V, n: usize) {
124 self.values.push_n(value, n);
125 self.nulls.append_n_non_nulls(n);
126 }
127
128 pub(crate) fn append_decimal_array(
131 &mut self,
132 array: &DecimalArray,
133 ctx: &mut ExecutionCtx,
134 ) -> VortexResult<()> {
135 match_each_decimal_value_type!(array.values_type(), |D| {
136 self.values.extend(array.buffer::<D>().iter().copied());
139 });
140
141 self.nulls.append_validity_mask(
142 &array
143 .as_ref()
144 .validity()?
145 .execute_mask(array.as_ref().len(), ctx)?,
146 );
147 Ok(())
148 }
149
150 pub fn finish_into_decimal(&mut self) -> DecimalArray {
152 let validity = self.nulls.finish_with_nullability(self.dtype.nullability());
153
154 let decimal_dtype = *self.decimal_dtype();
155
156 delegate_fn!(std::mem::take(&mut self.values), |T, values| {
157 DecimalArray::new::<T>(values.freeze(), decimal_dtype, validity)
158 })
159 }
160
161 pub fn decimal_dtype(&self) -> &DecimalDType {
163 let DType::Decimal(decimal_dtype, _) = &self.dtype else {
164 vortex_panic!("`DecimalBuilder` somehow had dtype {}", self.dtype);
165 };
166
167 decimal_dtype
168 }
169}
170
171impl ArrayBuilder for DecimalBuilder {
172 fn as_any(&self) -> &dyn Any {
173 self
174 }
175
176 fn as_any_mut(&mut self) -> &mut dyn Any {
177 self
178 }
179
180 fn dtype(&self) -> &DType {
181 &self.dtype
182 }
183
184 fn len(&self) -> usize {
185 self.values.len()
186 }
187
188 fn append_zeros(&mut self, n: usize) {
189 self.values.push_n(0, n);
190 self.nulls.append_n_non_nulls(n);
191 }
192
193 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
194 self.values.push_n(0, n);
195 self.nulls.append_n_nulls(n);
196 }
197
198 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
199 vortex_ensure!(
200 scalar.dtype() == self.dtype(),
201 "DecimalBuilder expected scalar with dtype {}, got {}",
202 self.dtype(),
203 scalar.dtype()
204 );
205
206 match scalar.as_decimal().decimal_value() {
207 None => self.append_null(),
208 Some(v) => match_each_decimal_value!(v, |dec_val| {
209 self.append_value(dec_val);
210 }),
211 }
212
213 Ok(())
214 }
215
216 fn reserve_exact(&mut self, additional: usize) {
217 self.values.reserve(additional);
218 self.nulls.reserve_exact(additional);
219 }
220
221 fn finish(&mut self) -> ArrayRef {
222 self.finish_into_decimal().into_array()
223 }
224
225 fn finish_into_canonical(&mut self, _ctx: &mut ExecutionCtx) -> Canonical {
226 Canonical::Decimal(self.finish_into_decimal())
227 }
228}
229
230impl DecimalBuffer {
231 fn push<V: NativeDecimalType>(&mut self, value: V) {
232 delegate_fn!(self, |T, buffer| {
233 buffer.push(
234 <T as BigCast>::from(value)
235 .ok_or_else(|| {
236 vortex_err!(
237 "decimal conversion failure {:?}, type: {:?} to {:?}",
238 value,
239 V::DECIMAL_TYPE,
240 T::DECIMAL_TYPE,
241 )
242 })
243 .vortex_expect("operation should succeed in builder"),
244 )
245 });
246 }
247
248 fn push_n<V: NativeDecimalType>(&mut self, value: V, n: usize) {
249 delegate_fn!(self, |T, buffer| {
250 buffer.push_n(
251 <T as BigCast>::from(value).vortex_expect("decimal conversion failure"),
252 n,
253 )
254 });
255 }
256
257 fn reserve(&mut self, additional: usize) {
258 delegate_fn!(self, |T, buffer| { buffer.reserve(additional) })
259 }
260
261 fn len(&self) -> usize {
262 delegate_fn!(self, |T, buffer| { buffer.len() })
263 }
264
265 pub fn extend<I, V: NativeDecimalType>(&mut self, iter: I)
266 where
267 I: Iterator<Item = V>,
268 {
269 delegate_fn!(self, |T, buffer| {
270 buffer.extend(
271 iter.map(|x| <T as BigCast>::from(x).vortex_expect("decimal conversion failure")),
272 )
273 })
274 }
275}
276
277macro_rules! impl_from_buffer {
278 ($T:ty, $variant:ident) => {
279 impl From<BufferMut<$T>> for DecimalBuffer {
280 fn from(buffer: BufferMut<$T>) -> Self {
281 Self::$variant(buffer)
282 }
283 }
284 };
285}
286
287impl_from_buffer!(i8, I8);
288impl_from_buffer!(i16, I16);
289impl_from_buffer!(i32, I32);
290impl_from_buffer!(i64, I64);
291impl_from_buffer!(i128, I128);
292impl_from_buffer!(i256, I256);
293
294impl Default for DecimalBuffer {
295 fn default() -> Self {
296 Self::I8(BufferMut::<i8>::empty())
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use crate::VortexSessionExecute;
303 use crate::array_session;
304 use crate::assert_arrays_eq;
305 use crate::builders::ArrayBuilder;
306 use crate::builders::DecimalBuilder;
307 use crate::builders::decimal::DecimalArray;
308 use crate::dtype::DecimalDType;
309
310 #[test]
311 fn test_mixed_extend() {
312 let values = 42i8;
313
314 let mut i8s = DecimalBuilder::new::<i8>(DecimalDType::new(2, 1), false.into());
315 for v in 0..values {
316 i8s.append_value(v);
317 }
318 let i8s = i8s.finish();
319
320 let mut i128s = DecimalBuilder::new::<i128>(DecimalDType::new(2, 1), false.into());
321 i8s.append_to_builder(&mut i128s, &mut array_session().create_execution_ctx())
322 .unwrap();
323 let i128s = i128s.finish();
324
325 for i in 0..i8s.len() {
326 assert_eq!(
327 i8s.execute_scalar(i, &mut array_session().create_execution_ctx())
328 .unwrap(),
329 i128s
330 .execute_scalar(i, &mut array_session().create_execution_ctx())
331 .unwrap()
332 );
333 }
334 }
335
336 #[test]
337 fn test_append_scalar() {
338 let mut ctx = array_session().create_execution_ctx();
339 use crate::scalar::Scalar;
340
341 let mut builder = DecimalBuilder::new::<i64>(DecimalDType::new(10, 2), true.into());
343 builder.append_value(1234i64);
344 builder.append_value(5678i64);
345 builder.append_null();
346
347 let array = builder.finish();
348 let expected = DecimalArray::from_option_iter(
349 [Some(1234i64), Some(5678), None],
350 DecimalDType::new(10, 2),
351 );
352 assert_arrays_eq!(&array, &expected, &mut ctx);
353
354 let mut builder2 = DecimalBuilder::new::<i64>(DecimalDType::new(10, 2), true.into());
356 for i in 0..array.len() {
357 let scalar = array
358 .execute_scalar(i, &mut array_session().create_execution_ctx())
359 .unwrap();
360 builder2.append_scalar(&scalar).unwrap();
361 }
362
363 let array2 = builder2.finish();
364 assert_arrays_eq!(&array2, &array, &mut ctx);
365
366 let mut builder = DecimalBuilder::new::<i64>(DecimalDType::new(10, 2), false.into());
368 let wrong_scalar = Scalar::from(true);
369 assert!(builder.append_scalar(&wrong_scalar).is_err());
370 }
371}