This is an automated email from the ASF dual-hosted git repository.

tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new bde749ee0 Impl FromIterator for Decimal256Array (#2247)
bde749ee0 is described below

commit bde749ee02af4ca0ba023c84dea263bf2c8a5078
Author: Liang-Chi Hsieh <[email protected]>
AuthorDate: Tue Aug 2 03:18:17 2022 -0700

    Impl FromIterator for Decimal256Array (#2247)
    
    * Add FromIterator
    
    * For review
---
 arrow/src/array/array_decimal.rs | 124 ++++++++++++++++++++++++++++++++-------
 1 file changed, 103 insertions(+), 21 deletions(-)

diff --git a/arrow/src/array/array_decimal.rs b/arrow/src/array/array_decimal.rs
index cb9f799fd..5ce407b0b 100644
--- a/arrow/src/array/array_decimal.rs
+++ b/arrow/src/array/array_decimal.rs
@@ -16,6 +16,7 @@
 // under the License.
 
 use crate::array::{ArrayAccessor, Decimal128Iter, Decimal256Iter};
+use num::BigInt;
 use std::borrow::Borrow;
 use std::convert::From;
 use std::fmt;
@@ -27,8 +28,10 @@ use super::{
 use super::{BooleanBufferBuilder, FixedSizeBinaryArray};
 #[allow(deprecated)]
 pub use crate::array::DecimalIter;
-use crate::buffer::Buffer;
-use crate::datatypes::{validate_decimal_precision, DECIMAL_DEFAULT_SCALE};
+use crate::buffer::{Buffer, MutableBuffer};
+use crate::datatypes::{
+    validate_decimal_precision, DECIMAL256_MAX_PRECISION, 
DECIMAL_DEFAULT_SCALE,
+};
 use crate::datatypes::{DataType, DECIMAL128_MAX_PRECISION, 
DECIMAL128_MAX_SCALE};
 use crate::error::{ArrowError, Result};
 use crate::util::decimal::{BasicDecimal, Decimal128, Decimal256};
@@ -91,6 +94,7 @@ pub trait BasicDecimalArray<T: BasicDecimal, U: 
From<ArrayData>>:
     private_decimal::DecimalArrayPrivate
 {
     const VALUE_LENGTH: i32;
+    const DEFAULT_TYPE: DataType;
 
     fn data(&self) -> &ArrayData;
 
@@ -219,10 +223,17 @@ pub trait BasicDecimalArray<T: BasicDecimal, U: 
From<ArrayData>>:
         let array_data = unsafe { builder.build_unchecked() };
         U::from(array_data)
     }
+
+    /// The default precision and scale used when not specified.
+    fn default_type() -> DataType {
+        Self::DEFAULT_TYPE
+    }
 }
 
 impl BasicDecimalArray<Decimal128, Decimal128Array> for Decimal128Array {
     const VALUE_LENGTH: i32 = 16;
+    const DEFAULT_TYPE: DataType =
+        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
 
     fn data(&self) -> &ArrayData {
         &self.data
@@ -239,6 +250,8 @@ impl BasicDecimalArray<Decimal128, Decimal128Array> for 
Decimal128Array {
 
 impl BasicDecimalArray<Decimal256, Decimal256Array> for Decimal256Array {
     const VALUE_LENGTH: i32 = 32;
+    const DEFAULT_TYPE: DataType =
+        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
 
     fn data(&self) -> &ArrayData {
         &self.data
@@ -324,12 +337,6 @@ impl Decimal128Array {
         self.data = self.data.with_data_type(new_data_type);
         Ok(self)
     }
-
-    /// The default precision and scale used when not specified.
-    pub fn default_type() -> DataType {
-        // Keep maximum precision
-        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE)
-    }
 }
 
 impl From<ArrayData> for Decimal128Array {
@@ -384,6 +391,59 @@ impl<'a> Decimal128Array {
     }
 }
 
+impl From<BigInt> for Decimal256 {
+    fn from(bigint: BigInt) -> Self {
+        Decimal256::from_big_int(&bigint, DECIMAL256_MAX_PRECISION, 
DECIMAL_DEFAULT_SCALE)
+            .unwrap()
+    }
+}
+
+fn build_decimal_array_from<U: BasicDecimalArray<T, U>, T>(
+    null_buf: BooleanBufferBuilder,
+    buffer: Buffer,
+) -> U
+where
+    T: BasicDecimal,
+    U: From<ArrayData>,
+{
+    let data = unsafe {
+        ArrayData::new_unchecked(
+            U::default_type(),
+            null_buf.len(),
+            None,
+            Some(null_buf.into()),
+            0,
+            vec![buffer],
+            vec![],
+        )
+    };
+    U::from(data)
+}
+
+impl<Ptr: Into<Decimal256>> FromIterator<Option<Ptr>> for Decimal256Array {
+    fn from_iter<I: IntoIterator<Item = Option<Ptr>>>(iter: I) -> Self {
+        let iter = iter.into_iter();
+        let (lower, upper) = iter.size_hint();
+        let size_hint = upper.unwrap_or(lower);
+
+        let mut null_buf = BooleanBufferBuilder::new(size_hint);
+
+        let mut buffer = MutableBuffer::with_capacity(size_hint);
+
+        iter.for_each(|item| {
+            if let Some(a) = item {
+                null_buf.append(true);
+                buffer.extend_from_slice(Into::into(a).raw_value());
+            } else {
+                null_buf.append(false);
+                buffer.extend_zeros(32);
+            }
+        });
+
+        build_decimal_array_from::<Decimal256Array, _>(null_buf, buffer.into())
+    }
+}
+
 impl<Ptr: Borrow<Option<i128>>> FromIterator<Ptr> for Decimal128Array {
     fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self {
         let iter = iter.into_iter();
@@ -405,18 +465,7 @@ impl<Ptr: Borrow<Option<i128>>> FromIterator<Ptr> for 
Decimal128Array {
             })
             .collect();
 
-        let data = unsafe {
-            ArrayData::new_unchecked(
-                Self::default_type(),
-                null_buf.len(),
-                None,
-                Some(null_buf.into()),
-                0,
-                vec![buffer],
-                vec![],
-            )
-        };
-        Decimal128Array::from(data)
+        build_decimal_array_from::<Decimal128Array, _>(null_buf, buffer)
     }
 }
 
@@ -794,7 +843,6 @@ mod tests {
 
     #[test]
     fn test_decimal256_iter() {
-        // TODO: Impl FromIterator for Decimal256Array
         let mut builder = Decimal256Builder::new(30, 76, 6);
         let value = BigInt::from_str_radix("12345", 10).unwrap();
         let decimal1 = Decimal256::from_big_int(&value, 76, 6).unwrap();
@@ -811,4 +859,38 @@ mod tests {
         let collected: Vec<_> = array.iter().collect();
         assert_eq!(vec![Some(decimal1), None, Some(decimal2)], collected);
     }
+
+    #[test]
+    fn test_from_iter_decimal256array() {
+        let value1 = BigInt::from_str_radix("12345", 10).unwrap();
+        let value2 = BigInt::from_str_radix("56789", 10).unwrap();
+
+        let array: Decimal256Array =
+            vec![Some(value1.clone()), None, Some(value2.clone())]
+                .into_iter()
+                .collect();
+        assert_eq!(array.len(), 3);
+        assert_eq!(array.data_type(), &DataType::Decimal256(76, 10));
+        assert_eq!(
+            Decimal256::from_big_int(
+                &value1,
+                DECIMAL256_MAX_PRECISION,
+                DECIMAL_DEFAULT_SCALE
+            )
+            .unwrap(),
+            array.value(0)
+        );
+        assert!(!array.is_null(0));
+        assert!(array.is_null(1));
+        assert_eq!(
+            Decimal256::from_big_int(
+                &value2,
+                DECIMAL256_MAX_PRECISION,
+                DECIMAL_DEFAULT_SCALE
+            )
+            .unwrap(),
+            array.value(2)
+        );
+        assert!(!array.is_null(2));
+    }
 }

Reply via email to