You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2023/06/12 11:39:46 UTC

[arrow-rs] branch master updated: Add PrimitiveBuilder type constructors (#4401)

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 c1283f180 Add PrimitiveBuilder type constructors (#4401)
c1283f180 is described below

commit c1283f1805f1691b10d9505dedb745687946eb1c
Author: Raphael Taylor-Davies <17...@users.noreply.github.com>
AuthorDate: Mon Jun 12 12:39:41 2023 +0100

    Add PrimitiveBuilder type constructors (#4401)
---
 arrow-array/src/array/primitive_array.rs     | 51 ++--------------------------
 arrow-array/src/builder/primitive_builder.rs | 32 ++++++++++++++++-
 arrow-array/src/types.rs                     | 40 ++++++++++++++++++++++
 3 files changed, 74 insertions(+), 49 deletions(-)

diff --git a/arrow-array/src/array/primitive_array.rs b/arrow-array/src/array/primitive_array.rs
index b821ad1b4..576f645b0 100644
--- a/arrow-array/src/array/primitive_array.rs
+++ b/arrow-array/src/array/primitive_array.rs
@@ -1388,64 +1388,19 @@ impl<T: DecimalType + ArrowPrimitiveType> PrimitiveArray<T> {
     /// Returns a Decimal array with the same data as self, with the
     /// specified precision and scale.
     ///
-    /// Returns an Error if:
-    /// - `precision` is zero
-    /// - `precision` is larger than `T:MAX_PRECISION`
-    /// - `scale` is larger than `T::MAX_SCALE`
-    /// - `scale` is > `precision`
+    /// See [`validate_decimal_precision_and_scale`]
     pub fn with_precision_and_scale(
         self,
         precision: u8,
         scale: i8,
-    ) -> Result<Self, ArrowError>
-    where
-        Self: Sized,
-    {
-        // validate precision and scale
-        self.validate_precision_scale(precision, scale)?;
-
-        // safety: self.data is valid DataType::Decimal as checked above
+    ) -> Result<Self, ArrowError> {
+        validate_decimal_precision_and_scale::<T>(precision, scale)?;
         Ok(Self {
             data_type: T::TYPE_CONSTRUCTOR(precision, scale),
             ..self
         })
     }
 
-    // validate that the new precision and scale are valid or not
-    fn validate_precision_scale(
-        &self,
-        precision: u8,
-        scale: i8,
-    ) -> Result<(), ArrowError> {
-        if precision == 0 {
-            return Err(ArrowError::InvalidArgumentError(format!(
-                "precision cannot be 0, has to be between [1, {}]",
-                T::MAX_PRECISION
-            )));
-        }
-        if precision > T::MAX_PRECISION {
-            return Err(ArrowError::InvalidArgumentError(format!(
-                "precision {} is greater than max {}",
-                precision,
-                T::MAX_PRECISION
-            )));
-        }
-        if scale > T::MAX_SCALE {
-            return Err(ArrowError::InvalidArgumentError(format!(
-                "scale {} is greater than max {}",
-                scale,
-                T::MAX_SCALE
-            )));
-        }
-        if scale > 0 && scale as u8 > precision {
-            return Err(ArrowError::InvalidArgumentError(format!(
-                "scale {scale} is greater than precision {precision}"
-            )));
-        }
-
-        Ok(())
-    }
-
     /// Validates values in this array can be properly interpreted
     /// with the specified precision.
     pub fn validate_decimal_precision(&self, precision: u8) -> Result<(), ArrowError> {
diff --git a/arrow-array/src/builder/primitive_builder.rs b/arrow-array/src/builder/primitive_builder.rs
index f064519e4..3e31b1d05 100644
--- a/arrow-array/src/builder/primitive_builder.rs
+++ b/arrow-array/src/builder/primitive_builder.rs
@@ -21,7 +21,7 @@ use crate::{ArrayRef, ArrowPrimitiveType, PrimitiveArray};
 use arrow_buffer::NullBufferBuilder;
 use arrow_buffer::{Buffer, MutableBuffer};
 use arrow_data::ArrayData;
-use arrow_schema::DataType;
+use arrow_schema::{ArrowError, DataType};
 use std::any::Any;
 use std::sync::Arc;
 
@@ -331,6 +331,36 @@ impl<T: ArrowPrimitiveType> PrimitiveBuilder<T> {
     }
 }
 
+impl<P: DecimalType> PrimitiveBuilder<P> {
+    /// Sets the precision and scale
+    pub fn with_precision_and_scale(
+        self,
+        precision: u8,
+        scale: i8,
+    ) -> Result<Self, ArrowError> {
+        validate_decimal_precision_and_scale::<P>(precision, scale)?;
+        Ok(Self {
+            data_type: P::TYPE_CONSTRUCTOR(precision, scale),
+            ..self
+        })
+    }
+}
+
+impl<P: ArrowTimestampType> PrimitiveBuilder<P> {
+    /// Sets the timezone
+    pub fn with_timezone(self, timezone: impl Into<Arc<str>>) -> Self {
+        self.with_timezone_opt(Some(timezone.into()))
+    }
+
+    /// Sets an optional timezone
+    pub fn with_timezone_opt<S: Into<Arc<str>>>(self, timezone: Option<S>) -> Self {
+        Self {
+            data_type: DataType::Timestamp(P::UNIT, timezone.map(Into::into)),
+            ..self
+        }
+    }
+}
+
 impl<P: ArrowPrimitiveType> Extend<Option<P::Native>> for PrimitiveBuilder<P> {
     #[inline]
     fn extend<T: IntoIterator<Item = Option<P::Native>>>(&mut self, iter: T) {
diff --git a/arrow-array/src/types.rs b/arrow-array/src/types.rs
index 8c19301dc..f99e6a8f6 100644
--- a/arrow-array/src/types.rs
+++ b/arrow-array/src/types.rs
@@ -1403,6 +1403,46 @@ pub trait DecimalType:
     ) -> Result<(), ArrowError>;
 }
 
+/// Validate that `precision` and `scale` are valid for `T`
+///
+/// Returns an Error if:
+/// - `precision` is zero
+/// - `precision` is larger than `T:MAX_PRECISION`
+/// - `scale` is larger than `T::MAX_SCALE`
+/// - `scale` is > `precision`
+pub fn validate_decimal_precision_and_scale<T: DecimalType>(
+    precision: u8,
+    scale: i8,
+) -> Result<(), ArrowError> {
+    if precision == 0 {
+        return Err(ArrowError::InvalidArgumentError(format!(
+            "precision cannot be 0, has to be between [1, {}]",
+            T::MAX_PRECISION
+        )));
+    }
+    if precision > T::MAX_PRECISION {
+        return Err(ArrowError::InvalidArgumentError(format!(
+            "precision {} is greater than max {}",
+            precision,
+            T::MAX_PRECISION
+        )));
+    }
+    if scale > T::MAX_SCALE {
+        return Err(ArrowError::InvalidArgumentError(format!(
+            "scale {} is greater than max {}",
+            scale,
+            T::MAX_SCALE
+        )));
+    }
+    if scale > 0 && scale as u8 > precision {
+        return Err(ArrowError::InvalidArgumentError(format!(
+            "scale {scale} is greater than precision {precision}"
+        )));
+    }
+
+    Ok(())
+}
+
 /// The decimal type for a Decimal128Array
 #[derive(Debug)]
 pub struct Decimal128Type {}