You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by al...@apache.org on 2026/10/22 15:15:01 UTC
(arrow-rs) branch 57_maintenance updated: [57_maintenance] fix(arrow-data): fix gaps in ListView equality (#11802)
This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch 57_maintenance
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/57_maintenance by this push:
new 9e44357a6b [57_maintenance] fix(arrow-data): fix gaps in ListView equality (#11802)
9e44357a6b is described below
commit 9e44357a6bbc050e84a802af731066ee2012916a
Author: Jeffrey Vo <je...@gmail.com>
AuthorDate: Fri Oct 23 00:14:36 2026 +0900
[57_maintenance] fix(arrow-data): fix gaps in ListView equality (#11802)
- Backport https://github.com/apache/arrow-rs/pull/11345
- For inclusion in https://github.com/apache/arrow-rs/issues/11666
Cherry-pick of
https://github.com/apache/arrow-rs/commit/862b1e065b602400784268df9ded5d0a18710eed
Co-authored-by: Neil Conway <ne...@gmail.com>
---
arrow-data/src/equal/list_view.rs | 23 +++++++++++++++--------
arrow-data/src/equal/mod.rs | 3 +++
arrow/tests/array_equal.rs | 26 ++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/arrow-data/src/equal/list_view.rs b/arrow-data/src/equal/list_view.rs
index c7cb31db90..299414b135 100644
--- a/arrow-data/src/equal/list_view.rs
+++ b/arrow-data/src/equal/list_view.rs
@@ -17,7 +17,7 @@
use crate::ArrayData;
use crate::data::count_nulls;
-use crate::equal::equal_values;
+use crate::equal::equal_range;
use arrow_buffer::ArrowNativeType;
use num_integer::Integer;
@@ -74,8 +74,7 @@ pub(super) fn list_view_equal<T: ArrowNativeType + Integer>(
let rhs_offset = rhs_offset.to_usize().unwrap();
let size = size.to_usize().unwrap();
- // Check if offsets are valid for the given range
- if !equal_values(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
+ if !equal_range(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
return false;
}
}
@@ -101,10 +100,10 @@ pub(super) fn list_view_equal<T: ArrowNativeType + Integer>(
return false;
}
- for (index, ((&lhs_offset, &rhs_offset), &size)) in lhs_range_offsets
+ for (index, ((&lhs_offset, &rhs_offset), (&lhs_size, &rhs_size))) in lhs_range_offsets
.iter()
.zip(rhs_range_offsets)
- .zip(lhs_range_sizes)
+ .zip(lhs_range_sizes.iter().zip(rhs_range_sizes))
.enumerate()
{
let lhs_is_null = lhs_nulls.is_null(index);
@@ -114,12 +113,20 @@ pub(super) fn list_view_equal<T: ArrowNativeType + Integer>(
return false;
}
+ // Null rows are equal whatever their sizes and values
+ if lhs_is_null {
+ continue;
+ }
+
+ if lhs_size != rhs_size {
+ return false;
+ }
+
let lhs_offset = lhs_offset.to_usize().unwrap();
let rhs_offset = rhs_offset.to_usize().unwrap();
- let size = size.to_usize().unwrap();
+ let size = lhs_size.to_usize().unwrap();
- // Check if values match in the range
- if !lhs_is_null && !equal_values(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
+ if !equal_range(lhs_data, rhs_data, lhs_offset, rhs_offset, size) {
return false;
}
}
diff --git a/arrow-data/src/equal/mod.rs b/arrow-data/src/equal/mod.rs
index 7a310b1240..46df45db34 100644
--- a/arrow-data/src/equal/mod.rs
+++ b/arrow-data/src/equal/mod.rs
@@ -58,6 +58,9 @@ use variable_size::variable_sized_equal;
/// Compares the values of two [ArrayData] starting at `lhs_start` and `rhs_start` respectively
/// for `len` slots.
+///
+/// Assumes the null masks of the two ranges are already known to be equal. To compare
+/// ranges of child data, use [`equal_range`], which also compares the null masks.
#[inline]
fn equal_values(
lhs: &ArrayData,
diff --git a/arrow/tests/array_equal.rs b/arrow/tests/array_equal.rs
index 381054a25d..c21096c6dc 100644
--- a/arrow/tests/array_equal.rs
+++ b/arrow/tests/array_equal.rs
@@ -822,6 +822,22 @@ fn test_test_list_view_array<T: OffsetSizeTrait>() {
test_equal(&a, &b, true);
}
+fn test_list_view_sizes_and_child_nulls<T: OffsetSizeTrait>() {
+ // Same first elements but different sizes, with a null row
+ let a = create_list_view_array::<T, _, _>([Some(vec![Some(1), Some(2)]), None]);
+ let b = create_list_view_array::<T, _, _>([Some(vec![Some(1), Some(2), Some(3)]), None]);
+ test_equal(&a, &b, false);
+
+ // Child values that differ only in their null masks, without and with a null row
+ let a = create_list_view_array::<T, _, _>([Some(vec![Some(1), Some(0)])]);
+ let b = create_list_view_array::<T, _, _>([Some(vec![Some(1), None])]);
+ test_equal(&a, &b, false);
+
+ let a = create_list_view_array::<T, _, _>([None, Some(vec![Some(1), Some(0)])]);
+ let b = create_list_view_array::<T, _, _>([None, Some(vec![Some(1), None])]);
+ test_equal(&a, &b, false);
+}
+
// Special test for List<ListView<i32>>.
// This tests the equal_ranges kernel
fn test_sliced_list_of_list_view<T: OffsetSizeTrait>() {
@@ -871,6 +887,16 @@ fn test_large_list_view_array() {
test_test_list_view_array::<i64>();
}
+#[test]
+fn test_list_view_array_sizes_and_child_nulls() {
+ test_list_view_sizes_and_child_nulls::<i32>();
+}
+
+#[test]
+fn test_large_list_view_array_sizes_and_child_nulls() {
+ test_list_view_sizes_and_child_nulls::<i64>();
+}
+
#[test]
fn test_nested_list_view_array() {
test_sliced_list_of_list_view::<i32>();