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