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

[arrow-rs] branch master updated: Support casting from unsigned numeric to Decimal256 (#3273)

This is an automated email from the ASF dual-hosted git repository.

viirya 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 7c75a66ee Support casting from unsigned numeric to Decimal256 (#3273)
7c75a66ee is described below

commit 7c75a66ee30f14c84984e4ee9aabca737f62f440
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Tue Dec 6 00:26:40 2022 -0800

    Support casting from unsigned numeric to Decimal256 (#3273)
---
 arrow-buffer/src/bigint.rs |  4 +++
 arrow-cast/src/cast.rs     | 80 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/arrow-buffer/src/bigint.rs b/arrow-buffer/src/bigint.rs
index 23400b4a3..cfe14fb39 100644
--- a/arrow-buffer/src/bigint.rs
+++ b/arrow-buffer/src/bigint.rs
@@ -493,6 +493,10 @@ define_as_primitive!(i8);
 define_as_primitive!(i16);
 define_as_primitive!(i32);
 define_as_primitive!(i64);
+define_as_primitive!(u8);
+define_as_primitive!(u16);
+define_as_primitive!(u32);
+define_as_primitive!(u64);
 
 impl ToPrimitive for i256 {
     fn to_i64(&self) -> Option<i64> {
diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs
index 7bb3aeb96..ebdefb18e 100644
--- a/arrow-cast/src/cast.rs
+++ b/arrow-cast/src/cast.rs
@@ -133,6 +133,7 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
         (Decimal256(_, _), Decimal128(_, _)) => true,
         // unsigned integer to decimal
         (UInt8 | UInt16 | UInt32 | UInt64, Decimal128(_, _)) |
+        (UInt8 | UInt16 | UInt32 | UInt64, Decimal256(_, _)) |
         // signed numeric to decimal
         (Null | Int8 | Int16 | Int32 | Int64 | Float32 | Float64, Decimal128(_, _)) |
         (Null | Int8 | Int16 | Int32 | Int64 | Float32 | Float64, Decimal256(_, _)) |
@@ -954,7 +955,34 @@ pub fn cast_with_options(
         (_, Decimal256(precision, scale)) => {
             // cast data to decimal
             match from_type {
-                // TODO now just support signed numeric to decimal, support decimal to numeric later
+                UInt8 => cast_integer_to_decimal::<_, Decimal256Type, _>(
+                    as_primitive_array::<UInt8Type>(array),
+                    *precision,
+                    *scale,
+                    i256::from_i128(10_i128),
+                    cast_options,
+                ),
+                UInt16 => cast_integer_to_decimal::<_, Decimal256Type, _>(
+                    as_primitive_array::<UInt16Type>(array),
+                    *precision,
+                    *scale,
+                    i256::from_i128(10_i128),
+                    cast_options,
+                ),
+                UInt32 => cast_integer_to_decimal::<_, Decimal256Type, _>(
+                    as_primitive_array::<UInt32Type>(array),
+                    *precision,
+                    *scale,
+                    i256::from_i128(10_i128),
+                    cast_options,
+                ),
+                UInt64 => cast_integer_to_decimal::<_, Decimal256Type, _>(
+                    as_primitive_array::<UInt64Type>(array),
+                    *precision,
+                    *scale,
+                    i256::from_i128(10_i128),
+                    cast_options,
+                ),
                 Int8 => cast_integer_to_decimal::<_, Decimal256Type, _>(
                     as_primitive_array::<Int8Type>(array),
                     *precision,
@@ -4197,9 +4225,53 @@ mod tests {
 
     #[test]
     fn test_cast_numeric_to_decimal256() {
-        // test negative cast type
-        let decimal_type = DataType::Decimal256(58, 6);
-        assert!(!can_cast_types(&DataType::UInt64, &decimal_type));
+        let decimal_type = DataType::Decimal256(76, 6);
+        // u8, u16, u32, u64
+        let input_datas = vec![
+            Arc::new(UInt8Array::from(vec![
+                Some(1),
+                Some(2),
+                Some(3),
+                None,
+                Some(5),
+            ])) as ArrayRef, // u8
+            Arc::new(UInt16Array::from(vec![
+                Some(1),
+                Some(2),
+                Some(3),
+                None,
+                Some(5),
+            ])) as ArrayRef, // u16
+            Arc::new(UInt32Array::from(vec![
+                Some(1),
+                Some(2),
+                Some(3),
+                None,
+                Some(5),
+            ])) as ArrayRef, // u32
+            Arc::new(UInt64Array::from(vec![
+                Some(1),
+                Some(2),
+                Some(3),
+                None,
+                Some(5),
+            ])) as ArrayRef, // u64
+        ];
+
+        for array in input_datas {
+            generate_cast_test_case!(
+                &array,
+                Decimal256Array,
+                &decimal_type,
+                vec![
+                    Some(i256::from_i128(1000000_i128)),
+                    Some(i256::from_i128(2000000_i128)),
+                    Some(i256::from_i128(3000000_i128)),
+                    None,
+                    Some(i256::from_i128(5000000_i128))
+                ]
+            );
+        }
 
         // i8, i16, i32, i64
         let input_datas = vec![