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 3577093f26 fix(arrow-select): handle all-empty run arrays in
concat_run_arrays (#10782)
3577093f26 is described below
commit 3577093f26591aee806a9133c891b6b8e5255477
Author: Thor <[email protected]>
AuthorDate: Mon Aug 24 16:56:55 2026 -0500
fix(arrow-select): handle all-empty run arrays in concat_run_arrays (#10782)
concat_run_arrays filters out any input RunArray whose run_ends() is
empty before concatenating their values. When every input is filtered
out this way (e.g. concatenating two zero-length slices of a nested
RunEndEncoded struct field), the resulting values_slices is empty and
falls through to concat(&[]), which errors because a type-erased &[&dyn
Array] with no elements carries no DataType to build a result from.
Add an early return for the empty-after-filter case, building a valid
zero-length array from the original (non-empty) input's DataType
instead.
# Which issue does this PR close?
<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax.
-->
- Closes #10781.
# Rationale for this change
`concat_run_arrays` should return a valid array instead of an error when
empty run_ends are passed into it.
# What changes are included in this PR?
A small empty run arrays check that returns an empty array of the data
type instead.
# Are these changes tested?
Yes a unit test was added
# Are there any user-facing changes?
No
---------
Co-authored-by: Jeffrey Vo <[email protected]>
---
arrow-select/src/concat.rs | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arrow-select/src/concat.rs b/arrow-select/src/concat.rs
index e1384edbc5..eece5ffbaf 100644
--- a/arrow-select/src/concat.rs
+++ b/arrow-select/src/concat.rs
@@ -424,6 +424,12 @@ where
.filter(|x| !x.run_ends().is_empty())
.collect();
+ if run_arrays.is_empty() {
+ // If all input arrays are empty then handle here otherwise we
+ // lose the type below
+ return Ok(new_empty_array(arrays[0].data_type()));
+ }
+
// The run ends need to be adjusted by the sum of the lengths of the
previous arrays.
let needed_run_end_adjustments = std::iter::once(R::default_value())
.chain(
@@ -1905,6 +1911,24 @@ mod tests {
assert_eq!(expected, actual);
}
+ #[test]
+ fn test_concat_run_array_all_empty() {
+ let run_ends1 = Int32Array::from(vec![2, 4]);
+ let values1 = Int32Array::from(vec![10, 20]);
+ let array1 = RunArray::try_new(&run_ends1, &values1).unwrap();
+ let array1 = array1.slice(0, 0);
+
+ let run_ends2 = Int32Array::from(vec![1, 4]);
+ let values2 = Int32Array::from(vec![30, 40]);
+ let array2 = RunArray::try_new(&run_ends2, &values2).unwrap();
+ let array2 = array2.slice(0, 0);
+
+ let result = concat(&[&array1, &array2]).unwrap();
+ let result_run_array: &arrow_array::RunArray<Int32Type> =
result.as_run();
+ assert_eq!(result_run_array.len(), 0);
+ assert_eq!(result_run_array.data_type(), array1.data_type());
+ }
+
#[test]
fn test_concat_run_array_matching_first_last_value() {
// Create a run array with run ends [2, 4, 7] and values [10, 20, 30]