Skip to content

Commit 194cba1

Browse files
committed
ARROW-10818: [Rust] Implement Decimal128/256
1 parent fb44622 commit 194cba1

38 files changed

Lines changed: 2345 additions & 316 deletions

rust/arrow/src/array/array.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ pub fn make_array(data: ArrayData) -> ArrayRef {
318318
dt => panic!("Unexpected dictionary key type {:?}", dt),
319319
},
320320
DataType::Null => Arc::new(NullArray::from(data)) as ArrayRef,
321-
DataType::Decimal(_, _) => Arc::new(DecimalArray::from(data)) as ArrayRef,
321+
DataType::Decimal128(_, _) => Arc::new(Decimal128Array::from(data)) as ArrayRef,
322+
DataType::Decimal256(_, _) => Arc::new(Decimal256Array::from(data)) as ArrayRef,
322323
dt => panic!("Unexpected data type {:?}", dt),
323324
}
324325
}
@@ -432,8 +433,11 @@ pub fn new_null_array(data_type: &DataType, length: usize) -> ArrayRef {
432433
vec![new_empty_array(value.as_ref()).data().clone()],
433434
))
434435
}
435-
DataType::Decimal(_, _) => {
436-
unimplemented!("Creating null Decimal array not yet supported")
436+
DataType::Decimal128(_, _) => {
437+
unimplemented!();
438+
}
439+
DataType::Decimal256(_, _) => {
440+
unimplemented!();
437441
}
438442
}
439443
}

rust/arrow/src/array/array_binary.rs

Lines changed: 2 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use std::convert::{From, TryInto};
18+
use std::convert::From;
1919
use std::fmt;
2020
use std::mem;
2121
use std::{any::Any, iter::FromIterator};
@@ -26,6 +26,7 @@ use super::{
2626
};
2727
use crate::buffer::Buffer;
2828
use crate::error::ArrowError;
29+
2930
use crate::util::bit_util;
3031
use crate::{buffer::MutableBuffer, datatypes::DataType};
3132

@@ -589,149 +590,6 @@ impl Array for FixedSizeBinaryArray {
589590
}
590591
}
591592

592-
/// A type of `DecimalArray` whose elements are binaries.
593-
pub struct DecimalArray {
594-
data: ArrayData,
595-
value_data: RawPtrBox<u8>,
596-
precision: usize,
597-
scale: usize,
598-
length: i32,
599-
}
600-
601-
impl DecimalArray {
602-
/// Returns the element at index `i` as i128.
603-
pub fn value(&self, i: usize) -> i128 {
604-
assert!(i < self.data.len(), "DecimalArray out of bounds access");
605-
let offset = i.checked_add(self.data.offset()).unwrap();
606-
let raw_val = unsafe {
607-
let pos = self.value_offset_at(offset);
608-
std::slice::from_raw_parts(
609-
self.value_data.as_ptr().offset(pos as isize),
610-
(self.value_offset_at(offset + 1) - pos) as usize,
611-
)
612-
};
613-
let as_array = raw_val.try_into();
614-
match as_array {
615-
Ok(v) if raw_val.len() == 16 => i128::from_le_bytes(v),
616-
_ => panic!("DecimalArray elements are not 128bit integers."),
617-
}
618-
}
619-
620-
/// Returns the offset for the element at index `i`.
621-
///
622-
/// Note this doesn't do any bound checking, for performance reason.
623-
#[inline]
624-
pub fn value_offset(&self, i: usize) -> i32 {
625-
self.value_offset_at(self.data.offset() + i)
626-
}
627-
628-
/// Returns the length for an element.
629-
///
630-
/// All elements have the same length as the array is a fixed size.
631-
#[inline]
632-
pub fn value_length(&self) -> i32 {
633-
self.length
634-
}
635-
636-
/// Returns a clone of the value data buffer
637-
pub fn value_data(&self) -> Buffer {
638-
self.data.buffers()[0].clone()
639-
}
640-
641-
#[inline]
642-
fn value_offset_at(&self, i: usize) -> i32 {
643-
self.length * i as i32
644-
}
645-
646-
pub fn from_fixed_size_list_array(
647-
v: FixedSizeListArray,
648-
precision: usize,
649-
scale: usize,
650-
) -> Self {
651-
assert_eq!(
652-
v.data_ref().child_data()[0].child_data().len(),
653-
0,
654-
"DecimalArray can only be created from list array of u8 values \
655-
(i.e. FixedSizeList<PrimitiveArray<u8>>)."
656-
);
657-
assert_eq!(
658-
v.data_ref().child_data()[0].data_type(),
659-
&DataType::UInt8,
660-
"DecimalArray can only be created from FixedSizeList<u8> arrays, mismatched data types."
661-
);
662-
663-
let mut builder = ArrayData::builder(DataType::Decimal(precision, scale))
664-
.len(v.len())
665-
.add_buffer(v.data_ref().child_data()[0].buffers()[0].clone());
666-
if let Some(bitmap) = v.data_ref().null_bitmap() {
667-
builder = builder.null_bit_buffer(bitmap.bits.clone())
668-
}
669-
670-
let data = builder.build();
671-
Self::from(data)
672-
}
673-
pub fn precision(&self) -> usize {
674-
self.precision
675-
}
676-
677-
pub fn scale(&self) -> usize {
678-
self.scale
679-
}
680-
}
681-
682-
impl From<ArrayData> for DecimalArray {
683-
fn from(data: ArrayData) -> Self {
684-
assert_eq!(
685-
data.buffers().len(),
686-
1,
687-
"DecimalArray data should contain 1 buffer only (values)"
688-
);
689-
let values = data.buffers()[0].as_ptr();
690-
let (precision, scale) = match data.data_type() {
691-
DataType::Decimal(precision, scale) => (*precision, *scale),
692-
_ => panic!("Expected data type to be Decimal"),
693-
};
694-
let length = 16;
695-
Self {
696-
data,
697-
value_data: unsafe { RawPtrBox::new(values) },
698-
precision,
699-
scale,
700-
length,
701-
}
702-
}
703-
}
704-
705-
impl fmt::Debug for DecimalArray {
706-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707-
write!(f, "DecimalArray<{}, {}>\n[\n", self.precision, self.scale)?;
708-
print_long_array(self, f, |array, index, f| {
709-
fmt::Debug::fmt(&array.value(index), f)
710-
})?;
711-
write!(f, "]")
712-
}
713-
}
714-
715-
impl Array for DecimalArray {
716-
fn as_any(&self) -> &Any {
717-
self
718-
}
719-
720-
fn data(&self) -> &ArrayData {
721-
&self.data
722-
}
723-
724-
/// Returns the total number of bytes of memory occupied by the buffers owned by this [DecimalArray].
725-
fn get_buffer_memory_size(&self) -> usize {
726-
self.data.get_buffer_memory_size()
727-
}
728-
729-
/// Returns the total number of bytes of memory occupied physically by this [DecimalArray].
730-
fn get_array_memory_size(&self) -> usize {
731-
self.data.get_array_memory_size() + mem::size_of_val(self)
732-
}
733-
}
734-
735593
#[cfg(test)]
736594
mod tests {
737595
use crate::{
@@ -1119,39 +977,4 @@ mod tests {
1119977
format!("{:?}", arr)
1120978
);
1121979
}
1122-
1123-
#[test]
1124-
fn test_decimal_array() {
1125-
// let val_8887: [u8; 16] = [192, 219, 180, 17, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1126-
// let val_neg_8887: [u8; 16] = [64, 36, 75, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255];
1127-
let values: [u8; 32] = [
1128-
192, 219, 180, 17, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 75, 238, 253,
1129-
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1130-
];
1131-
let array_data = ArrayData::builder(DataType::Decimal(23, 6))
1132-
.len(2)
1133-
.add_buffer(Buffer::from(&values[..]))
1134-
.build();
1135-
let decimal_array = DecimalArray::from(array_data);
1136-
assert_eq!(8_887_000_000, decimal_array.value(0));
1137-
assert_eq!(-8_887_000_000, decimal_array.value(1));
1138-
assert_eq!(16, decimal_array.value_length());
1139-
}
1140-
1141-
#[test]
1142-
fn test_decimal_array_fmt_debug() {
1143-
let values: [u8; 32] = [
1144-
192, 219, 180, 17, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 75, 238, 253,
1145-
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1146-
];
1147-
let array_data = ArrayData::builder(DataType::Decimal(23, 6))
1148-
.len(2)
1149-
.add_buffer(Buffer::from(&values[..]))
1150-
.build();
1151-
let arr = DecimalArray::from(array_data);
1152-
assert_eq!(
1153-
"DecimalArray<23, 6>\n[\n 8887000000,\n -8887000000,\n]",
1154-
format!("{:?}", arr)
1155-
);
1156-
}
1157980
}

0 commit comments

Comments
 (0)