From fee692189f655900d85b5e3538be9499b422c08b Mon Sep 17 00:00:00 2001 From: Jonah Gao Date: Mon, 15 Apr 2024 19:59:49 +0800 Subject: [PATCH] fix: panic when casting `ListArray` to `FixedSizeList` (#5643) --- arrow-cast/src/cast/list.rs | 6 ++++-- arrow-cast/src/cast/mod.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arrow-cast/src/cast/list.rs b/arrow-cast/src/cast/list.rs index 33faacdccb92..2ceab1d0c8c2 100644 --- a/arrow-cast/src/cast/list.rs +++ b/arrow-cast/src/cast/list.rs @@ -63,7 +63,9 @@ where { let cap = array.len() * size as usize; - let mut nulls = (cast_options.safe || array.null_count() != 0).then(|| { + // Whether the resulting array may contain null lists + let nullable = cast_options.safe || array.null_count() != 0; + let mut nulls = nullable.then(|| { let mut buffer = BooleanBufferBuilder::new(array.len()); match array.nulls() { Some(n) => buffer.append_buffer(n.inner()), @@ -74,7 +76,7 @@ where // Nulls in FixedSizeListArray take up space and so we must pad the values let values = array.values().to_data(); - let mut mutable = MutableArrayData::new(vec![&values], cast_options.safe, cap); + let mut mutable = MutableArrayData::new(vec![&values], nullable, cap); // The end position in values of the last incorrectly-sized list slice let mut last_pos = 0; for (idx, w) in array.offsets().windows(2).enumerate() { diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs index d559715911bb..8b7579c4cfc0 100644 --- a/arrow-cast/src/cast/mod.rs +++ b/arrow-cast/src/cast/mod.rs @@ -6806,6 +6806,27 @@ mod tests { 3, )) as ArrayRef; assert_eq!(expected.as_ref(), res.as_ref()); + + // The safe option is false and the source array contains a null list. + // issue: https://github.com/apache/arrow-rs/issues/5642 + let array = Arc::new(ListArray::from_iter_primitive::(vec![ + Some(vec![Some(1), Some(2), Some(3)]), + None, + ])) as ArrayRef; + let res = cast_with_options( + array.as_ref(), + &DataType::FixedSizeList(Arc::new(Field::new("item", DataType::Int32, true)), 3), + &CastOptions { + safe: false, + ..Default::default() + }, + ) + .unwrap(); + let expected = Arc::new(FixedSizeListArray::from_iter_primitive::( + vec![Some(vec![Some(1), Some(2), Some(3)]), None], + 3, + )) as ArrayRef; + assert_eq!(expected.as_ref(), res.as_ref()); } #[test]