From d9bf63822b32a03a8b8ca2864e8fb4133e53b498 Mon Sep 17 00:00:00 2001 From: comphead Date: Fri, 31 Mar 2023 15:05:59 -0700 Subject: [PATCH 1/5] Support CAST Decimal to Utf8 --- arrow-cast/src/cast.rs | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs index 9886decd9ddc..2796f5a3317a 100644 --- a/arrow-cast/src/cast.rs +++ b/arrow-cast/src/cast.rs @@ -145,6 +145,9 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool { // decimal to signed numeric (Decimal128(_, _), Null | Int8 | Int16 | Int32 | Int64 | Float32 | Float64) | (Decimal256(_, _), Null | Int8 | Int16 | Int32 | Int64 | Float32 | Float64) => true, + // decimal to Utf8 + (Decimal128(_, _), Utf8 | LargeUtf8) => true, + (Decimal256(_, _), Utf8 | LargeUtf8) => true, // Utf8 to decimal (Utf8 | LargeUtf8, Decimal128(_, _)) => true, (Utf8 | LargeUtf8, Decimal256(_, _)) => true, @@ -810,6 +813,8 @@ pub fn cast_with_options( x as f64 / 10_f64.powi(*scale as i32) }) } + Utf8 => value_to_string::(array), + LargeUtf8 => value_to_string::(array), Null => Ok(new_null_array(to_type, array.len())), _ => Err(ArrowError::CastError(format!( "Casting from {from_type:?} to {to_type:?} not supported" @@ -877,6 +882,8 @@ pub fn cast_with_options( x.to_f64().unwrap() / 10_f64.powi(*scale as i32) }) } + Utf8 => value_to_string::(array), + LargeUtf8 => value_to_string::(array), Null => Ok(new_null_array(to_type, array.len())), _ => Err(ArrowError::CastError(format!( "Casting from {from_type:?} to {to_type:?} not supported" @@ -8132,4 +8139,68 @@ mod tests { .unwrap(); assert_eq!(1672531200000000000, c.value(0)); } + + #[test] + fn test_cast_decimal_to_utf8() { + fn test_decimal_to_string( + input_type: DataType, + output_type: DataType, + array: PrimitiveArray, + ) { + assert!(can_cast_types(&input_type, &output_type)); + + let b = cast(&array, &output_type).unwrap(); + + assert_eq!(b.data_type(), &output_type); + let c = b + .as_any() + .downcast_ref::>>() + .unwrap(); + + assert_eq!("1123.454", c.value(0)); + assert_eq!("2123.456", c.value(1)); + assert_eq!("-3123.453", c.value(2)); + assert_eq!("-3123.456", c.value(3)); + assert_eq!("0.000", c.value(4)); + assert_eq!("0.123", c.value(5)); + assert_eq!("1234.567", c.value(6)); + assert_eq!("-1234.567", c.value(7)); + assert!(c.is_null(8)); + } + let array128: Vec> = vec![ + Some(1123454), + Some(2123456), + Some(-3123453), + Some(-3123456), + Some(0), + Some(123), + Some(123456789), + Some(-123456789), + None, + ]; + + let array256: Vec> = + array128.iter().map(|v| v.map(i256::from_i128)).collect(); + + test_decimal_to_string::( + DataType::Decimal128(7, 3), + DataType::Utf8, + create_decimal_array(array128.clone(), 7, 3).unwrap(), + ); + test_decimal_to_string::( + DataType::Decimal128(7, 3), + DataType::LargeUtf8, + create_decimal_array(array128, 7, 3).unwrap(), + ); + test_decimal_to_string::( + DataType::Decimal128(7, 3), + DataType::Utf8, + create_decimal256_array(array256.clone(), 7, 3).unwrap(), + ); + test_decimal_to_string::( + DataType::Decimal128(7, 3), + DataType::LargeUtf8, + create_decimal256_array(array256, 7, 3).unwrap(), + ); + } } From b3548f66b2ed8df249c356e7bb4eb1e837335454 Mon Sep 17 00:00:00 2001 From: comphead Date: Fri, 31 Mar 2023 17:06:50 -0700 Subject: [PATCH 2/5] remove null --- arrow/tests/array_cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/tests/array_cast.rs b/arrow/tests/array_cast.rs index 2807bbd79b83..f5729d2197ba 100644 --- a/arrow/tests/array_cast.rs +++ b/arrow/tests/array_cast.rs @@ -186,7 +186,7 @@ fn get_arrays_of_all_types() -> Vec { Arc::new(DurationMicrosecondArray::from(vec![1000, 2000])), Arc::new(DurationNanosecondArray::from(vec![1000, 2000])), Arc::new( - create_decimal_array(vec![Some(1), Some(2), Some(3), None], 38, 0).unwrap(), + create_decimal_array(vec![Some(1), Some(2), Some(3)], 38, 0).unwrap(), ), make_dictionary_primitive::(vec![1, 2]), make_dictionary_primitive::(vec![1, 2]), From 7d3e7f1a09fd33477b34a6bfcf6cf078095b96ee Mon Sep 17 00:00:00 2001 From: comphead Date: Fri, 31 Mar 2023 17:14:09 -0700 Subject: [PATCH 3/5] fmt --- arrow/tests/array_cast.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arrow/tests/array_cast.rs b/arrow/tests/array_cast.rs index f5729d2197ba..96a4f2b41f3c 100644 --- a/arrow/tests/array_cast.rs +++ b/arrow/tests/array_cast.rs @@ -185,9 +185,7 @@ fn get_arrays_of_all_types() -> Vec { Arc::new(DurationMillisecondArray::from(vec![1000, 2000])), Arc::new(DurationMicrosecondArray::from(vec![1000, 2000])), Arc::new(DurationNanosecondArray::from(vec![1000, 2000])), - Arc::new( - create_decimal_array(vec![Some(1), Some(2), Some(3)], 38, 0).unwrap(), - ), + Arc::new(create_decimal_array(vec![Some(1), Some(2), Some(3)], 38, 0).unwrap()), make_dictionary_primitive::(vec![1, 2]), make_dictionary_primitive::(vec![1, 2]), make_dictionary_primitive::(vec![1, 2]), From 0928b87e5e1624add68e90b6a2bf3cebc4a2c373 Mon Sep 17 00:00:00 2001 From: comphead Date: Sat, 1 Apr 2023 09:50:16 -0700 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: Raphael Taylor-Davies <1781103+tustvold@users.noreply.github.com> --- arrow-cast/src/cast.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs index 2796f5a3317a..2c06d737c5e2 100644 --- a/arrow-cast/src/cast.rs +++ b/arrow-cast/src/cast.rs @@ -8142,8 +8142,7 @@ mod tests { #[test] fn test_cast_decimal_to_utf8() { - fn test_decimal_to_string( - input_type: DataType, + fn test_decimal_to_string( output_type: DataType, array: PrimitiveArray, ) { @@ -8152,10 +8151,7 @@ mod tests { let b = cast(&array, &output_type).unwrap(); assert_eq!(b.data_type(), &output_type); - let c = b - .as_any() - .downcast_ref::>>() - .unwrap(); + let c = b.as_string::() assert_eq!("1123.454", c.value(0)); assert_eq!("2123.456", c.value(1)); From d6b6478bdf48dec3544f95b0d9200235baf18523 Mon Sep 17 00:00:00 2001 From: comphead Date: Sat, 1 Apr 2023 10:24:41 -0700 Subject: [PATCH 5/5] comments --- arrow-cast/src/cast.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs index 2c06d737c5e2..8444865f8f37 100644 --- a/arrow-cast/src/cast.rs +++ b/arrow-cast/src/cast.rs @@ -8142,16 +8142,14 @@ mod tests { #[test] fn test_cast_decimal_to_utf8() { - fn test_decimal_to_string( + fn test_decimal_to_string( output_type: DataType, array: PrimitiveArray, ) { - assert!(can_cast_types(&input_type, &output_type)); - let b = cast(&array, &output_type).unwrap(); assert_eq!(b.data_type(), &output_type); - let c = b.as_string::() + let c = b.as_string::(); assert_eq!("1123.454", c.value(0)); assert_eq!("2123.456", c.value(1)); @@ -8179,22 +8177,18 @@ mod tests { array128.iter().map(|v| v.map(i256::from_i128)).collect(); test_decimal_to_string::( - DataType::Decimal128(7, 3), DataType::Utf8, create_decimal_array(array128.clone(), 7, 3).unwrap(), ); test_decimal_to_string::( - DataType::Decimal128(7, 3), DataType::LargeUtf8, create_decimal_array(array128, 7, 3).unwrap(), ); test_decimal_to_string::( - DataType::Decimal128(7, 3), DataType::Utf8, create_decimal256_array(array256.clone(), 7, 3).unwrap(), ); test_decimal_to_string::( - DataType::Decimal128(7, 3), DataType::LargeUtf8, create_decimal256_array(array256, 7, 3).unwrap(), );