use crate::builder::BooleanBufferBuilder;
use crate::decimal::{Decimal, Decimal256};
use crate::iterator::DecimalIter;
use crate::raw_pointer::RawPtrBox;
use crate::types::{Decimal128Type, Decimal256Type, DecimalType, NativeDecimalType};
use crate::{
print_long_array, Array, ArrayAccessor, FixedSizeBinaryArray, FixedSizeListArray,
};
use arrow_buffer::{Buffer, MutableBuffer};
use arrow_data::decimal::{
validate_decimal256_precision_with_lt_bytes, validate_decimal_precision,
};
use arrow_data::ArrayData;
use arrow_schema::{ArrowError, DataType};
use std::any::Any;
use std::marker::PhantomData;
pub type Decimal128Array = DecimalArray<Decimal128Type>;
pub type Decimal256Array = DecimalArray<Decimal256Type>;
pub struct DecimalArray<T: DecimalType> {
data: ArrayData,
value_data: RawPtrBox<u8>,
precision: u8,
scale: u8,
_phantom: PhantomData<T>,
}
impl<T: DecimalType> DecimalArray<T> {
pub const VALUE_LENGTH: i32 = T::BYTE_LENGTH as i32;
const DEFAULT_TYPE: DataType = T::DEFAULT_TYPE;
pub const MAX_PRECISION: u8 = T::MAX_PRECISION;
pub const MAX_SCALE: u8 = T::MAX_SCALE;
const TYPE_CONSTRUCTOR: fn(u8, u8) -> DataType = T::TYPE_CONSTRUCTOR;
pub fn data(&self) -> &ArrayData {
&self.data
}
pub fn precision(&self) -> u8 {
self.precision
}
pub fn scale(&self) -> u8 {
self.scale
}
pub fn value(&self, i: usize) -> Decimal<T> {
assert!(
i < self.data().len(),
"Trying to access an element at index {} from a DecimalArray of length {}",
i,
self.len()
);
unsafe { self.value_unchecked(i) }
}
pub unsafe fn value_unchecked(&self, i: usize) -> Decimal<T> {
let data = self.data();
let offset = i + data.offset();
let raw_val = {
let pos = self.value_offset_at(offset);
T::Native::from_slice(std::slice::from_raw_parts(
self.raw_value_data_ptr().offset(pos as isize),
Self::VALUE_LENGTH as usize,
))
};
Decimal::new(self.precision(), self.scale(), &raw_val)
}
#[inline]
pub fn value_offset(&self, i: usize) -> i32 {
self.value_offset_at(self.data().offset() + i)
}
#[inline]
pub fn value_length(&self) -> i32 {
Self::VALUE_LENGTH
}
pub fn value_data(&self) -> Buffer {
self.data().buffers()[0].clone()
}
#[inline]
pub fn value_offset_at(&self, i: usize) -> i32 {
Self::VALUE_LENGTH * i as i32
}
#[inline]
pub fn value_as_string(&self, row: usize) -> String {
self.value(row).to_string()
}
pub fn from_fixed_size_binary_array(
v: FixedSizeBinaryArray,
precision: u8,
scale: u8,
) -> Self {
assert!(
v.value_length() == Self::VALUE_LENGTH,
"Value length of the array ({}) must equal to the byte width of the decimal ({})",
v.value_length(),
Self::VALUE_LENGTH,
);
let data_type = if Self::VALUE_LENGTH == 16 {
DataType::Decimal128(precision, scale)
} else {
DataType::Decimal256(precision, scale)
};
let builder = v.into_data().into_builder().data_type(data_type);
let array_data = unsafe { builder.build_unchecked() };
Self::from(array_data)
}
#[deprecated(note = "please use `from_fixed_size_binary_array` instead")]
pub fn from_fixed_size_list_array(
v: FixedSizeListArray,
precision: u8,
scale: u8,
) -> Self {
assert_eq!(
v.data_ref().child_data().len(),
1,
"DecimalArray can only be created from list array of u8 values \
(i.e. FixedSizeList<PrimitiveArray<u8>>)."
);
let child_data = &v.data_ref().child_data()[0];
assert_eq!(
child_data.child_data().len(),
0,
"DecimalArray can only be created from list array of u8 values \
(i.e. FixedSizeList<PrimitiveArray<u8>>)."
);
assert_eq!(
child_data.data_type(),
&DataType::UInt8,
"DecimalArray can only be created from FixedSizeList<u8> arrays, mismatched data types."
);
assert!(
v.value_length() == Self::VALUE_LENGTH,
"Value length of the array ({}) must equal to the byte width of the decimal ({})",
v.value_length(),
Self::VALUE_LENGTH,
);
assert_eq!(
v.data_ref().child_data()[0].null_count(),
0,
"The child array cannot contain null values."
);
let list_offset = v.offset();
let child_offset = child_data.offset();
let data_type = if Self::VALUE_LENGTH == 16 {
DataType::Decimal128(precision, scale)
} else {
DataType::Decimal256(precision, scale)
};
let builder = ArrayData::builder(data_type)
.len(v.len())
.add_buffer(child_data.buffers()[0].slice(child_offset))
.null_bit_buffer(v.data_ref().null_buffer().cloned())
.offset(list_offset);
let array_data = unsafe { builder.build_unchecked() };
Self::from(array_data)
}
pub const fn default_type() -> DataType {
Self::DEFAULT_TYPE
}
fn raw_value_data_ptr(&self) -> *const u8 {
self.value_data.as_ptr()
}
pub fn with_precision_and_scale(
self,
precision: u8,
scale: u8,
) -> Result<Self, ArrowError>
where
Self: Sized,
{
self.validate_precision_scale(precision, scale)?;
if precision < self.precision {
self.validate_data(precision)?;
}
let new_data_type = Self::TYPE_CONSTRUCTOR(precision, scale);
let data = self.data().clone().into_builder().data_type(new_data_type);
Ok(unsafe { data.build_unchecked().into() })
}
fn validate_precision_scale(
&self,
precision: u8,
scale: u8,
) -> Result<(), ArrowError> {
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
)));
}
let data_type = Self::TYPE_CONSTRUCTOR(self.precision, self.scale);
assert_eq!(self.data().data_type(), &data_type);
Ok(())
}
fn validate_data(&self, precision: u8) -> Result<(), ArrowError> {
match Self::VALUE_LENGTH {
16 => self
.as_any()
.downcast_ref::<Decimal128Array>()
.unwrap()
.validate_decimal_precision(precision),
32 => self
.as_any()
.downcast_ref::<Decimal256Array>()
.unwrap()
.validate_decimal_precision(precision),
other_width => {
panic!("invalid byte width {}", other_width);
}
}
}
}
impl Decimal128Array {
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)
}
fn validate_decimal_precision(&self, precision: u8) -> Result<(), ArrowError> {
(0..self.len()).try_for_each(|idx| {
if self.is_valid(idx) {
let decimal = unsafe { self.value_unchecked(idx) };
validate_decimal_precision(decimal.as_i128(), precision)
} else {
Ok(())
}
})
}
}
impl Decimal256Array {
fn validate_decimal_precision(&self, precision: u8) -> Result<(), ArrowError> {
(0..self.len()).try_for_each(|idx| {
if self.is_valid(idx) {
let raw_val = unsafe {
let pos = self.value_offset(idx);
std::slice::from_raw_parts(
self.raw_value_data_ptr().offset(pos as isize),
Self::VALUE_LENGTH as usize,
)
};
validate_decimal256_precision_with_lt_bytes(raw_val, precision)
} else {
Ok(())
}
})
}
}
impl<T: DecimalType> From<ArrayData> for DecimalArray<T> {
fn from(data: ArrayData) -> Self {
assert_eq!(
data.buffers().len(),
1,
"DecimalArray data should contain 1 buffer only (values)"
);
let values = data.buffers()[0].as_ptr();
let (precision, scale) = match (data.data_type(), Self::VALUE_LENGTH) {
(DataType::Decimal128(precision, scale), 16)
| (DataType::Decimal256(precision, scale), 32) => (*precision, *scale),
_ => panic!("Expected data type to be Decimal"),
};
Self {
data,
value_data: unsafe { RawPtrBox::new(values) },
precision,
scale,
_phantom: Default::default(),
}
}
}
fn build_decimal_array_from<T: DecimalType>(
null_buf: BooleanBufferBuilder,
buffer: Buffer,
) -> DecimalArray<T> {
let data = unsafe {
ArrayData::new_unchecked(
DecimalArray::<T>::default_type(),
null_buf.len(),
None,
Some(null_buf.into()),
0,
vec![buffer],
vec![],
)
};
DecimalArray::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(null_buf, buffer.into())
}
}
impl<Ptr: Into<i128>> FromIterator<Option<Ptr>> for Decimal128Array {
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 buffer: Buffer = iter
.map(|item| {
if let Some(a) = item {
null_buf.append(true);
a.into()
} else {
null_buf.append(false);
0
}
})
.collect();
build_decimal_array_from(null_buf, buffer)
}
}
impl<T: DecimalType> Array for DecimalArray<T> {
fn as_any(&self) -> &dyn Any {
self
}
fn data(&self) -> &ArrayData {
&self.data
}
fn into_data(self) -> ArrayData {
self.into()
}
}
impl<T: DecimalType> From<DecimalArray<T>> for ArrayData {
fn from(array: DecimalArray<T>) -> Self {
array.data
}
}
impl<T: DecimalType> std::fmt::Debug for DecimalArray<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"Decimal{}Array<{}, {}>\n[\n",
T::BYTE_LENGTH * 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, "]")
}
}
impl<'a, T: DecimalType> ArrayAccessor for &'a DecimalArray<T> {
type Item = Decimal<T>;
fn value(&self, index: usize) -> Self::Item {
DecimalArray::<T>::value(self, index)
}
unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
DecimalArray::<T>::value_unchecked(self, index)
}
}
impl<'a, T: DecimalType> IntoIterator for &'a DecimalArray<T> {
type Item = Option<Decimal<T>>;
type IntoIter = DecimalIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
DecimalIter::<'a, T>::new(self)
}
}
impl<'a, T: DecimalType> DecimalArray<T> {
pub fn iter(&'a self) -> DecimalIter<'a, T> {
DecimalIter::<'a, T>::new(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::builder::{Decimal128Builder, Decimal256Builder};
use crate::decimal::Decimal128;
use arrow_data::decimal::{DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE};
use arrow_schema::Field;
use num::{BigInt, Num};
#[test]
fn test_decimal_array() {
let values: [u8; 32] = [
192, 219, 180, 17, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 75, 238, 253,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
];
let array_data = ArrayData::builder(DataType::Decimal128(38, 6))
.len(2)
.add_buffer(Buffer::from(&values[..]))
.build()
.unwrap();
let decimal_array = Decimal128Array::from(array_data);
assert_eq!(8_887_000_000_i128, decimal_array.value(0).into());
assert_eq!(-8_887_000_000_i128, decimal_array.value(1).into());
assert_eq!(16, decimal_array.value_length());
}
#[test]
#[cfg(not(feature = "force_validate"))]
fn test_decimal_append_error_value() {
let mut decimal_builder = Decimal128Builder::with_capacity(10, 5, 3);
let mut result = decimal_builder.append_value(123456);
let mut error = result.unwrap_err();
assert_eq!(
"Invalid argument error: 123456 is too large to store in a Decimal128 of precision 5. Max is 99999",
error.to_string()
);
unsafe {
decimal_builder.disable_value_validation();
}
result = decimal_builder.append_value(123456);
assert!(result.is_ok());
decimal_builder.append_value(12345).unwrap();
let arr = decimal_builder.finish();
assert_eq!("12.345", arr.value_as_string(1));
decimal_builder = Decimal128Builder::new(2, 1);
result = decimal_builder.append_value(100);
error = result.unwrap_err();
assert_eq!(
"Invalid argument error: 100 is too large to store in a Decimal128 of precision 2. Max is 99",
error.to_string()
);
unsafe {
decimal_builder.disable_value_validation();
}
result = decimal_builder.append_value(100);
assert!(result.is_ok());
decimal_builder.append_value(99).unwrap();
result = decimal_builder.append_value(-100);
assert!(result.is_ok());
decimal_builder.append_value(-99).unwrap();
let arr = decimal_builder.finish();
assert_eq!("9.9", arr.value_as_string(1));
assert_eq!("-9.9", arr.value_as_string(3));
}
#[test]
fn test_decimal_from_iter_values() {
let array = Decimal128Array::from_iter_values(vec![-100, 0, 101].into_iter());
assert_eq!(array.len(), 3);
assert_eq!(array.data_type(), &DataType::Decimal128(38, 10));
assert_eq!(-100_i128, array.value(0).into());
assert!(!array.is_null(0));
assert_eq!(0_i128, array.value(1).into());
assert!(!array.is_null(1));
assert_eq!(101_i128, array.value(2).into());
assert!(!array.is_null(2));
}
#[test]
fn test_decimal_from_iter() {
let array: Decimal128Array =
vec![Some(-100), None, Some(101)].into_iter().collect();
assert_eq!(array.len(), 3);
assert_eq!(array.data_type(), &DataType::Decimal128(38, 10));
assert_eq!(-100_i128, array.value(0).into());
assert!(!array.is_null(0));
assert!(array.is_null(1));
assert_eq!(101_i128, array.value(2).into());
assert!(!array.is_null(2));
}
#[test]
fn test_decimal_iter() {
let data = vec![Some(-100), None, Some(101)];
let array: Decimal128Array = data.clone().into_iter().collect();
let collected: Vec<_> = array.iter().map(|d| d.map(|v| v.as_i128())).collect();
assert_eq!(data, collected);
}
#[test]
fn test_decimal_into_iter() {
let data = vec![Some(-100), None, Some(101)];
let array: Decimal128Array = data.clone().into_iter().collect();
let collected: Vec<_> =
array.into_iter().map(|d| d.map(|v| v.as_i128())).collect();
assert_eq!(data, collected);
}
#[test]
fn test_decimal_iter_sized() {
let data = vec![Some(-100), None, Some(101)];
let array: Decimal128Array = data.into_iter().collect();
let mut iter = array.into_iter();
assert_eq!(array.len(), 3);
assert_eq!(iter.size_hint(), (3, Some(3)));
iter.next().unwrap();
assert_eq!(iter.size_hint(), (2, Some(2)));
iter.next().unwrap();
iter.next().unwrap();
assert_eq!(iter.size_hint(), (0, Some(0)));
assert!(iter.next().is_none());
assert_eq!(iter.size_hint(), (0, Some(0)));
}
#[test]
fn test_decimal_array_value_as_string() {
let arr = [123450, -123450, 100, -100, 10, -10, 0]
.into_iter()
.map(Some)
.collect::<Decimal128Array>()
.with_precision_and_scale(6, 3)
.unwrap();
assert_eq!("123.450", arr.value_as_string(0));
assert_eq!("-123.450", arr.value_as_string(1));
assert_eq!("0.100", arr.value_as_string(2));
assert_eq!("-0.100", arr.value_as_string(3));
assert_eq!("0.010", arr.value_as_string(4));
assert_eq!("-0.010", arr.value_as_string(5));
assert_eq!("0.000", arr.value_as_string(6));
}
#[test]
fn test_decimal_array_with_precision_and_scale() {
let arr = Decimal128Array::from_iter_values([12345, 456, 7890, -123223423432432])
.with_precision_and_scale(20, 2)
.unwrap();
assert_eq!(arr.data_type(), &DataType::Decimal128(20, 2));
assert_eq!(arr.precision(), 20);
assert_eq!(arr.scale(), 2);
let actual: Vec<_> = (0..arr.len()).map(|i| arr.value_as_string(i)).collect();
let expected = vec!["123.45", "4.56", "78.90", "-1232234234324.32"];
assert_eq!(actual, expected);
}
#[test]
#[should_panic(
expected = "-123223423432432 is too small to store in a Decimal128 of precision 5. Min is -99999"
)]
fn test_decimal_array_with_precision_and_scale_out_of_range() {
Decimal128Array::from_iter_values([12345, 456, 7890, -123223423432432])
.with_precision_and_scale(5, 2)
.unwrap();
}
#[test]
#[should_panic(expected = "precision 40 is greater than max 38")]
fn test_decimal_array_with_precision_and_scale_invalid_precision() {
Decimal128Array::from_iter_values([12345, 456])
.with_precision_and_scale(40, 2)
.unwrap();
}
#[test]
#[should_panic(expected = "scale 40 is greater than max 38")]
fn test_decimal_array_with_precision_and_scale_invalid_scale() {
Decimal128Array::from_iter_values([12345, 456])
.with_precision_and_scale(20, 40)
.unwrap();
}
#[test]
#[should_panic(expected = "scale 10 is greater than precision 4")]
fn test_decimal_array_with_precision_and_scale_invalid_precision_and_scale() {
Decimal128Array::from_iter_values([12345, 456])
.with_precision_and_scale(4, 10)
.unwrap();
}
#[test]
fn test_decimal_array_fmt_debug() {
let arr = [Some(8887000000_i128), Some(-8887000000_i128), None]
.into_iter()
.collect::<Decimal128Array>()
.with_precision_and_scale(23, 6)
.unwrap();
assert_eq!(
"Decimal128Array<23, 6>\n[\n 8887.000000,\n -8887.000000,\n null,\n]",
format!("{:?}", arr)
);
}
#[test]
fn test_decimal_array_from_fixed_size_binary() {
let value_data = ArrayData::builder(DataType::FixedSizeBinary(16))
.offset(1)
.len(3)
.add_buffer(Buffer::from_slice_ref(&[99999_i128, 2, 34, 560]))
.null_bit_buffer(Some(Buffer::from_slice_ref(&[0b1010])))
.build()
.unwrap();
let binary_array = FixedSizeBinaryArray::from(value_data);
let decimal = Decimal128Array::from_fixed_size_binary_array(binary_array, 38, 1);
assert_eq!(decimal.len(), 3);
assert_eq!(decimal.value_as_string(0), "0.2".to_string());
assert!(decimal.is_null(1));
assert_eq!(decimal.value_as_string(2), "56.0".to_string());
}
#[test]
#[should_panic(
expected = "Value length of the array (8) must equal to the byte width of the decimal (16)"
)]
fn test_decimal_array_from_fixed_size_binary_wrong_length() {
let value_data = ArrayData::builder(DataType::FixedSizeBinary(8))
.offset(1)
.len(3)
.add_buffer(Buffer::from_slice_ref(&[99999_i64, 2, 34, 560]))
.null_bit_buffer(Some(Buffer::from_slice_ref(&[0b1010])))
.build()
.unwrap();
let binary_array = FixedSizeBinaryArray::from(value_data);
let _ = Decimal128Array::from_fixed_size_binary_array(binary_array, 38, 1);
}
#[test]
#[allow(deprecated)]
fn test_decimal_array_from_fixed_size_list() {
let value_data = ArrayData::builder(DataType::UInt8)
.offset(16)
.len(48)
.add_buffer(Buffer::from_slice_ref(&[99999_i128, 12, 34, 56]))
.build()
.unwrap();
let null_buffer = Buffer::from_slice_ref(&[0b101]);
let list_data_type = DataType::FixedSizeList(
Box::new(Field::new("item", DataType::UInt8, false)),
16,
);
let list_data = ArrayData::builder(list_data_type)
.len(2)
.null_bit_buffer(Some(null_buffer))
.offset(1)
.add_child_data(value_data)
.build()
.unwrap();
let list_array = FixedSizeListArray::from(list_data);
let decimal = Decimal128Array::from_fixed_size_list_array(list_array, 38, 0);
assert_eq!(decimal.len(), 2);
assert!(decimal.is_null(0));
assert_eq!(decimal.value_as_string(1), "56".to_string());
}
#[test]
#[allow(deprecated)]
#[should_panic(expected = "The child array cannot contain null values.")]
fn test_decimal_array_from_fixed_size_list_with_child_nulls_failed() {
let value_data = ArrayData::builder(DataType::UInt8)
.len(16)
.add_buffer(Buffer::from_slice_ref(&[12_i128]))
.null_bit_buffer(Some(Buffer::from_slice_ref(&[0b1010101010101010])))
.build()
.unwrap();
let list_data_type = DataType::FixedSizeList(
Box::new(Field::new("item", DataType::UInt8, false)),
16,
);
let list_data = ArrayData::builder(list_data_type)
.len(1)
.add_child_data(value_data)
.build()
.unwrap();
let list_array = FixedSizeListArray::from(list_data);
drop(Decimal128Array::from_fixed_size_list_array(
list_array, 38, 0,
));
}
#[test]
#[allow(deprecated)]
#[should_panic(
expected = "Value length of the array (8) must equal to the byte width of the decimal (16)"
)]
fn test_decimal_array_from_fixed_size_list_with_wrong_length() {
let value_data = ArrayData::builder(DataType::UInt8)
.len(16)
.add_buffer(Buffer::from_slice_ref(&[12_i128]))
.null_bit_buffer(Some(Buffer::from_slice_ref(&[0b1010101010101010])))
.build()
.unwrap();
let list_data_type = DataType::FixedSizeList(
Box::new(Field::new("item", DataType::UInt8, false)),
8,
);
let list_data = ArrayData::builder(list_data_type)
.len(2)
.add_child_data(value_data)
.build()
.unwrap();
let list_array = FixedSizeListArray::from(list_data);
drop(Decimal128Array::from_fixed_size_list_array(
list_array, 38, 0,
));
}
#[test]
fn test_decimal256_iter() {
let mut builder = Decimal256Builder::with_capacity(30, 76, 6);
let value = BigInt::from_str_radix("12345", 10).unwrap();
let decimal1 = Decimal256::from_big_int(&value, 76, 6).unwrap();
builder.append_value(&decimal1).unwrap();
builder.append_null();
let value = BigInt::from_str_radix("56789", 10).unwrap();
let decimal2 = Decimal256::from_big_int(&value, 76, 6).unwrap();
builder.append_value(&decimal2).unwrap();
let array: Decimal256Array = builder.finish();
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));
}
#[test]
fn test_from_iter_decimal128array() {
let array: Decimal128Array = vec![
Some(Decimal128::new_from_i128(38, 10, -100)),
None,
Some(Decimal128::new_from_i128(38, 10, 101)),
]
.into_iter()
.collect();
assert_eq!(array.len(), 3);
assert_eq!(array.data_type(), &DataType::Decimal128(38, 10));
assert_eq!(-100_i128, array.value(0).into());
assert!(!array.is_null(0));
assert!(array.is_null(1));
assert_eq!(101_i128, array.value(2).into());
assert!(!array.is_null(2));
}
#[test]
#[should_panic(
expected = "Trying to access an element at index 4 from a DecimalArray of length 3"
)]
fn test_fixed_size_binary_array_get_value_index_out_of_bound() {
let array = Decimal128Array::from_iter_values(vec![-100, 0, 101].into_iter());
array.value(4);
}
}