viirya commented on code in PR #2383:
URL: https://github.com/apache/arrow-rs/pull/2383#discussion_r940952692
##########
arrow/src/array/array_decimal.rs:
##########
@@ -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)"
Review Comment:
We may show `Decimal128Array` or `Decimal256Array` based on byte width.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]