This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-11657-e30b544d13f78d5644c3d587a9d0f98a5dc6b311
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git

commit a8306d68e57527a6b929a15cf046bd8550e995ea
Author: Patrick Ribbsaeter <[email protected]>
AuthorDate: Sun Oct 18 02:23:57 2026 +0000

    Fix Fields::filter_leaves for ListView and LargeListView (#11657)
    
    # Which issue does this PR close?
    
    Closes #11612.
    
    # Rationale for this change
    
    `Fields::filter_leaves` and `Fields::try_filter_leaves` perform a
    depth-first traversal over nested `DataType` variants so that the filter
    predicate is invoked only on leaf fields (fields with no children).
    Currently, `try_filter_leaves` handles `DataType::List`,
    `DataType::LargeList`, and `DataType::FixedSizeList`, but omits
    `DataType::ListView` and `DataType::LargeListView`, causing `ListView`
    and `LargeListView` fields to be treated as leaf fields instead of
    descending into their element `FieldRef`.
    
    # What changes are included in this PR?
    
    - Add `DataType::ListView(child)` and `DataType::LargeListView(child)`
    match arms in `Fields::try_filter_leaves` (`arrow-schema/src/fields.rs`)
    to recursively filter their child element field, matching the behavior
    of `List` and `LargeList`.
    - Add `test_filter_list_view` covering leaf filtering and leaf index
    counting across nested and primitive `ListView` and `LargeListView`
    fields.
    
    # Are there any user-facing changes?
    
    Yes, `Fields::filter_leaves` and `Fields::try_filter_leaves` now
    properly descend into `DataType::ListView` and `DataType::LargeListView`
    child fields.
---
 arrow-schema/src/fields.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/arrow-schema/src/fields.rs b/arrow-schema/src/fields.rs
index f7fa588c31..60e560293e 100644
--- a/arrow-schema/src/fields.rs
+++ b/arrow-schema/src/fields.rs
@@ -177,6 +177,22 @@ impl Fields {
                         return Ok(None);
                     }
                 }
+                ListView(child) => {
+                    let fields = filter_field(child, filter)?;
+                    if let Some(fields) = fields {
+                        ListView(fields)
+                    } else {
+                        return Ok(None);
+                    }
+                }
+                LargeListView(child) => {
+                    let fields = filter_field(child, filter)?;
+                    if let Some(fields) = fields {
+                        LargeListView(fields)
+                    } else {
+                        return Ok(None);
+                    }
+                }
                 Map(child, ordered) => {
                     let fields = filter_field(child, filter)?;
                     if let Some(fields) = fields {
@@ -797,6 +813,76 @@ mod tests {
         assert!(r.is_err());
     }
 
+    #[test]
+    fn test_filter_list_view() {
+        let floats = Fields::from(vec![
+            Field::new("a", DataType::Float32, false),
+            Field::new("b", DataType::Float32, false),
+        ]);
+        let fields = Fields::from(vec![
+            Field::new(
+                "lv_struct",
+                DataType::ListView(Arc::new(Field::new(
+                    "floats",
+                    DataType::Struct(floats.clone()),
+                    true,
+                ))),
+                true,
+            ),
+            Field::new(
+                "llv_struct",
+                DataType::LargeListView(Arc::new(Field::new(
+                    "floats",
+                    DataType::Struct(floats.clone()),
+                    true,
+                ))),
+                false,
+            ),
+            Field::new(
+                "lv_prim",
+                
DataType::ListView(Arc::new(Field::new_list_field(DataType::Int32, false))),
+                true,
+            ),
+            Field::new(
+                "llv_prim",
+                
DataType::LargeListView(Arc::new(Field::new_list_field(DataType::Int64, true))),
+                false,
+            ),
+        ]);
+
+        let floats_a = DataType::Struct(vec![floats[0].clone()].into());
+
+        // Filter by leaf field name "a" inside nested structs of ListView and 
LargeListView
+        let r = fields.filter_leaves(|_, f| f.name() == "a");
+        assert_eq!(r.len(), 2);
+        assert_eq!(
+            r[0].as_ref(),
+            &Field::new(
+                "lv_struct",
+                DataType::ListView(Arc::new(Field::new("floats", 
floats_a.clone(), true))),
+                true,
+            )
+        );
+        assert_eq!(
+            r[1].as_ref(),
+            &Field::new(
+                "llv_struct",
+                DataType::LargeListView(Arc::new(Field::new("floats", 
floats_a, true))),
+                false,
+            )
+        );
+
+        // Parent ListView/LargeListView fields are not leaves themselves
+        let r = fields.filter_leaves(|_, f| f.name() == "lv_struct" || 
f.name() == "llv_struct");
+        assert_eq!(r.len(), 0);
+
+        // Leaf indices: 0,1 (lv_struct.floats.a,b), 2,3 
(llv_struct.floats.a,b), 4 (lv_prim.item), 5 (llv_prim.item)
+        let r = fields.filter_leaves(|idx, _| idx == 4 || idx == 5);
+        assert_eq!(r.len(), 2);
+        assert_eq!(r[0], fields[2]);
+        assert_eq!(r[1], fields[3]);
+    }
+
     #[test]
     fn test_union_fields_try_new_valid() {
         let res = UnionFields::try_new(

Reply via email to