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 a6596e4097 feat: support `MapArray` in lengths kernel (#10121)
a6596e4097 is described below
commit a6596e4097b4104ee604f20fab67260d2b2e556d
Author: Raz Luvaton <[email protected]>
AuthorDate: Fri Jun 12 00:11:31 2026 +0300
feat: support `MapArray` in lengths kernel (#10121)
# Which issue does this PR close?
N/A
# Rationale for this change
`MapArray` is not very different than `ListArray` that is supported in
`lengths` kernel
# What changes are included in this PR?
added MapArray support and tests
# Are these changes tested?
yes
# Are there any user-facing changes?
`lengths` now support `MapArray`
---
arrow-string/src/length.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/arrow-string/src/length.rs b/arrow-string/src/length.rs
index 99a9bd69a6..3b471130d6 100644
--- a/arrow-string/src/length.rs
+++ b/arrow-string/src/length.rs
@@ -47,9 +47,10 @@ fn bit_length_impl<P: ArrowPrimitiveType>(
/// Returns an array of Int32/Int64 denoting the length of each value in the
array.
///
/// For list array, length is the number of elements in each list.
+/// For map array, length is the number of entries in each map.
/// For string array and binary array, length is the number of bytes of each
value.
///
-/// * this only accepts ListArray/LargeListArray,
StringArray/LargeStringArray/StringViewArray, BinaryArray/LargeBinaryArray,
FixedSizeListArray,
+/// * this only accepts ListArray/LargeListArray, MapArray,
StringArray/LargeStringArray/StringViewArray, BinaryArray/LargeBinaryArray,
FixedSizeListArray,
/// and ListViewArray/LargeListViewArray, or DictionaryArray with above
Arrays as values, or
/// RunEndEncoded arrays with above arrays as values
/// * length of null is null.
@@ -85,6 +86,10 @@ pub fn length(array: &dyn Array) -> Result<ArrayRef,
ArrowError> {
list.nulls().cloned(),
)))
}
+ DataType::Map(_, _) => {
+ let map = array.as_map();
+ Ok(length_impl::<Int32Type>(map.offsets(), map.nulls()))
+ }
DataType::Utf8 => {
let list = array.as_string::<i32>();
Ok(length_impl::<Int32Type>(list.offsets(), list.nulls()))
@@ -197,6 +202,7 @@ pub fn bit_length(array: &dyn Array) -> Result<ArrayRef,
ArrowError> {
#[cfg(test)]
mod tests {
use super::*;
+ use arrow_array::builder::{Int32Builder, MapBuilder, StringBuilder};
use arrow_buffer::{Buffer, ScalarBuffer};
use arrow_data::ArrayData;
use arrow_schema::Field;
@@ -340,6 +346,29 @@ mod tests {
length_list_helper!(i64, Int64Array, Float32Type, value, result)
}
+ #[test]
+ fn length_test_map() {
+ let mut map_builder = MapBuilder::new(None, StringBuilder::new(),
Int32Builder::default());
+ // {}
+ map_builder.append(true).unwrap();
+
+ // {"a": 1, "b": 2, "cd": 4}
+ map_builder.keys().extend(["a", "b", "cd"].map(Some));
+ map_builder.values().extend([1, 2, 4].map(Some));
+ map_builder.append(true).unwrap();
+
+ // {"e": 0}
+ map_builder.keys().append_value("e");
+ map_builder.values().append_value(0);
+ map_builder.append(true).unwrap();
+
+ let map_array = map_builder.finish();
+
+ let lengths = length(&map_array).unwrap();
+ let lengths = lengths.as_primitive::<Int32Type>();
+ assert_eq!(lengths, &Int32Array::from(vec![0, 3, 1]));
+ }
+
type OptionStr = Option<&'static str>;
fn length_null_cases_string() -> Vec<(Vec<OptionStr>, usize,
Vec<Option<i32>>)> {
@@ -425,6 +454,34 @@ mod tests {
length_list_helper!(i64, Int64Array, Float32Type, value, result)
}
+ #[test]
+ fn length_test_null_map() {
+ let mut map_builder = MapBuilder::new(None, StringBuilder::new(),
Int32Builder::default());
+ // {}
+ map_builder.append(true).unwrap();
+
+ // null
+ map_builder.append_nulls(1).unwrap();
+
+ // {"a": 1, "b": 2, "cd": 4}
+ map_builder.keys().extend(["a", "b", "cd"].map(Some));
+ map_builder.values().extend([1, 2, 4].map(Some));
+ map_builder.append(true).unwrap();
+
+ // {"e": 0}
+ map_builder.keys().append_value("e");
+ map_builder.values().append_value(0);
+ map_builder.append(true).unwrap();
+
+ let map_array = map_builder.finish();
+ let lengths = length(&map_array).unwrap();
+ let lengths = lengths.as_primitive::<Int32Type>();
+ assert_eq!(
+ lengths,
+ &Int32Array::from(vec![Some(0), None, Some(3), Some(1)])
+ );
+ }
+
#[test]
fn length_test_list_view() {
// Create a ListViewArray with values [0, 1, 2], [3, 4, 5], [6, 7]