This is an automated email from the ASF dual-hosted git repository. alamb pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push: new d4ff12fbb6 Fix `can_cast_types` for temporal to `Utf8View` (#8328) d4ff12fbb6 is described below commit d4ff12fbb6d61d188919a3a9edcff53f2168aae8 Author: Piotr Findeisen <piotr.findei...@gmail.com> AuthorDate: Sat Sep 13 05:56:34 2025 -0700 Fix `can_cast_types` for temporal to `Utf8View` (#8328) `cast` and `cast_with_options` gained support for casting from temporal values to `Utf8View` in e613622fb69a7cc941bfb97bf1020bee580cfb86. This updates `can_cast_types` to match. This is necessary for DataFusion to use this casts, as DF consults `can_cast_types` first. --- arrow-cast/src/cast/mod.rs | 83 ++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs index e2bb3db859..117ad10b11 100644 --- a/arrow-cast/src/cast/mod.rs +++ b/arrow-cast/src/cast/mod.rs @@ -268,8 +268,7 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool { (Utf8 | LargeUtf8, Utf8View) => true, (BinaryView, Binary | LargeBinary | Utf8 | LargeUtf8 | Utf8View) => true, (Utf8View | Utf8 | LargeUtf8, _) => to_type.is_numeric() && to_type != &Float16, - (_, Utf8 | LargeUtf8) => from_type.is_primitive(), - (_, Utf8View) => from_type.is_numeric(), + (_, Utf8 | Utf8View | LargeUtf8) => from_type.is_primitive(), (_, Binary | LargeBinary) => from_type.is_integer(), @@ -5775,28 +5774,9 @@ mod tests { assert!(c.is_null(2)); } - #[test] - fn test_cast_date32_to_string() { - let array = Date32Array::from(vec![10000, 17890]); - let b = cast(&array, &DataType::Utf8).unwrap(); - let c = b.as_any().downcast_ref::<StringArray>().unwrap(); - assert_eq!(&DataType::Utf8, c.data_type()); - assert_eq!("1997-05-19", c.value(0)); - assert_eq!("2018-12-25", c.value(1)); - } - - #[test] - fn test_cast_date64_to_string() { - let array = Date64Array::from(vec![10000 * 86400000, 17890 * 86400000]); - let b = cast(&array, &DataType::Utf8).unwrap(); - let c = b.as_any().downcast_ref::<StringArray>().unwrap(); - assert_eq!(&DataType::Utf8, c.data_type()); - assert_eq!("1997-05-19T00:00:00", c.value(0)); - assert_eq!("2018-12-25T00:00:00", c.value(1)); - } - - macro_rules! assert_cast_timestamp_to_string { + macro_rules! assert_cast { ($array:expr, $datatype:expr, $output_array_type: ty, $expected:expr) => {{ + assert!(can_cast_types($array.data_type(), &$datatype)); let out = cast(&$array, &$datatype).unwrap(); let actual = out .as_any() @@ -5807,6 +5787,7 @@ mod tests { assert_eq!(actual, $expected); }}; ($array:expr, $datatype:expr, $output_array_type: ty, $options:expr, $expected:expr) => {{ + assert!(can_cast_types($array.data_type(), &$datatype)); let out = cast_with_options(&$array, &$datatype, &$options).unwrap(); let actual = out .as_any() @@ -5818,6 +5799,44 @@ mod tests { }}; } + #[test] + fn test_cast_date32_to_string() { + let array = Date32Array::from(vec![Some(0), Some(10000), Some(13036), Some(17890), None]); + let expected = vec![ + Some("1970-01-01"), + Some("1997-05-19"), + Some("2005-09-10"), + Some("2018-12-25"), + None, + ]; + + assert_cast!(array, DataType::Utf8View, StringViewArray, expected); + assert_cast!(array, DataType::Utf8, StringArray, expected); + assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected); + } + + #[test] + fn test_cast_date64_to_string() { + let array = Date64Array::from(vec![ + Some(0), + Some(10000 * 86400000), + Some(13036 * 86400000), + Some(17890 * 86400000), + None, + ]); + let expected = vec![ + Some("1970-01-01T00:00:00"), + Some("1997-05-19T00:00:00"), + Some("2005-09-10T00:00:00"), + Some("2018-12-25T00:00:00"), + None, + ]; + + assert_cast!(array, DataType::Utf8View, StringViewArray, expected); + assert_cast!(array, DataType::Utf8, StringArray, expected); + assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected); + } + #[test] fn test_cast_date32_to_timestamp_and_timestamp_with_timezone() { let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu @@ -6020,9 +6039,9 @@ mod tests { None, ]; - assert_cast_timestamp_to_string!(array, DataType::Utf8View, StringViewArray, expected); - assert_cast_timestamp_to_string!(array, DataType::Utf8, StringArray, expected); - assert_cast_timestamp_to_string!(array, DataType::LargeUtf8, LargeStringArray, expected); + assert_cast!(array, DataType::Utf8View, StringViewArray, expected); + assert_cast!(array, DataType::Utf8, StringArray, expected); + assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected); } #[test] @@ -6044,21 +6063,21 @@ mod tests { Some("2018-12-25 00:00:02.001000"), None, ]; - assert_cast_timestamp_to_string!( + assert_cast!( array_without_tz, DataType::Utf8View, StringViewArray, cast_options, expected ); - assert_cast_timestamp_to_string!( + assert_cast!( array_without_tz, DataType::Utf8, StringArray, cast_options, expected ); - assert_cast_timestamp_to_string!( + assert_cast!( array_without_tz, DataType::LargeUtf8, LargeStringArray, @@ -6074,21 +6093,21 @@ mod tests { Some("2018-12-25 05:45:02.001000"), None, ]; - assert_cast_timestamp_to_string!( + assert_cast!( array_with_tz, DataType::Utf8View, StringViewArray, cast_options, expected ); - assert_cast_timestamp_to_string!( + assert_cast!( array_with_tz, DataType::Utf8, StringArray, cast_options, expected ); - assert_cast_timestamp_to_string!( + assert_cast!( array_with_tz, DataType::LargeUtf8, LargeStringArray,