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 77c814cfc Rewrite `Decimal` and `DecimalArray` using `const_generic`
(#2383)
77c814cfc is described below
commit 77c814cfc66845192c1e0be6ae8b0de6a1a0d5f0
Author: Remzi Yang <[email protected]>
AuthorDate: Tue Aug 9 18:38:46 2022 +0800
Rewrite `Decimal` and `DecimalArray` using `const_generic` (#2383)
* const generic decimal
Signed-off-by: remzi <[email protected]>
* fix docs and lint
Signed-off-by: remzi <[email protected]>
* add bound
Signed-off-by: remzi <[email protected]>
---
arrow/src/array/array_decimal.rs | 422 ++++++++++------------
arrow/src/array/builder/decimal_builder.rs | 22 +-
arrow/src/array/equal/mod.rs | 1 -
arrow/src/array/iterator.rs | 11 +-
arrow/src/array/ord.rs | 1 -
arrow/src/array/transform/mod.rs | 2 -
arrow/src/compute/kernels/cast.rs | 1 -
arrow/src/compute/kernels/sort.rs | 1 -
arrow/src/compute/kernels/take.rs | 2 -
arrow/src/csv/reader.rs | 1 -
arrow/src/ffi.rs | 1 -
arrow/src/util/decimal.rs | 229 ++++++------
arrow/src/util/display.rs | 1 -
arrow/src/util/integration_util.rs | 2 +-
arrow/src/util/pretty.rs | 2 +-
parquet/src/arrow/array_reader/primitive_array.rs | 2 +-
parquet/src/arrow/arrow_writer/mod.rs | 1 -
parquet/src/arrow/buffer/converter.rs | 6 +-
18 files changed, 324 insertions(+), 384 deletions(-)
diff --git a/arrow/src/array/array_decimal.rs b/arrow/src/array/array_decimal.rs
index 9d7644bef..781ed5f8f 100644
--- a/arrow/src/array/array_decimal.rs
+++ b/arrow/src/array/array_decimal.rs
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-use crate::array::{ArrayAccessor, Decimal128Iter, Decimal256Iter};
+use crate::array::ArrayAccessor;
use num::BigInt;
use std::borrow::Borrow;
use std::convert::From;
@@ -25,17 +25,17 @@ use std::{any::Any, iter::FromIterator};
use super::{
array::print_long_array, raw_pointer::RawPtrBox, Array, ArrayData,
FixedSizeListArray,
};
-use super::{BooleanBufferBuilder, FixedSizeBinaryArray};
+use super::{BasicDecimalIter, BooleanBufferBuilder, FixedSizeBinaryArray};
#[allow(deprecated)]
pub use crate::array::DecimalIter;
use crate::buffer::{Buffer, MutableBuffer};
+use crate::datatypes::DataType;
use crate::datatypes::{
validate_decimal256_precision, validate_decimal_precision,
DECIMAL256_MAX_PRECISION,
- DECIMAL256_MAX_SCALE, DECIMAL_DEFAULT_SCALE,
+ 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};
+use crate::util::decimal::{BasicDecimal, Decimal256};
/// `Decimal128Array` stores fixed width decimal numbers,
/// with a fixed precision and scale.
@@ -71,19 +71,9 @@ use crate::util::decimal::{BasicDecimal, Decimal128,
Decimal256};
/// assert_eq!(6, decimal_array.scale());
/// ```
///
-pub struct Decimal128Array {
- data: ArrayData,
- value_data: RawPtrBox<u8>,
- precision: usize,
- scale: usize,
-}
+pub type Decimal128Array = BasicDecimalArray<16>;
-pub struct Decimal256Array {
- data: ArrayData,
- value_data: RawPtrBox<u8>,
- precision: usize,
- scale: usize,
-}
+pub type Decimal256Array = BasicDecimalArray<32>;
mod private_decimal {
pub trait DecimalArrayPrivate {
@@ -91,24 +81,37 @@ mod private_decimal {
}
}
-pub trait BasicDecimalArray<T: BasicDecimal, U: From<ArrayData>>:
- private_decimal::DecimalArrayPrivate
-{
- const VALUE_LENGTH: i32;
- const DEFAULT_TYPE: DataType;
- const MAX_PRECISION: usize;
- const MAX_SCALE: usize;
+pub struct BasicDecimalArray<const BYTE_WIDTH: usize> {
+ data: ArrayData,
+ value_data: RawPtrBox<u8>,
+ precision: usize,
+ scale: usize,
+}
+
+impl<const BYTE_WIDTH: usize> BasicDecimalArray<BYTE_WIDTH> {
+ pub const VALUE_LENGTH: i32 = BYTE_WIDTH as i32;
+ pub const DEFAULT_TYPE: DataType =
BasicDecimal::<BYTE_WIDTH>::DEFAULT_TYPE;
+ pub const MAX_PRECISION: usize = BasicDecimal::<BYTE_WIDTH>::MAX_PRECISION;
+ pub const MAX_SCALE: usize = BasicDecimal::<BYTE_WIDTH>::MAX_SCALE;
+ pub const TYPE_CONSTRUCTOR: fn(usize, usize) -> DataType =
+ BasicDecimal::<BYTE_WIDTH>::TYPE_CONSTRUCTOR;
- fn data(&self) -> &ArrayData;
+ pub fn data(&self) -> &ArrayData {
+ &self.data
+ }
/// Return the precision (total digits) that can be stored by this array
- fn precision(&self) -> usize;
+ pub fn precision(&self) -> usize {
+ self.precision
+ }
/// Return the scale (digits after the decimal) that can be stored by this
array
- fn scale(&self) -> usize;
+ pub fn scale(&self) -> usize {
+ self.scale
+ }
/// Returns the element at index `i`.
- fn value(&self, i: usize) -> T {
+ pub fn value(&self, i: usize) -> BasicDecimal<BYTE_WIDTH> {
assert!(i < self.data().len(), "Out of bounds access");
unsafe { self.value_unchecked(i) }
@@ -117,7 +120,7 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
/// Returns the element at index `i`.
/// # Safety
/// Caller is responsible for ensuring that the index is within the bounds
of the array
- unsafe fn value_unchecked(&self, i: usize) -> T {
+ pub unsafe fn value_unchecked(&self, i: usize) -> BasicDecimal<BYTE_WIDTH>
{
let data = self.data();
let offset = i + data.offset();
let raw_val = {
@@ -127,14 +130,14 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
Self::VALUE_LENGTH as usize,
)
};
- T::new(self.precision(), self.scale(), raw_val)
+ BasicDecimal::<BYTE_WIDTH>::new(self.precision(), self.scale(),
raw_val)
}
/// Returns the offset for the element at index `i`.
///
/// Note this doesn't do any bound checking, for performance reason.
#[inline]
- fn value_offset(&self, i: usize) -> i32 {
+ pub fn value_offset(&self, i: usize) -> i32 {
self.value_offset_at(self.data().offset() + i)
}
@@ -142,22 +145,22 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
///
/// All elements have the same length as the array is a fixed size.
#[inline]
- fn value_length(&self) -> i32 {
+ pub fn value_length(&self) -> i32 {
Self::VALUE_LENGTH
}
/// Returns a clone of the value data buffer
- fn value_data(&self) -> Buffer {
+ pub fn value_data(&self) -> Buffer {
self.data().buffers()[0].clone()
}
#[inline]
- fn value_offset_at(&self, i: usize) -> i32 {
+ pub fn value_offset_at(&self, i: usize) -> i32 {
Self::VALUE_LENGTH * i as i32
}
#[inline]
- fn value_as_string(&self, row: usize) -> String {
+ pub fn value_as_string(&self, row: usize) -> String {
self.value(row).to_string()
}
@@ -165,11 +168,11 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
///
/// NB: This function does not validate that each value is in the
permissible
/// range for a decimal
- fn from_fixed_size_binary_array(
+ pub fn from_fixed_size_binary_array(
v: FixedSizeBinaryArray,
precision: usize,
scale: usize,
- ) -> U {
+ ) -> Self {
assert!(
v.value_length() == Self::VALUE_LENGTH,
"Value length of the array ({}) must equal to the byte width of
the decimal ({})",
@@ -184,7 +187,7 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
let builder = v.into_data().into_builder().data_type(data_type);
let array_data = unsafe { builder.build_unchecked() };
- U::from(array_data)
+ Self::from(array_data)
}
/// Build a decimal array from [`FixedSizeListArray`].
@@ -192,11 +195,11 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
/// NB: This function does not validate that each value is in the
permissible
/// range for a decimal.
#[deprecated(note = "please use `from_fixed_size_binary_array` instead")]
- fn from_fixed_size_list_array(
+ pub fn from_fixed_size_list_array(
v: FixedSizeListArray,
precision: usize,
scale: usize,
- ) -> U {
+ ) -> Self {
assert_eq!(
v.data_ref().child_data().len(),
1,
@@ -242,14 +245,49 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
.offset(list_offset);
let array_data = unsafe { builder.build_unchecked() };
- U::from(array_data)
+ Self::from(array_data)
}
/// The default precision and scale used when not specified.
- fn default_type() -> DataType {
+ pub const fn default_type() -> DataType {
Self::DEFAULT_TYPE
}
+ fn raw_value_data_ptr(&self) -> *const u8 {
+ self.value_data.as_ptr()
+ }
+}
+
+impl Decimal128Array {
+ /// Creates a [Decimal128Array] with default precision and scale,
+ /// based on an iterator of `i128` values without nulls
+ pub fn from_iter_values<I: IntoIterator<Item = i128>>(iter: I) -> Self {
+ let val_buf: Buffer = iter.into_iter().collect();
+ let data = unsafe {
+ ArrayData::new_unchecked(
+ Self::default_type(),
+ val_buf.len() / std::mem::size_of::<i128>(),
+ None,
+ None,
+ 0,
+ vec![val_buf],
+ vec![],
+ )
+ };
+ Decimal128Array::from(data)
+ }
+
+ /// Validates decimal values in this array can be properly interpreted
+ /// with the specified precision.
+ pub fn validate_decimal_precision(&self, precision: usize) -> Result<()> {
+ if precision < self.precision {
+ for v in self.iter().flatten() {
+ validate_decimal_precision(v.as_i128(), precision)?;
+ }
+ }
+ Ok(())
+ }
+
/// Returns a Decimal array with the same data as self, with the
/// specified precision.
///
@@ -257,7 +295,7 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
/// 1. `precision` is larger than [`Self::MAX_PRECISION`]
/// 2. `scale` is larger than [`Self::MAX_SCALE`];
/// 3. `scale` is > `precision`
- fn with_precision_and_scale(self, precision: usize, scale: usize) ->
Result<U>
+ pub fn with_precision_and_scale(self, precision: usize, scale: usize) ->
Result<Self>
where
Self: Sized,
{
@@ -287,116 +325,86 @@ pub trait BasicDecimalArray<T: BasicDecimal, U:
From<ArrayData>>:
// decreased
self.validate_decimal_precision(precision)?;
- let data_type = if Self::VALUE_LENGTH == 16 {
- DataType::Decimal128(self.precision(), self.scale())
- } else {
- DataType::Decimal256(self.precision(), self.scale())
- };
+ let data_type = Self::TYPE_CONSTRUCTOR(self.precision, self.scale);
assert_eq!(self.data().data_type(), &data_type);
// safety: self.data is valid DataType::Decimal as checked above
- let new_data_type = if Self::VALUE_LENGTH == 16 {
- DataType::Decimal128(precision, scale)
- } else {
- DataType::Decimal256(precision, scale)
- };
+ let new_data_type = Self::TYPE_CONSTRUCTOR(precision, scale);
Ok(self.data().clone().with_data_type(new_data_type).into())
}
+}
+impl Decimal256Array {
/// Validates decimal values in this array can be properly interpreted
/// with the specified precision.
- fn validate_decimal_precision(&self, precision: usize) -> Result<()>;
-}
-
-impl BasicDecimalArray<Decimal128, Decimal128Array> for Decimal128Array {
- const VALUE_LENGTH: i32 = 16;
- const DEFAULT_TYPE: DataType =
- DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
- const MAX_PRECISION: usize = DECIMAL128_MAX_PRECISION;
- const MAX_SCALE: usize = DECIMAL128_MAX_SCALE;
-
- fn data(&self) -> &ArrayData {
- &self.data
- }
-
- fn precision(&self) -> usize {
- self.precision
- }
-
- fn scale(&self) -> usize {
- self.scale
- }
-
- fn validate_decimal_precision(&self, precision: usize) -> Result<()> {
+ pub fn validate_decimal_precision(&self, precision: usize) -> Result<()> {
if precision < self.precision {
for v in self.iter().flatten() {
- validate_decimal_precision(v.as_i128(), precision)?;
+ validate_decimal256_precision(&v.to_string(), precision)?;
}
}
Ok(())
}
-}
-
-impl BasicDecimalArray<Decimal256, Decimal256Array> for Decimal256Array {
- const VALUE_LENGTH: i32 = 32;
- const DEFAULT_TYPE: DataType =
- DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
- const MAX_PRECISION: usize = DECIMAL256_MAX_PRECISION;
- const MAX_SCALE: usize = DECIMAL256_MAX_SCALE;
- fn data(&self) -> &ArrayData {
- &self.data
- }
+ /// Returns a Decimal array with the same data as self, with the
+ /// specified precision.
+ ///
+ /// Returns an Error if:
+ /// 1. `precision` is larger than [`Self::MAX_PRECISION`]
+ /// 2. `scale` is larger than [`Self::MAX_SCALE`];
+ /// 3. `scale` is > `precision`
+ pub fn with_precision_and_scale(self, precision: usize, scale: usize) ->
Result<Self>
+ where
+ Self: Sized,
+ {
+ if precision > Self::MAX_PRECISION {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "precision {} is greater than max {}",
+ precision,
+ Self::MAX_PRECISION
+ )));
+ }
+ if scale > Self::MAX_SCALE {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "scale {} is greater than max {}",
+ scale,
+ Self::MAX_SCALE
+ )));
+ }
+ if scale > precision {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "scale {} is greater than precision {}",
+ scale, precision
+ )));
+ }
- fn precision(&self) -> usize {
- self.precision
- }
+ // Ensure that all values are within the requested
+ // precision. For performance, only check if the precision is
+ // decreased
+ self.validate_decimal_precision(precision)?;
- fn scale(&self) -> usize {
- self.scale
- }
+ let data_type = Self::TYPE_CONSTRUCTOR(self.precision, self.scale);
+ assert_eq!(self.data().data_type(), &data_type);
- fn validate_decimal_precision(&self, precision: usize) -> Result<()> {
- if precision < self.precision {
- for v in self.iter().flatten() {
- validate_decimal256_precision(&v.to_string(), precision)?;
- }
- }
- Ok(())
- }
-}
+ // safety: self.data is valid DataType::Decimal as checked above
+ let new_data_type = Self::TYPE_CONSTRUCTOR(precision, scale);
-impl Decimal128Array {
- /// Creates a [Decimal128Array] with default precision and scale,
- /// based on an iterator of `i128` values without nulls
- pub fn from_iter_values<I: IntoIterator<Item = i128>>(iter: I) -> Self {
- let val_buf: Buffer = iter.into_iter().collect();
- let data = unsafe {
- ArrayData::new_unchecked(
- Self::default_type(),
- val_buf.len() / std::mem::size_of::<i128>(),
- None,
- None,
- 0,
- vec![val_buf],
- vec![],
- )
- };
- Decimal128Array::from(data)
+ Ok(self.data().clone().with_data_type(new_data_type).into())
}
}
-impl From<ArrayData> for Decimal128Array {
+impl<const BYTE_WIDTH: usize> From<ArrayData> for
BasicDecimalArray<BYTE_WIDTH> {
fn from(data: ArrayData) -> Self {
assert_eq!(
data.buffers().len(),
1,
- "Decimal128Array data should contain 1 buffer only (values)"
+ "DecimalArray data should contain 1 buffer only (values)"
);
let values = data.buffers()[0].as_ptr();
- let (precision, scale) = match data.data_type() {
- DataType::Decimal128(precision, scale) => (*precision, *scale),
+ let (precision, scale) = match (data.data_type(), BYTE_WIDTH) {
+ (DataType::Decimal128(precision, scale), 16)
+ | (DataType::Decimal256(precision, scale), 32) => (*precision,
*scale),
_ => panic!("Expected data type to be Decimal"),
};
Self {
@@ -408,27 +416,6 @@ impl From<ArrayData> for Decimal128Array {
}
}
-impl From<ArrayData> for Decimal256Array {
- fn from(data: ArrayData) -> Self {
- assert_eq!(
- data.buffers().len(),
- 1,
- "Decimal256Array data should contain 1 buffer only (values)"
- );
- let values = data.buffers()[0].as_ptr();
- let (precision, scale) = match data.data_type() {
- DataType::Decimal256(precision, scale) => (*precision, *scale),
- _ => panic!("Expected data type to be Decimal256"),
- };
- Self {
- data,
- value_data: unsafe { RawPtrBox::new(values) },
- precision,
- scale,
- }
- }
-}
-
impl<'a> Decimal128Array {
/// Constructs a new iterator that iterates `Decimal128` values as i128
values.
/// This is kept mostly for back-compatibility purpose.
@@ -446,17 +433,13 @@ impl From<BigInt> for Decimal256 {
}
}
-fn build_decimal_array_from<U: BasicDecimalArray<T, U>, T>(
+fn build_decimal_array_from<const BYTE_WIDTH: usize>(
null_buf: BooleanBufferBuilder,
buffer: Buffer,
-) -> U
-where
- T: BasicDecimal,
- U: From<ArrayData>,
-{
+) -> BasicDecimalArray<BYTE_WIDTH> {
let data = unsafe {
ArrayData::new_unchecked(
- U::default_type(),
+ BasicDecimalArray::<BYTE_WIDTH>::default_type(),
null_buf.len(),
None,
Some(null_buf.into()),
@@ -465,7 +448,7 @@ where
vec![],
)
};
- U::from(data)
+ BasicDecimalArray::<BYTE_WIDTH>::from(data)
}
impl<Ptr: Into<Decimal256>> FromIterator<Option<Ptr>> for Decimal256Array {
@@ -488,7 +471,7 @@ impl<Ptr: Into<Decimal256>> FromIterator<Option<Ptr>> for
Decimal256Array {
}
});
- build_decimal_array_from::<Decimal256Array, _>(null_buf, buffer.into())
+ build_decimal_array_from::<32>(null_buf, buffer.into())
}
}
@@ -513,96 +496,75 @@ impl<Ptr: Borrow<Option<i128>>> FromIterator<Ptr> for
Decimal128Array {
})
.collect();
- build_decimal_array_from::<Decimal128Array, _>(null_buf, buffer)
+ build_decimal_array_from::<16>(null_buf, buffer)
}
}
-macro_rules! def_decimal_array {
- ($ty:ident, $array_name:expr, $decimal_ty:ident, $iter_ty:ident) => {
- impl private_decimal::DecimalArrayPrivate for $ty {
- fn raw_value_data_ptr(&self) -> *const u8 {
- self.value_data.as_ptr()
- }
- }
-
- impl Array for $ty {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn data(&self) -> &ArrayData {
- &self.data
- }
+impl<const BYTE_WIDTH: usize> Array for BasicDecimalArray<BYTE_WIDTH> {
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
- fn into_data(self) -> ArrayData {
- self.into()
- }
- }
+ fn data(&self) -> &ArrayData {
+ &self.data
+ }
- impl From<$ty> for ArrayData {
- fn from(array: $ty) -> Self {
- array.data
- }
- }
+ fn into_data(self) -> ArrayData {
+ self.into()
+ }
+}
- impl fmt::Debug for $ty {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
- f,
- "{}<{}, {}>\n[\n",
- $array_name, self.precision, self.scale
- )?;
- print_long_array(self, f, |array, index, f| {
- let formatted_decimal = array.value_as_string(index);
-
- write!(f, "{}", formatted_decimal)
- })?;
- write!(f, "]")
- }
- }
+impl<const BYTE_WIDTH: usize> From<BasicDecimalArray<BYTE_WIDTH>> for
ArrayData {
+ fn from(array: BasicDecimalArray<BYTE_WIDTH>) -> Self {
+ array.data
+ }
+}
- impl<'a> ArrayAccessor for &'a $ty {
- type Item = $decimal_ty;
+impl<const BYTE_WIDTH: usize> fmt::Debug for BasicDecimalArray<BYTE_WIDTH> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "Decimal{}Array<{}, {}>\n[\n",
+ BYTE_WIDTH * 8,
+ self.precision,
+ self.scale
+ )?;
+ print_long_array(self, f, |array, index, f| {
+ let formatted_decimal = array.value_as_string(index);
+
+ write!(f, "{}", formatted_decimal)
+ })?;
+ write!(f, "]")
+ }
+}
- fn value(&self, index: usize) -> Self::Item {
- $ty::value(self, index)
- }
+impl<'a, const BYTE_WIDTH: usize> ArrayAccessor for &'a
BasicDecimalArray<BYTE_WIDTH> {
+ type Item = BasicDecimal<BYTE_WIDTH>;
- unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
- $ty::value_unchecked(self, index)
- }
- }
+ fn value(&self, index: usize) -> Self::Item {
+ BasicDecimalArray::<BYTE_WIDTH>::value(self, index)
+ }
- impl<'a> IntoIterator for &'a $ty {
- type Item = Option<$decimal_ty>;
- type IntoIter = $iter_ty<'a>;
+ unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
+ BasicDecimalArray::<BYTE_WIDTH>::value_unchecked(self, index)
+ }
+}
- fn into_iter(self) -> Self::IntoIter {
- $iter_ty::<'a>::new(self)
- }
- }
+impl<'a, const BYTE_WIDTH: usize> IntoIterator for &'a
BasicDecimalArray<BYTE_WIDTH> {
+ type Item = Option<BasicDecimal<BYTE_WIDTH>>;
+ type IntoIter = BasicDecimalIter<'a, BYTE_WIDTH>;
- impl<'a> $ty {
- /// constructs a new iterator
- pub fn iter(&'a self) -> $iter_ty<'a> {
- $iter_ty::<'a>::new(self)
- }
- }
- };
+ fn into_iter(self) -> Self::IntoIter {
+ BasicDecimalIter::<'a, BYTE_WIDTH>::new(self)
+ }
}
-def_decimal_array!(
- Decimal128Array,
- "Decimal128Array",
- Decimal128,
- Decimal128Iter
-);
-def_decimal_array!(
- Decimal256Array,
- "Decimal256Array",
- Decimal256,
- Decimal256Iter
-);
+impl<'a, const BYTE_WIDTH: usize> BasicDecimalArray<BYTE_WIDTH> {
+ /// constructs a new iterator
+ pub fn iter(&'a self) -> BasicDecimalIter<'a, BYTE_WIDTH> {
+ BasicDecimalIter::<'a, BYTE_WIDTH>::new(self)
+ }
+}
#[cfg(test)]
mod tests {
diff --git a/arrow/src/array/builder/decimal_builder.rs
b/arrow/src/array/builder/decimal_builder.rs
index 22c1490e8..bd43100b7 100644
--- a/arrow/src/array/builder/decimal_builder.rs
+++ b/arrow/src/array/builder/decimal_builder.rs
@@ -19,7 +19,7 @@ use num::BigInt;
use std::any::Any;
use std::sync::Arc;
-use crate::array::array_decimal::{BasicDecimalArray, Decimal256Array};
+use crate::array::array_decimal::Decimal256Array;
use crate::array::ArrayRef;
use crate::array::Decimal128Array;
use crate::array::{ArrayBuilder, FixedSizeBinaryBuilder};
@@ -27,7 +27,7 @@ use crate::array::{ArrayBuilder, FixedSizeBinaryBuilder};
use crate::error::{ArrowError, Result};
use crate::datatypes::{validate_decimal256_precision,
validate_decimal_precision};
-use crate::util::decimal::{BasicDecimal, Decimal256};
+use crate::util::decimal::Decimal256;
/// Array Builder for [`Decimal128Array`]
///
@@ -258,7 +258,7 @@ mod tests {
use super::*;
use num::Num;
- use crate::array::array_decimal::{BasicDecimalArray, Decimal128Array};
+ use crate::array::array_decimal::Decimal128Array;
use crate::array::{array_decimal, Array};
use crate::datatypes::DataType;
use crate::util::decimal::{Decimal128, Decimal256};
@@ -305,21 +305,21 @@ mod tests {
fn test_decimal256_builder() {
let mut builder = Decimal256Builder::new(30, 40, 6);
- let mut bytes = vec![0; 32];
+ let mut bytes = [0_u8; 32];
bytes[0..16].clone_from_slice(&8_887_000_000_i128.to_le_bytes());
- let value = Decimal256::try_new_from_bytes(40, 6,
bytes.as_slice()).unwrap();
+ let value = Decimal256::try_new_from_bytes(40, 6, &bytes).unwrap();
builder.append_value(&value).unwrap();
builder.append_null();
- bytes = vec![255; 32];
- let value = Decimal256::try_new_from_bytes(40, 6,
bytes.as_slice()).unwrap();
+ bytes = [255; 32];
+ let value = Decimal256::try_new_from_bytes(40, 6, &bytes).unwrap();
builder.append_value(&value).unwrap();
- bytes = vec![0; 32];
+ bytes = [0; 32];
bytes[0..16].clone_from_slice(&0_i128.to_le_bytes());
bytes[15] = 128;
- let value = Decimal256::try_new_from_bytes(40, 6,
bytes.as_slice()).unwrap();
+ let value = Decimal256::try_new_from_bytes(40, 6, &bytes).unwrap();
builder.append_value(&value).unwrap();
builder.append_option(None::<&Decimal256>).unwrap();
@@ -349,9 +349,9 @@ mod tests {
fn test_decimal256_builder_unmatched_precision_scale() {
let mut builder = Decimal256Builder::new(30, 10, 6);
- let mut bytes = vec![0; 32];
+ let mut bytes = [0_u8; 32];
bytes[0..16].clone_from_slice(&8_887_000_000_i128.to_le_bytes());
- let value = Decimal256::try_new_from_bytes(40, 6,
bytes.as_slice()).unwrap();
+ let value = Decimal256::try_new_from_bytes(40, 6, &bytes).unwrap();
builder.append_value(&value).unwrap();
}
diff --git a/arrow/src/array/equal/mod.rs b/arrow/src/array/equal/mod.rs
index 3387e2842..6fdc06f83 100644
--- a/arrow/src/array/equal/mod.rs
+++ b/arrow/src/array/equal/mod.rs
@@ -262,7 +262,6 @@ mod tests {
use std::convert::TryFrom;
use std::sync::Arc;
- use crate::array::BasicDecimalArray;
use crate::array::{
array::Array, ArrayData, ArrayDataBuilder, ArrayRef, BooleanArray,
FixedSizeBinaryBuilder, FixedSizeListBuilder, GenericBinaryArray,
Int32Builder,
diff --git a/arrow/src/array/iterator.rs b/arrow/src/array/iterator.rs
index 8ee9f2544..7cc9bde6b 100644
--- a/arrow/src/array/iterator.rs
+++ b/arrow/src/array/iterator.rs
@@ -16,7 +16,7 @@
// under the License.
use crate::array::array::ArrayAccessor;
-use crate::array::{BasicDecimalArray, Decimal256Array};
+use crate::array::BasicDecimalArray;
use super::{
Array, BooleanArray, Decimal128Array, GenericBinaryArray, GenericListArray,
@@ -104,14 +104,15 @@ pub type GenericStringIter<'a, T> = ArrayIter<&'a
GenericStringArray<T>>;
pub type GenericBinaryIter<'a, T> = ArrayIter<&'a GenericBinaryArray<T>>;
pub type GenericListArrayIter<'a, O> = ArrayIter<&'a GenericListArray<O>>;
+pub type BasicDecimalIter<'a, const BYTE_WIDTH: usize> =
+ ArrayIter<&'a BasicDecimalArray<BYTE_WIDTH>>;
/// an iterator that returns `Some(Decimal128)` or `None`, that can be used on
a
/// [`Decimal128Array`]
-pub type Decimal128Iter<'a> = ArrayIter<&'a Decimal128Array>;
+pub type Decimal128Iter<'a> = BasicDecimalIter<'a, 16>;
/// an iterator that returns `Some(Decimal256)` or `None`, that can be used on
a
-/// [`Decimal256Array`]
-pub type Decimal256Iter<'a> = ArrayIter<&'a Decimal256Array>;
-
+/// [`super::Decimal256Array`]
+pub type Decimal256Iter<'a> = BasicDecimalIter<'a, 32>;
/// an iterator that returns `Some(i128)` or `None`, that can be used on a
/// [`Decimal128Array`]
#[derive(Debug)]
diff --git a/arrow/src/array/ord.rs b/arrow/src/array/ord.rs
index 1e19c7cc2..47173aa7d 100644
--- a/arrow/src/array/ord.rs
+++ b/arrow/src/array/ord.rs
@@ -19,7 +19,6 @@
use std::cmp::Ordering;
-use crate::array::BasicDecimalArray;
use crate::array::*;
use crate::datatypes::TimeUnit;
use crate::datatypes::*;
diff --git a/arrow/src/array/transform/mod.rs b/arrow/src/array/transform/mod.rs
index 409f2dd14..f0fccef14 100644
--- a/arrow/src/array/transform/mod.rs
+++ b/arrow/src/array/transform/mod.rs
@@ -670,8 +670,6 @@ mod tests {
use std::{convert::TryFrom, sync::Arc};
use super::*;
-
- use crate::array::BasicDecimalArray;
use crate::array::Decimal128Array;
use crate::{
array::{
diff --git a/arrow/src/compute/kernels/cast.rs
b/arrow/src/compute/kernels/cast.rs
index c6b8f4779..c9082afef 100644
--- a/arrow/src/compute/kernels/cast.rs
+++ b/arrow/src/compute/kernels/cast.rs
@@ -2420,7 +2420,6 @@ where
#[cfg(test)]
mod tests {
use super::*;
- use crate::array::BasicDecimalArray;
use crate::datatypes::TimeUnit;
use crate::util::decimal::Decimal128;
use crate::{buffer::Buffer, util::display::array_value_to_string};
diff --git a/arrow/src/compute/kernels/sort.rs
b/arrow/src/compute/kernels/sort.rs
index 0a3d0541c..dca09a66a 100644
--- a/arrow/src/compute/kernels/sort.rs
+++ b/arrow/src/compute/kernels/sort.rs
@@ -17,7 +17,6 @@
//! Defines sort kernel for `ArrayRef`
-use crate::array::BasicDecimalArray;
use crate::array::*;
use crate::buffer::MutableBuffer;
use crate::compute::take;
diff --git a/arrow/src/compute/kernels/take.rs
b/arrow/src/compute/kernels/take.rs
index 05832e4f5..fb8f75651 100644
--- a/arrow/src/compute/kernels/take.rs
+++ b/arrow/src/compute/kernels/take.rs
@@ -19,8 +19,6 @@
use std::{ops::AddAssign, sync::Arc};
-use crate::array::BasicDecimalArray;
-
use crate::buffer::{Buffer, MutableBuffer};
use crate::compute::util::{
take_value_indices_from_fixed_size_list, take_value_indices_from_list,
diff --git a/arrow/src/csv/reader.rs b/arrow/src/csv/reader.rs
index 7c533a8f8..f01ce37c7 100644
--- a/arrow/src/csv/reader.rs
+++ b/arrow/src/csv/reader.rs
@@ -1116,7 +1116,6 @@ mod tests {
use std::io::{Cursor, Write};
use tempfile::NamedTempFile;
- use crate::array::BasicDecimalArray;
use crate::array::*;
use crate::compute::cast;
use crate::datatypes::Field;
diff --git a/arrow/src/ffi.rs b/arrow/src/ffi.rs
index 0716a49d6..528f3adc2 100644
--- a/arrow/src/ffi.rs
+++ b/arrow/src/ffi.rs
@@ -911,7 +911,6 @@ impl<'a> ArrowArrayChild<'a> {
#[cfg(test)]
mod tests {
use super::*;
- use crate::array::BasicDecimalArray;
use crate::array::{
export_array_into_raw, make_array, Array, ArrayData, BooleanArray,
Decimal128Array, DictionaryArray, DurationSecondArray,
FixedSizeBinaryArray,
diff --git a/arrow/src/util/decimal.rs b/arrow/src/util/decimal.rs
index 62a950795..74f3379f4 100644
--- a/arrow/src/util/decimal.rs
+++ b/arrow/src/util/decimal.rs
@@ -18,21 +18,51 @@
//! Decimal related utils
use crate::datatypes::{
- DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE, DECIMAL256_MAX_PRECISION,
- DECIMAL256_MAX_SCALE,
+ DataType, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE,
DECIMAL256_MAX_PRECISION,
+ DECIMAL256_MAX_SCALE, DECIMAL_DEFAULT_SCALE,
};
use crate::error::{ArrowError, Result};
use num::bigint::BigInt;
use num::Signed;
use std::cmp::{min, Ordering};
-pub trait BasicDecimal: PartialOrd + Ord + PartialEq + Eq {
- /// The bit-width of the internal representation.
- const BIT_WIDTH: usize;
- /// The maximum precision.
- const MAX_PRECISION: usize;
- /// The maximum scale.
- const MAX_SCALE: usize;
+#[derive(Debug)]
+pub struct BasicDecimal<const BYTE_WIDTH: usize> {
+ precision: usize,
+ scale: usize,
+ value: [u8; BYTE_WIDTH],
+}
+
+impl<const BYTE_WIDTH: usize> BasicDecimal<BYTE_WIDTH> {
+ #[allow(clippy::type_complexity)]
+ const _MAX_PRECISION_SCALE_CONSTRUCTOR_DEFAULT_TYPE: (
+ usize,
+ usize,
+ fn(usize, usize) -> DataType,
+ DataType,
+ ) = match BYTE_WIDTH {
+ 16 => (
+ DECIMAL128_MAX_PRECISION,
+ DECIMAL128_MAX_SCALE,
+ DataType::Decimal128,
+ DataType::Decimal128(DECIMAL128_MAX_PRECISION,
DECIMAL_DEFAULT_SCALE),
+ ),
+ 32 => (
+ DECIMAL256_MAX_PRECISION,
+ DECIMAL256_MAX_SCALE,
+ DataType::Decimal256,
+ DataType::Decimal256(DECIMAL256_MAX_PRECISION,
DECIMAL_DEFAULT_SCALE),
+ ),
+ _ => panic!("invalid byte width"),
+ };
+
+ pub const MAX_PRECISION: usize =
+ Self::_MAX_PRECISION_SCALE_CONSTRUCTOR_DEFAULT_TYPE.0;
+ pub const MAX_SCALE: usize =
Self::_MAX_PRECISION_SCALE_CONSTRUCTOR_DEFAULT_TYPE.1;
+ pub const TYPE_CONSTRUCTOR: fn(usize, usize) -> DataType =
+ Self::_MAX_PRECISION_SCALE_CONSTRUCTOR_DEFAULT_TYPE.2;
+ pub const DEFAULT_TYPE: DataType =
+ Self::_MAX_PRECISION_SCALE_CONSTRUCTOR_DEFAULT_TYPE.3;
/// Tries to create a decimal value from precision, scale and bytes.
/// If the length of bytes isn't same as the bit width of this decimal,
@@ -41,7 +71,11 @@ pub trait BasicDecimal: PartialOrd + Ord + PartialEq + Eq {
/// Safety:
/// This method doesn't validate if the decimal value represented by the
bytes
/// can be fitted into the specified precision.
- fn try_new_from_bytes(precision: usize, scale: usize, bytes: &[u8]) ->
Result<Self>
+ pub fn try_new_from_bytes(
+ precision: usize,
+ scale: usize,
+ bytes: &[u8; BYTE_WIDTH],
+ ) -> Result<Self>
where
Self: Sized,
{
@@ -67,13 +101,13 @@ pub trait BasicDecimal: PartialOrd + Ord + PartialEq + Eq {
)));
}
- if bytes.len() == Self::BIT_WIDTH / 8 {
+ if bytes.len() == BYTE_WIDTH {
Ok(Self::new(precision, scale, bytes))
} else {
Err(ArrowError::InvalidArgumentError(format!(
"Input to Decimal{} must be {} bytes",
- Self::BIT_WIDTH,
- Self::BIT_WIDTH / 8
+ BYTE_WIDTH * 8,
+ BYTE_WIDTH
)))
}
}
@@ -83,21 +117,33 @@ pub trait BasicDecimal: PartialOrd + Ord + PartialEq + Eq {
/// Safety:
/// This method doesn't check if the length of bytes is compatible with
this decimal.
/// Use `try_new_from_bytes` for safe constructor.
- fn new(precision: usize, scale: usize, bytes: &[u8]) -> Self;
-
+ pub fn new(precision: usize, scale: usize, bytes: &[u8]) -> Self {
+ Self {
+ precision,
+ scale,
+ value: bytes.try_into().unwrap(),
+ }
+ }
/// Returns the raw bytes of the integer representation of the decimal.
- fn raw_value(&self) -> &[u8];
+ pub fn raw_value(&self) -> &[u8] {
+ &self.value
+ }
/// Returns the precision of the decimal.
- fn precision(&self) -> usize;
+ pub fn precision(&self) -> usize {
+ self.precision
+ }
/// Returns the scale of the decimal.
- fn scale(&self) -> usize;
+ pub fn scale(&self) -> usize {
+ self.scale
+ }
/// Returns the string representation of the decimal.
/// If the string representation cannot be fitted with the precision of
the decimal,
/// the string will be truncated.
- fn to_string(&self) -> String {
+ #[allow(clippy::inherent_to_string)]
+ pub fn to_string(&self) -> String {
let raw_bytes = self.raw_value();
let integer = BigInt::from_signed_bytes_le(raw_bytes);
let value_str = integer.to_string();
@@ -119,15 +165,44 @@ pub trait BasicDecimal: PartialOrd + Ord + PartialEq + Eq
{
}
}
+impl<const BYTE_WIDTH: usize> PartialOrd for BasicDecimal<BYTE_WIDTH> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ assert_eq!(
+ self.scale, other.scale,
+ "Cannot compare two Decimals with different scale: {}, {}",
+ self.scale, other.scale
+ );
+ Some(singed_cmp_le_bytes(&self.value, &other.value))
+ }
+}
+
+impl<const BYTE_WIDTH: usize> Ord for BasicDecimal<BYTE_WIDTH> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ assert_eq!(
+ self.scale, other.scale,
+ "Cannot compare two Decimals with different scale: {}, {}",
+ self.scale, other.scale
+ );
+ singed_cmp_le_bytes(&self.value, &other.value)
+ }
+}
+
+impl<const BYTE_WIDTH: usize> PartialEq<Self> for BasicDecimal<BYTE_WIDTH> {
+ fn eq(&self, other: &Self) -> bool {
+ assert_eq!(
+ self.scale, other.scale,
+ "Cannot compare two Decimals with different scale: {}, {}",
+ self.scale, other.scale
+ );
+ self.value.eq(&other.value)
+ }
+}
+
+impl<const BYTE_WIDTH: usize> Eq for BasicDecimal<BYTE_WIDTH> {}
+
/// Represents a decimal value with precision and scale.
/// The decimal value could represented by a signed 128-bit integer.
-#[derive(Debug)]
-pub struct Decimal128 {
- #[allow(dead_code)]
- precision: usize,
- scale: usize,
- value: [u8; 16],
-}
+pub type Decimal128 = BasicDecimal<16>;
impl Decimal128 {
/// Creates `Decimal128` from an `i128` value.
@@ -154,13 +229,7 @@ impl From<Decimal128> for i128 {
/// Represents a decimal value with precision and scale.
/// The decimal value could be represented by a signed 256-bit integer.
-#[derive(Debug)]
-pub struct Decimal256 {
- #[allow(dead_code)]
- precision: usize,
- scale: usize,
- value: [u8; 32],
-}
+pub type Decimal256 = BasicDecimal<32>;
impl Decimal256 {
/// Constructs a `Decimal256` value from a `BigInt`.
@@ -170,9 +239,9 @@ impl Decimal256 {
scale: usize,
) -> Result<Decimal256> {
let mut bytes = if num.is_negative() {
- vec![255; 32]
+ [255_u8; 32]
} else {
- vec![0; 32]
+ [0; 32]
};
let num_bytes = &num.to_signed_bytes_le();
bytes[0..num_bytes.len()].clone_from_slice(num_bytes);
@@ -180,71 +249,6 @@ impl Decimal256 {
}
}
-macro_rules! def_decimal {
- ($ty:ident, $bit:expr, $max_p:expr, $max_s:expr) => {
- impl BasicDecimal for $ty {
- const BIT_WIDTH: usize = $bit;
- const MAX_PRECISION: usize = $max_p;
- const MAX_SCALE: usize = $max_s;
-
- fn new(precision: usize, scale: usize, bytes: &[u8]) -> Self {
- $ty {
- precision,
- scale,
- value: bytes.try_into().unwrap(),
- }
- }
-
- fn raw_value(&self) -> &[u8] {
- &self.value
- }
-
- fn precision(&self) -> usize {
- self.precision
- }
-
- fn scale(&self) -> usize {
- self.scale
- }
- }
-
- impl PartialOrd for $ty {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- assert_eq!(
- self.scale, other.scale,
- "Cannot compare two Decimals with different scale: {}, {}",
- self.scale, other.scale
- );
- Some(singed_cmp_le_bytes(&self.value, &other.value))
- }
- }
-
- impl Ord for $ty {
- fn cmp(&self, other: &Self) -> Ordering {
- assert_eq!(
- self.scale, other.scale,
- "Cannot compare two Decimals with different scale: {}, {}",
- self.scale, other.scale
- );
- singed_cmp_le_bytes(&self.value, &other.value)
- }
- }
-
- impl PartialEq<Self> for $ty {
- fn eq(&self, other: &Self) -> bool {
- assert_eq!(
- self.scale, other.scale,
- "Cannot compare two Decimals with different scale: {}, {}",
- self.scale, other.scale
- );
- self.value.eq(&other.value)
- }
- }
-
- impl Eq for $ty {}
- };
-}
-
// compare two signed integer which are encoded with little endian.
// left bytes and right bytes must have the same length.
fn singed_cmp_le_bytes(left: &[u8], right: &[u8]) -> Ordering {
@@ -286,24 +290,9 @@ fn singed_cmp_le_bytes(left: &[u8], right: &[u8]) ->
Ordering {
Ordering::Equal
}
-def_decimal!(
- Decimal128,
- 128,
- DECIMAL128_MAX_PRECISION,
- DECIMAL128_MAX_SCALE
-);
-def_decimal!(
- Decimal256,
- 256,
- DECIMAL256_MAX_PRECISION,
- DECIMAL256_MAX_SCALE
-);
-
#[cfg(test)]
mod tests {
- use crate::util::decimal::{
- singed_cmp_le_bytes, BasicDecimal, Decimal128, Decimal256,
- };
+ use super::*;
use num::{BigInt, Num};
use rand::random;
@@ -356,9 +345,9 @@ mod tests {
#[test]
fn decimal_256_from_bytes() {
- let mut bytes = vec![0; 32];
+ let mut bytes = [0_u8; 32];
bytes[0..16].clone_from_slice(&100_i128.to_le_bytes());
- let value = Decimal256::try_new_from_bytes(5, 2,
bytes.as_slice()).unwrap();
+ let value = Decimal256::try_new_from_bytes(5, 2, &bytes).unwrap();
assert_eq!(value.to_string(), "1.00");
bytes[0..16].clone_from_slice(&i128::MAX.to_le_bytes());
@@ -378,7 +367,7 @@ mod tests {
);
// smaller than i128 minimum
- bytes = vec![255; 32];
+ bytes = [255; 32];
bytes[31] = 128;
let value = Decimal256::try_new_from_bytes(76, 4, &bytes).unwrap();
assert_eq!(
@@ -386,7 +375,7 @@ mod tests {
"-574437317700748313234121683441537667865831564552201235664496608164256541.5731"
);
- bytes = vec![255; 32];
+ bytes = [255; 32];
let value = Decimal256::try_new_from_bytes(5, 2, &bytes).unwrap();
assert_eq!(value.to_string(), "-0.01");
}
diff --git a/arrow/src/util/display.rs b/arrow/src/util/display.rs
index 26bc8a192..aa4fd4200 100644
--- a/arrow/src/util/display.rs
+++ b/arrow/src/util/display.rs
@@ -23,7 +23,6 @@ use std::fmt::Write;
use std::sync::Arc;
use crate::array::Array;
-use crate::array::BasicDecimalArray;
use crate::datatypes::{
ArrowNativeType, ArrowPrimitiveType, DataType, Field, Int16Type, Int32Type,
Int64Type, Int8Type, TimeUnit, UInt16Type, UInt32Type, UInt64Type,
UInt8Type,
diff --git a/arrow/src/util/integration_util.rs
b/arrow/src/util/integration_util.rs
index 65d54a02b..ee5c947a2 100644
--- a/arrow/src/util/integration_util.rs
+++ b/arrow/src/util/integration_util.rs
@@ -34,7 +34,7 @@ use crate::datatypes::*;
use crate::error::{ArrowError, Result};
use crate::record_batch::{RecordBatch, RecordBatchReader};
use crate::util::bit_util;
-use crate::util::decimal::{BasicDecimal, Decimal256};
+use crate::util::decimal::Decimal256;
/// A struct that represents an Arrow file with a schema and record batches
#[derive(Deserialize, Serialize, Debug)]
diff --git a/arrow/src/util/pretty.rs b/arrow/src/util/pretty.rs
index 84d445e9a..6f4d9e34a 100644
--- a/arrow/src/util/pretty.rs
+++ b/arrow/src/util/pretty.rs
@@ -107,7 +107,7 @@ fn create_column(field: &str, columns: &[ArrayRef]) ->
Result<Table> {
mod tests {
use crate::{
array::{
- self, new_null_array, Array, BasicDecimalArray, Date32Array,
Date64Array,
+ self, new_null_array, Array, Date32Array, Date64Array,
FixedSizeBinaryBuilder, Float16Array, Int32Array, PrimitiveBuilder,
StringArray, StringBuilder, StringDictionaryBuilder, StructArray,
Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray,
diff --git a/parquet/src/arrow/array_reader/primitive_array.rs
b/parquet/src/arrow/array_reader/primitive_array.rs
index 516a3f50c..61883bc70 100644
--- a/parquet/src/arrow/array_reader/primitive_array.rs
+++ b/parquet/src/arrow/array_reader/primitive_array.rs
@@ -25,7 +25,7 @@ use crate::data_type::DataType;
use crate::errors::{ParquetError, Result};
use crate::schema::types::ColumnDescPtr;
use arrow::array::{
- ArrayDataBuilder, ArrayRef, BasicDecimalArray, BooleanArray,
BooleanBufferBuilder,
+ ArrayDataBuilder, ArrayRef, BooleanArray, BooleanBufferBuilder,
Decimal128Array, Float32Array, Float64Array, Int32Array, Int64Array,
};
use arrow::buffer::Buffer;
diff --git a/parquet/src/arrow/arrow_writer/mod.rs
b/parquet/src/arrow/arrow_writer/mod.rs
index 800aff98a..08f37c395 100644
--- a/parquet/src/arrow/arrow_writer/mod.rs
+++ b/parquet/src/arrow/arrow_writer/mod.rs
@@ -23,7 +23,6 @@ use std::sync::Arc;
use arrow::array as arrow_array;
use arrow::array::ArrayRef;
-use arrow::array::BasicDecimalArray;
use arrow::datatypes::{DataType as ArrowDataType, IntervalUnit, SchemaRef};
use arrow::record_batch::RecordBatch;
use arrow_array::Array;
diff --git a/parquet/src/arrow/buffer/converter.rs
b/parquet/src/arrow/buffer/converter.rs
index d8cbd256a..aa98b48d5 100644
--- a/parquet/src/arrow/buffer/converter.rs
+++ b/parquet/src/arrow/buffer/converter.rs
@@ -17,9 +17,9 @@
use crate::data_type::{ByteArray, FixedLenByteArray, Int96};
use arrow::array::{
- Array, ArrayRef, BasicDecimalArray, Decimal128Array, FixedSizeBinaryArray,
- FixedSizeBinaryBuilder, IntervalDayTimeArray, IntervalDayTimeBuilder,
- IntervalYearMonthArray, IntervalYearMonthBuilder, TimestampNanosecondArray,
+ Array, ArrayRef, Decimal128Array, FixedSizeBinaryArray,
FixedSizeBinaryBuilder,
+ IntervalDayTimeArray, IntervalDayTimeBuilder, IntervalYearMonthArray,
+ IntervalYearMonthBuilder, TimestampNanosecondArray,
};
use std::sync::Arc;