Skip to main content

arrow_array/builder/
primitive_builder.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::builder::ArrayBuilder;
19use crate::types::*;
20use crate::{Array, ArrayRef, PrimitiveArray};
21use arrow_buffer::{Buffer, MutableBuffer, NullBufferBuilder, ScalarBuffer};
22use arrow_data::ArrayData;
23use arrow_schema::{ArrowError, DataType};
24use std::any::Any;
25use std::sync::Arc;
26
27/// A signed 8-bit integer array builder.
28pub type Int8Builder = PrimitiveBuilder<Int8Type>;
29/// A signed 16-bit integer array builder.
30pub type Int16Builder = PrimitiveBuilder<Int16Type>;
31/// A signed 32-bit integer array builder.
32pub type Int32Builder = PrimitiveBuilder<Int32Type>;
33/// A signed 64-bit integer array builder.
34pub type Int64Builder = PrimitiveBuilder<Int64Type>;
35/// An usigned 8-bit integer array builder.
36pub type UInt8Builder = PrimitiveBuilder<UInt8Type>;
37/// An usigned 16-bit integer array builder.
38pub type UInt16Builder = PrimitiveBuilder<UInt16Type>;
39/// An usigned 32-bit integer array builder.
40pub type UInt32Builder = PrimitiveBuilder<UInt32Type>;
41/// An usigned 64-bit integer array builder.
42pub type UInt64Builder = PrimitiveBuilder<UInt64Type>;
43/// A 16-bit floating point array builder.
44pub type Float16Builder = PrimitiveBuilder<Float16Type>;
45/// A 32-bit floating point array builder.
46pub type Float32Builder = PrimitiveBuilder<Float32Type>;
47/// A 64-bit floating point array builder.
48pub type Float64Builder = PrimitiveBuilder<Float64Type>;
49
50/// A timestamp second array builder.
51pub type TimestampSecondBuilder = PrimitiveBuilder<TimestampSecondType>;
52/// A timestamp millisecond array builder.
53pub type TimestampMillisecondBuilder = PrimitiveBuilder<TimestampMillisecondType>;
54/// A timestamp microsecond array builder.
55pub type TimestampMicrosecondBuilder = PrimitiveBuilder<TimestampMicrosecondType>;
56/// A timestamp nanosecond array builder.
57pub type TimestampNanosecondBuilder = PrimitiveBuilder<TimestampNanosecondType>;
58
59/// A 32-bit date array builder.
60pub type Date32Builder = PrimitiveBuilder<Date32Type>;
61/// A 64-bit date array builder.
62pub type Date64Builder = PrimitiveBuilder<Date64Type>;
63
64/// A 32-bit elaspsed time in seconds array builder.
65pub type Time32SecondBuilder = PrimitiveBuilder<Time32SecondType>;
66/// A 32-bit elaspsed time in milliseconds array builder.
67pub type Time32MillisecondBuilder = PrimitiveBuilder<Time32MillisecondType>;
68/// A 64-bit elaspsed time in microseconds array builder.
69pub type Time64MicrosecondBuilder = PrimitiveBuilder<Time64MicrosecondType>;
70/// A 64-bit elaspsed time in nanoseconds array builder.
71pub type Time64NanosecondBuilder = PrimitiveBuilder<Time64NanosecondType>;
72
73/// A “calendar” interval in months array builder.
74pub type IntervalYearMonthBuilder = PrimitiveBuilder<IntervalYearMonthType>;
75/// A “calendar” interval in days and milliseconds array builder.
76pub type IntervalDayTimeBuilder = PrimitiveBuilder<IntervalDayTimeType>;
77/// A “calendar” interval in months, days, and nanoseconds array builder.
78pub type IntervalMonthDayNanoBuilder = PrimitiveBuilder<IntervalMonthDayNanoType>;
79
80/// An elapsed time in seconds array builder.
81pub type DurationSecondBuilder = PrimitiveBuilder<DurationSecondType>;
82/// An elapsed time in milliseconds array builder.
83pub type DurationMillisecondBuilder = PrimitiveBuilder<DurationMillisecondType>;
84/// An elapsed time in microseconds array builder.
85pub type DurationMicrosecondBuilder = PrimitiveBuilder<DurationMicrosecondType>;
86/// An elapsed time in nanoseconds array builder.
87pub type DurationNanosecondBuilder = PrimitiveBuilder<DurationNanosecondType>;
88
89/// A decimal 32 array builder
90pub type Decimal32Builder = PrimitiveBuilder<Decimal32Type>;
91/// A decimal 64 array builder
92pub type Decimal64Builder = PrimitiveBuilder<Decimal64Type>;
93/// A decimal 128 array builder
94pub type Decimal128Builder = PrimitiveBuilder<Decimal128Type>;
95/// A decimal 256 array builder
96pub type Decimal256Builder = PrimitiveBuilder<Decimal256Type>;
97
98/// Builder for [`PrimitiveArray`]
99#[derive(Debug)]
100pub struct PrimitiveBuilder<T: ArrowPrimitiveType> {
101    values_builder: Vec<T::Native>,
102    null_buffer_builder: NullBufferBuilder,
103    data_type: DataType,
104}
105
106impl<T: ArrowPrimitiveType> ArrayBuilder for PrimitiveBuilder<T> {
107    /// Returns the builder as a non-mutable `Any` reference.
108    fn as_any(&self) -> &dyn Any {
109        self
110    }
111
112    /// Returns the builder as a mutable `Any` reference.
113    fn as_any_mut(&mut self) -> &mut dyn Any {
114        self
115    }
116
117    /// Returns the boxed builder as a box of `Any`.
118    fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
119        self
120    }
121
122    /// Returns the number of array slots in the builder
123    fn len(&self) -> usize {
124        self.values_builder.len()
125    }
126
127    /// Builds the array and reset this builder.
128    fn finish(&mut self) -> ArrayRef {
129        Arc::new(self.finish())
130    }
131
132    /// Builds the array without resetting the builder.
133    fn finish_cloned(&self) -> ArrayRef {
134        Arc::new(self.finish_cloned())
135    }
136}
137
138impl<T: ArrowPrimitiveType> Default for PrimitiveBuilder<T> {
139    fn default() -> Self {
140        Self::new()
141    }
142}
143
144impl<T: ArrowPrimitiveType> PrimitiveBuilder<T> {
145    /// Creates a new primitive array builder
146    pub fn new() -> Self {
147        Self::with_capacity(1024)
148    }
149
150    /// Creates a new primitive array builder with capacity no of items
151    pub fn with_capacity(capacity: usize) -> Self {
152        Self {
153            values_builder: Vec::with_capacity(capacity),
154            null_buffer_builder: NullBufferBuilder::new(capacity),
155            data_type: T::DATA_TYPE,
156        }
157    }
158
159    /// Creates a new primitive array builder from buffers
160    pub fn new_from_buffer(
161        values_buffer: MutableBuffer,
162        null_buffer: Option<MutableBuffer>,
163    ) -> Self {
164        let values_builder: Vec<T::Native> = ScalarBuffer::<T::Native>::from(values_buffer).into();
165
166        let null_buffer_builder = null_buffer
167            .map(|buffer| NullBufferBuilder::new_from_buffer(buffer, values_builder.len()))
168            .unwrap_or_else(|| NullBufferBuilder::new_with_len(values_builder.len()));
169
170        Self {
171            values_builder,
172            null_buffer_builder,
173            data_type: T::DATA_TYPE,
174        }
175    }
176
177    /// By default [`PrimitiveBuilder`] uses [`ArrowPrimitiveType::DATA_TYPE`] as the
178    /// data type of the generated array.
179    ///
180    /// This method allows overriding the data type, to allow specifying timezones
181    /// for [`DataType::Timestamp`] or precision and scale for [`DataType::Decimal32`],
182    /// [`DataType::Decimal64`], [`DataType::Decimal128`] and [`DataType::Decimal256`]
183    ///
184    /// # Panics
185    ///
186    /// This method panics if `data_type` is not [PrimitiveArray::is_compatible]
187    pub fn with_data_type(self, data_type: DataType) -> Self {
188        assert!(
189            PrimitiveArray::<T>::is_compatible(&data_type),
190            "incompatible data type for builder, expected {} got {}",
191            T::DATA_TYPE,
192            data_type
193        );
194        Self { data_type, ..self }
195    }
196
197    /// Returns the capacity of this builder measured in slots of type `T`
198    pub fn capacity(&self) -> usize {
199        self.values_builder.capacity()
200    }
201
202    /// Appends a value of type `T` into the builder
203    #[inline]
204    pub fn append_value(&mut self, v: T::Native) {
205        self.null_buffer_builder.append_non_null();
206        self.values_builder.push(v);
207    }
208
209    /// Appends a value of type `T` into the builder `n` times
210    #[inline]
211    pub fn append_value_n(&mut self, v: T::Native, n: usize) {
212        self.null_buffer_builder.append_n_non_nulls(n);
213        self.values_builder.extend(std::iter::repeat_n(v, n));
214    }
215
216    /// Appends a null slot into the builder
217    #[inline]
218    pub fn append_null(&mut self) {
219        self.null_buffer_builder.append_null();
220        self.values_builder.push(T::Native::default());
221    }
222
223    /// Appends `n` no. of null's into the builder
224    #[inline]
225    pub fn append_nulls(&mut self, n: usize) {
226        self.null_buffer_builder.append_n_nulls(n);
227        self.values_builder
228            .extend(std::iter::repeat_n(T::Native::default(), n));
229    }
230
231    /// Appends an `Option<T>` into the builder
232    #[inline]
233    pub fn append_option(&mut self, v: Option<T::Native>) {
234        match v {
235            None => self.append_null(),
236            Some(v) => self.append_value(v),
237        };
238    }
239
240    /// Appends a slice of type `T` into the builder
241    #[inline]
242    pub fn append_slice(&mut self, v: &[T::Native]) {
243        self.null_buffer_builder.append_n_non_nulls(v.len());
244        self.values_builder.extend_from_slice(v);
245    }
246
247    /// Appends values from a slice of type `T` and a validity boolean slice
248    ///
249    /// # Panics
250    ///
251    /// Panics if `values` and `is_valid` have different lengths
252    #[inline]
253    pub fn append_values(&mut self, values: &[T::Native], is_valid: &[bool]) {
254        assert_eq!(
255            values.len(),
256            is_valid.len(),
257            "Value and validity lengths must be equal"
258        );
259        self.null_buffer_builder.append_slice(is_valid);
260        self.values_builder.extend_from_slice(values);
261    }
262
263    /// Appends values from a iter of type `Option<T>`
264    ///
265    /// # Panics
266    ///
267    /// Panics if `values` and `is_valid` have different lengths
268    #[inline]
269    pub fn extend_from_iter_option<I: IntoIterator<Item = Option<T::Native>>>(&mut self, iter: I) {
270        let iter = iter.into_iter();
271        self.values_builder.extend(iter.map(|v| match v {
272            Some(v) => {
273                self.null_buffer_builder.append_non_null();
274                v
275            }
276            None => {
277                self.null_buffer_builder.append_null();
278                T::Native::default()
279            }
280        }));
281    }
282
283    /// Appends array values and null to this builder as is
284    /// (this means that underlying null values are copied as is).
285    ///
286    /// # Panics
287    ///
288    /// Panics if `array` and `self` data types are different
289    #[inline]
290    pub fn append_array(&mut self, array: &PrimitiveArray<T>) {
291        assert_eq!(
292            &self.data_type,
293            array.data_type(),
294            "array data type mismatch"
295        );
296
297        self.values_builder.extend_from_slice(array.values());
298        if let Some(null_buffer) = array.nulls() {
299            self.null_buffer_builder.append_buffer(null_buffer);
300        } else {
301            self.null_buffer_builder.append_n_non_nulls(array.len());
302        }
303    }
304
305    /// Appends values from a trusted length iterator.
306    ///
307    /// # Safety
308    /// This requires the iterator be a trusted length. This could instead require
309    /// the iterator implement `TrustedLen` once that is stabilized.
310    #[inline]
311    pub unsafe fn append_trusted_len_iter(&mut self, iter: impl IntoIterator<Item = T::Native>) {
312        let iter = iter.into_iter();
313        let len = iter
314            .size_hint()
315            .1
316            .expect("append_trusted_len_iter requires an upper bound");
317
318        self.null_buffer_builder.append_n_non_nulls(len);
319        self.values_builder.extend(iter);
320    }
321
322    /// Builds the [`PrimitiveArray`] and reset this builder.
323    pub fn finish(&mut self) -> PrimitiveArray<T> {
324        let len = self.len();
325        let nulls = self.null_buffer_builder.finish();
326        let builder = ArrayData::builder(self.data_type.clone())
327            .len(len)
328            .add_buffer(std::mem::take(&mut self.values_builder).into())
329            .nulls(nulls);
330
331        let array_data = unsafe { builder.build_unchecked() };
332        PrimitiveArray::<T>::from(array_data)
333    }
334
335    /// Builds the [`PrimitiveArray`] without resetting the builder.
336    pub fn finish_cloned(&self) -> PrimitiveArray<T> {
337        let len = self.len();
338        let nulls = self.null_buffer_builder.finish_cloned();
339        let values_buffer = Buffer::from_slice_ref(self.values_builder.as_slice());
340        let builder = ArrayData::builder(self.data_type.clone())
341            .len(len)
342            .add_buffer(values_buffer)
343            .nulls(nulls);
344
345        let array_data = unsafe { builder.build_unchecked() };
346        PrimitiveArray::<T>::from(array_data)
347    }
348
349    /// Returns the current values buffer as a slice
350    pub fn values_slice(&self) -> &[T::Native] {
351        self.values_builder.as_slice()
352    }
353
354    /// Returns the current values buffer as a mutable slice
355    pub fn values_slice_mut(&mut self) -> &mut [T::Native] {
356        self.values_builder.as_mut_slice()
357    }
358
359    /// Returns the current null buffer as a slice
360    pub fn validity_slice(&self) -> Option<&[u8]> {
361        self.null_buffer_builder.as_slice()
362    }
363
364    /// Returns the current null buffer allocated capacity, in bytes.
365    pub fn validity_capacity(&self) -> usize {
366        self.null_buffer_builder.allocated_size()
367    }
368
369    /// Returns the current null buffer as a mutable slice
370    pub fn validity_slice_mut(&mut self) -> Option<&mut [u8]> {
371        self.null_buffer_builder.as_slice_mut()
372    }
373
374    /// Returns the current values buffer and null buffer as a slice
375    pub fn slices_mut(&mut self) -> (&mut [T::Native], Option<&mut [u8]>) {
376        (
377            self.values_builder.as_mut_slice(),
378            self.null_buffer_builder.as_slice_mut(),
379        )
380    }
381}
382
383impl<P: DecimalType> PrimitiveBuilder<P> {
384    /// Sets the precision and scale
385    pub fn with_precision_and_scale(self, precision: u8, scale: i8) -> Result<Self, ArrowError> {
386        validate_decimal_precision_and_scale::<P>(precision, scale)?;
387        Ok(Self {
388            data_type: P::TYPE_CONSTRUCTOR(precision, scale),
389            ..self
390        })
391    }
392}
393
394impl<P: ArrowTimestampType> PrimitiveBuilder<P> {
395    /// Sets the timezone
396    pub fn with_timezone(self, timezone: impl Into<Arc<str>>) -> Self {
397        self.with_timezone_opt(Some(timezone.into()))
398    }
399
400    /// Sets an optional timezone
401    pub fn with_timezone_opt<S: Into<Arc<str>>>(self, timezone: Option<S>) -> Self {
402        Self {
403            data_type: DataType::Timestamp(P::UNIT, timezone.map(Into::into)),
404            ..self
405        }
406    }
407}
408
409impl<P: ArrowPrimitiveType> Extend<Option<P::Native>> for PrimitiveBuilder<P> {
410    #[inline]
411    fn extend<T: IntoIterator<Item = Option<P::Native>>>(&mut self, iter: T) {
412        for v in iter {
413            self.append_option(v)
414        }
415    }
416}
417
418#[cfg(test)]
419mod tests {
420    use super::*;
421    use arrow_buffer::{NullBuffer, ScalarBuffer};
422    use arrow_schema::TimeUnit;
423
424    use crate::array::Array;
425    use crate::array::BooleanArray;
426    use crate::array::Date32Array;
427    use crate::array::Int32Array;
428    use crate::array::TimestampSecondArray;
429
430    #[test]
431    fn test_primitive_array_builder_i32() {
432        let mut builder = Int32Array::builder(5);
433        for i in 0..5 {
434            builder.append_value(i);
435        }
436        let arr = builder.finish();
437        assert_eq!(5, arr.len());
438        assert_eq!(0, arr.offset());
439        assert_eq!(0, arr.null_count());
440        for i in 0..5 {
441            assert!(!arr.is_null(i));
442            assert!(arr.is_valid(i));
443            assert_eq!(i as i32, arr.value(i));
444        }
445    }
446
447    #[test]
448    fn test_primitive_array_builder_i32_append_iter() {
449        let mut builder = Int32Array::builder(5);
450        unsafe { builder.append_trusted_len_iter(0..5) };
451        let arr = builder.finish();
452        assert_eq!(5, arr.len());
453        assert_eq!(0, arr.offset());
454        assert_eq!(0, arr.null_count());
455        for i in 0..5 {
456            assert!(!arr.is_null(i));
457            assert!(arr.is_valid(i));
458            assert_eq!(i as i32, arr.value(i));
459        }
460    }
461
462    #[test]
463    fn test_primitive_array_builder_i32_append_nulls() {
464        let mut builder = Int32Array::builder(5);
465        builder.append_nulls(5);
466        let arr = builder.finish();
467        assert_eq!(5, arr.len());
468        assert_eq!(0, arr.offset());
469        assert_eq!(5, arr.null_count());
470        for i in 0..5 {
471            assert!(arr.is_null(i));
472            assert!(!arr.is_valid(i));
473        }
474    }
475
476    #[test]
477    fn test_primitive_array_builder_date32() {
478        let mut builder = Date32Array::builder(5);
479        for i in 0..5 {
480            builder.append_value(i);
481        }
482        let arr = builder.finish();
483        assert_eq!(5, arr.len());
484        assert_eq!(0, arr.offset());
485        assert_eq!(0, arr.null_count());
486        for i in 0..5 {
487            assert!(!arr.is_null(i));
488            assert!(arr.is_valid(i));
489            assert_eq!(i as i32, arr.value(i));
490        }
491    }
492
493    #[test]
494    fn test_primitive_array_builder_timestamp_second() {
495        let mut builder = TimestampSecondArray::builder(5);
496        for i in 0..5 {
497            builder.append_value(i);
498        }
499        let arr = builder.finish();
500        assert_eq!(5, arr.len());
501        assert_eq!(0, arr.offset());
502        assert_eq!(0, arr.null_count());
503        for i in 0..5 {
504            assert!(!arr.is_null(i));
505            assert!(arr.is_valid(i));
506            assert_eq!(i as i64, arr.value(i));
507        }
508    }
509
510    #[test]
511    fn test_primitive_array_builder_bool() {
512        // 00000010 01001000
513        let buf = Buffer::from([72_u8, 2_u8]);
514        let mut builder = BooleanArray::builder(10);
515        for i in 0..10 {
516            if i == 3 || i == 6 || i == 9 {
517                builder.append_value(true);
518            } else {
519                builder.append_value(false);
520            }
521        }
522
523        let arr = builder.finish();
524        assert_eq!(&buf, arr.values().inner());
525        assert_eq!(10, arr.len());
526        assert_eq!(0, arr.offset());
527        assert_eq!(0, arr.null_count());
528        for i in 0..10 {
529            assert!(!arr.is_null(i));
530            assert!(arr.is_valid(i));
531            assert_eq!(i == 3 || i == 6 || i == 9, arr.value(i), "failed at {i}")
532        }
533    }
534
535    #[test]
536    fn test_primitive_array_builder_append_option() {
537        let arr1 = Int32Array::from(vec![Some(0), None, Some(2), None, Some(4)]);
538
539        let mut builder = Int32Array::builder(5);
540        builder.append_option(Some(0));
541        builder.append_option(None);
542        builder.append_option(Some(2));
543        builder.append_option(None);
544        builder.append_option(Some(4));
545        let arr2 = builder.finish();
546
547        assert_eq!(arr1.len(), arr2.len());
548        assert_eq!(arr1.offset(), arr2.offset());
549        assert_eq!(arr1.null_count(), arr2.null_count());
550        for i in 0..5 {
551            assert_eq!(arr1.is_null(i), arr2.is_null(i));
552            assert_eq!(arr1.is_valid(i), arr2.is_valid(i));
553            if arr1.is_valid(i) {
554                assert_eq!(arr1.value(i), arr2.value(i));
555            }
556        }
557    }
558
559    #[test]
560    fn test_primitive_array_builder_append_null() {
561        let arr1 = Int32Array::from(vec![Some(0), Some(2), None, None, Some(4)]);
562
563        let mut builder = Int32Array::builder(5);
564        builder.append_value(0);
565        builder.append_value(2);
566        builder.append_null();
567        builder.append_null();
568        builder.append_value(4);
569        let arr2 = builder.finish();
570
571        assert_eq!(arr1.len(), arr2.len());
572        assert_eq!(arr1.offset(), arr2.offset());
573        assert_eq!(arr1.null_count(), arr2.null_count());
574        for i in 0..5 {
575            assert_eq!(arr1.is_null(i), arr2.is_null(i));
576            assert_eq!(arr1.is_valid(i), arr2.is_valid(i));
577            if arr1.is_valid(i) {
578                assert_eq!(arr1.value(i), arr2.value(i));
579            }
580        }
581    }
582
583    #[test]
584    fn test_primitive_array_builder_append_slice() {
585        let arr1 = Int32Array::from(vec![Some(0), Some(2), None, None, Some(4)]);
586
587        let mut builder = Int32Array::builder(5);
588        builder.append_slice(&[0, 2]);
589        builder.append_null();
590        builder.append_null();
591        builder.append_value(4);
592        let arr2 = builder.finish();
593
594        assert_eq!(arr1.len(), arr2.len());
595        assert_eq!(arr1.offset(), arr2.offset());
596        assert_eq!(arr1.null_count(), arr2.null_count());
597        for i in 0..5 {
598            assert_eq!(arr1.is_null(i), arr2.is_null(i));
599            assert_eq!(arr1.is_valid(i), arr2.is_valid(i));
600            if arr1.is_valid(i) {
601                assert_eq!(arr1.value(i), arr2.value(i));
602            }
603        }
604    }
605
606    #[test]
607    fn test_primitive_array_builder_finish() {
608        let mut builder = Int32Builder::new();
609        builder.append_slice(&[2, 4, 6, 8]);
610        let mut arr = builder.finish();
611        assert_eq!(4, arr.len());
612        assert_eq!(0, builder.len());
613
614        builder.append_slice(&[1, 3, 5, 7, 9]);
615        arr = builder.finish();
616        assert_eq!(5, arr.len());
617        assert_eq!(0, builder.len());
618    }
619
620    #[test]
621    fn test_primitive_array_builder_finish_cloned() {
622        let mut builder = Int32Builder::new();
623        builder.append_value(23);
624        builder.append_value(45);
625        let result = builder.finish_cloned();
626        assert_eq!(result, Int32Array::from(vec![23, 45]));
627        builder.append_value(56);
628        assert_eq!(builder.finish_cloned(), Int32Array::from(vec![23, 45, 56]));
629
630        builder.append_slice(&[2, 4, 6, 8]);
631        let mut arr = builder.finish();
632        assert_eq!(7, arr.len());
633        assert_eq!(arr, Int32Array::from(vec![23, 45, 56, 2, 4, 6, 8]));
634        assert_eq!(0, builder.len());
635
636        builder.append_slice(&[1, 3, 5, 7, 9]);
637        arr = builder.finish();
638        assert_eq!(5, arr.len());
639        assert_eq!(0, builder.len());
640    }
641
642    #[test]
643    fn test_primitive_array_builder_with_data_type() {
644        let mut builder = Decimal128Builder::new().with_data_type(DataType::Decimal128(1, 2));
645        builder.append_value(1);
646        let array = builder.finish();
647        assert_eq!(array.precision(), 1);
648        assert_eq!(array.scale(), 2);
649
650        let data_type = DataType::Timestamp(TimeUnit::Nanosecond, Some("+00:00".into()));
651        let mut builder = TimestampNanosecondBuilder::new().with_data_type(data_type.clone());
652        builder.append_value(1);
653        let array = builder.finish();
654        assert_eq!(array.data_type(), &data_type);
655    }
656
657    #[test]
658    #[should_panic(expected = "incompatible data type for builder, expected Int32 got Int64")]
659    fn test_invalid_with_data_type() {
660        Int32Builder::new().with_data_type(DataType::Int64);
661    }
662
663    #[test]
664    fn test_extend() {
665        let mut builder = PrimitiveBuilder::<Int16Type>::new();
666        builder.extend([1, 2, 3, 5, 2, 4, 4].into_iter().map(Some));
667        builder.extend([2, 4, 6, 2].into_iter().map(Some));
668        let array = builder.finish();
669        assert_eq!(array.values(), &[1, 2, 3, 5, 2, 4, 4, 2, 4, 6, 2]);
670    }
671
672    #[test]
673    fn test_primitive_array_append_array() {
674        let input = vec![
675            Some(1),
676            None,
677            Some(3),
678            None,
679            Some(5),
680            None,
681            None,
682            None,
683            Some(7),
684            Some(9),
685            Some(8),
686            Some(6),
687            Some(4),
688        ];
689        let arr1 = Int32Array::from(input[..5].to_vec());
690        let arr2 = Int32Array::from(input[5..8].to_vec());
691        let arr3 = Int32Array::from(input[8..].to_vec());
692
693        let mut builder = Int32Array::builder(5);
694        builder.append_array(&arr1);
695        builder.append_array(&arr2);
696        builder.append_array(&arr3);
697        let actual = builder.finish();
698        let expected = Int32Array::from(input);
699
700        assert_eq!(actual, expected);
701    }
702
703    #[test]
704    fn test_append_array_add_underlying_null_values() {
705        let array = Int32Array::new(
706            ScalarBuffer::from(vec![2, 3, 4, 5]),
707            Some(NullBuffer::from(&[true, true, false, false])),
708        );
709
710        let mut builder = Int32Array::builder(5);
711        builder.append_array(&array);
712        let actual = builder.finish();
713
714        assert_eq!(actual, array);
715        assert_eq!(actual.values(), array.values())
716    }
717
718    #[test]
719    #[should_panic(expected = "array data type mismatch")]
720    fn test_invalid_with_data_type_in_append_array() {
721        let array = {
722            let mut builder = Decimal128Builder::new().with_data_type(DataType::Decimal128(1, 2));
723            builder.append_value(1);
724            builder.finish()
725        };
726
727        let mut builder = Decimal128Builder::new().with_data_type(DataType::Decimal128(2, 3));
728        builder.append_array(&array)
729    }
730}