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

Jefffrey 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 c8aff1ef5f Support Utf8View and BinaryView Ranking (#10559)
c8aff1ef5f is described below

commit c8aff1ef5ff804b94cbc38d71ff9135f862efb81
Author: Dhruv Vaishnav <[email protected]>
AuthorDate: Wed Aug 5 19:13:07 2026 +0530

    Support Utf8View and BinaryView Ranking (#10559)
    
    # Which issue does this PR close?
    
    - Closes #7859.
    
    # Rationale for this change
    
    `rank` supports the standard UTF-8 and binary array representations, but
    not their view variants. Adding support makes ranking available for
    `Utf8View` and `BinaryView` arrays as well.
    
    # What changes are included in this PR?
    
    - Add `Utf8View` and `BinaryView` to the rankable data types.
    - Dispatch both view types through a shared `GenericByteViewArray`
    ranking path.
    - Add coverage for inline values, out-of-line values, duplicates, and
    null handling.
    
    # Are these changes tested?
    
    Yes. The following checks pass:
    
    - `cargo fmt --all -- --check`
    - `cargo test -p arrow-ord`
    - `cargo clippy -p arrow-ord --all-targets --all-features -- -D
    warnings`
    - `git diff --check`
    
    # Are there any user-facing changes?
    
    `Utf8View` and `BinaryView` arrays can now be passed to `rank`. There
    are no breaking API changes.
    
    # AI assistance
    
    OpenAI Codex assisted with codebase inspection, implementation, test
    creation, and validation. The submitter remains responsible for
    reviewing, understanding, and maintaining the contribution.
    
    ---------
    
    Co-authored-by: Jeffrey Vo <[email protected]>
---
 arrow-ord/src/rank.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/arrow-ord/src/rank.rs b/arrow-ord/src/rank.rs
index 252a41a4da..a4808b93fb 100644
--- a/arrow-ord/src/rank.rs
+++ b/arrow-ord/src/rank.rs
@@ -20,7 +20,8 @@
 use arrow_array::cast::AsArray;
 use arrow_array::types::*;
 use arrow_array::{
-    Array, ArrowNativeTypeOp, BooleanArray, GenericByteArray, 
downcast_primitive_array,
+    Array, ArrowNativeTypeOp, BooleanArray, GenericByteArray, 
GenericByteViewArray,
+    downcast_primitive_array,
 };
 use arrow_buffer::NullBuffer;
 use arrow_schema::{ArrowError, DataType, SortOptions};
@@ -36,6 +37,8 @@ pub(crate) fn can_rank(data_type: &DataType) -> bool {
                 | DataType::LargeUtf8
                 | DataType::Binary
                 | DataType::LargeBinary
+                | DataType::Utf8View
+                | DataType::BinaryView
         )
 }
 
@@ -60,6 +63,8 @@ pub fn rank(array: &dyn Array, options: Option<SortOptions>) 
-> Result<Vec<u32>,
         DataType::LargeUtf8 => bytes_rank(array.as_bytes::<LargeUtf8Type>(), 
options),
         DataType::Binary => bytes_rank(array.as_bytes::<BinaryType>(), 
options),
         DataType::LargeBinary => 
bytes_rank(array.as_bytes::<LargeBinaryType>(), options),
+        DataType::Utf8View => byte_view_rank(array.as_string_view(), options),
+        DataType::BinaryView => byte_view_rank(array.as_binary_view(), 
options),
         d => return Err(ArrowError::ComputeError(format!("{d:?} not supported 
in rank")))
     };
     Ok(ranks)
@@ -96,6 +101,23 @@ fn bytes_rank<T: ByteArrayType>(array: 
&GenericByteArray<T>, options: SortOption
     rank_impl(array.len(), to_sort, options, Ord::cmp, PartialEq::eq)
 }
 
+#[inline(never)]
+fn byte_view_rank<T: ByteViewType>(
+    array: &GenericByteViewArray<T>,
+    options: SortOptions,
+) -> Vec<u32> {
+    let to_sort: Vec<(&[u8], u32)> = match array.nulls().filter(|n| 
n.null_count() > 0) {
+        Some(n) => n
+            .valid_indices()
+            .map(|idx| (array.value(idx).as_ref(), idx as u32))
+            .collect(),
+        None => (0..array.len())
+            .map(|idx| (array.value(idx).as_ref(), idx as u32))
+            .collect(),
+    };
+    rank_impl(array.len(), to_sort, options, Ord::cmp, PartialEq::eq)
+}
+
 fn rank_impl<T, C, E>(
     len: usize,
     mut valid: Vec<(T, u32)>,
@@ -349,13 +371,46 @@ mod tests {
         let res = rank(&values, None).unwrap();
         assert_eq!(res, &[4, 3, 2, 2]);
 
+        let values = StringViewArray::from(v);
+        let res = rank(&values, None).unwrap();
+        assert_eq!(res, &[4, 3, 2, 2]);
+
         let v: Vec<&[u8]> = vec![&[1, 2], &[0], &[1, 2, 3], &[1, 2]];
         let values = LargeBinaryArray::from(v.clone());
         let res = rank(&values, None).unwrap();
         assert_eq!(res, &[3, 1, 4, 3]);
 
-        let values = BinaryArray::from(v);
+        let values = BinaryArray::from(v.clone());
         let res = rank(&values, None).unwrap();
         assert_eq!(res, &[3, 1, 4, 3]);
+
+        let values = BinaryViewArray::from_iter_values(v);
+        let res = rank(&values, None).unwrap();
+        assert_eq!(res, &[3, 1, 4, 3]);
+    }
+
+    #[test]
+    fn test_string_view_with_nulls() {
+        let values = StringViewArray::from(vec![
+            Some("a string longer than twelve bytes"),
+            Some("bar"),
+            None,
+            Some("a string longer than twelve bytes"),
+        ]);
+        let res = rank(&values, None).unwrap();
+        assert_eq!(res, &[3, 4, 1, 3]);
+    }
+
+    #[test]
+    fn test_binary_view_with_nulls() {
+        let long_value = b"a binary value longer than twelve bytes".as_ref();
+        let values = BinaryViewArray::from_iter([
+            Some(long_value),
+            Some(b"bar".as_ref()),
+            None,
+            Some(long_value),
+        ]);
+        let res = rank(&values, None).unwrap();
+        assert_eq!(res, &[3, 4, 1, 3]);
     }
 }

Reply via email to