Skip to content

Commit 605ccbd

Browse files
authored
feat: array_length for fixed size list (#16167)
* feat: array_length for fixed size list * remove list view
1 parent 3b551e9 commit 605ccbd

2 files changed

Lines changed: 45 additions & 16 deletions

File tree

datafusion/functions-nested/src/length.rs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
2020
use crate::utils::make_scalar_function;
2121
use arrow::array::{
22-
Array, ArrayRef, Int64Array, LargeListArray, ListArray, OffsetSizeTrait, UInt64Array,
22+
Array, ArrayRef, FixedSizeListArray, Int64Array, LargeListArray, ListArray,
23+
OffsetSizeTrait, UInt64Array,
2324
};
2425
use arrow::datatypes::{
2526
DataType,
2627
DataType::{FixedSizeList, LargeList, List, UInt64},
2728
};
28-
use datafusion_common::cast::{as_generic_list_array, as_int64_array};
29+
use datafusion_common::cast::{
30+
as_fixed_size_list_array, as_generic_list_array, as_int64_array,
31+
};
2932
use datafusion_common::{exec_err, internal_datafusion_err, plan_err, Result};
3033
use datafusion_expr::{
3134
ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
@@ -119,6 +122,23 @@ impl ScalarUDFImpl for ArrayLength {
119122
}
120123
}
121124

125+
macro_rules! array_length_impl {
126+
($array:expr, $dimension:expr) => {{
127+
let array = $array;
128+
let dimension = match $dimension {
129+
Some(d) => as_int64_array(d)?.clone(),
130+
None => Int64Array::from_value(1, array.len()),
131+
};
132+
let result = array
133+
.iter()
134+
.zip(dimension.iter())
135+
.map(|(arr, dim)| compute_array_length(arr, dim))
136+
.collect::<Result<UInt64Array>>()?;
137+
138+
Ok(Arc::new(result) as ArrayRef)
139+
}};
140+
}
141+
122142
/// Array_length SQL function
123143
pub fn array_length_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
124144
if args.len() != 1 && args.len() != 2 {
@@ -128,26 +148,18 @@ pub fn array_length_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
128148
match &args[0].data_type() {
129149
List(_) => general_array_length::<i32>(args),
130150
LargeList(_) => general_array_length::<i64>(args),
151+
FixedSizeList(_, _) => fixed_size_array_length(args),
131152
array_type => exec_err!("array_length does not support type '{array_type:?}'"),
132153
}
133154
}
134155

156+
fn fixed_size_array_length(array: &[ArrayRef]) -> Result<ArrayRef> {
157+
array_length_impl!(as_fixed_size_list_array(&array[0])?, array.get(1))
158+
}
159+
135160
/// Dispatch array length computation based on the offset type.
136161
fn general_array_length<O: OffsetSizeTrait>(array: &[ArrayRef]) -> Result<ArrayRef> {
137-
let list_array = as_generic_list_array::<O>(&array[0])?;
138-
let dimension = if array.len() == 2 {
139-
as_int64_array(&array[1])?.clone()
140-
} else {
141-
Int64Array::from_value(1, list_array.len())
142-
};
143-
144-
let result = list_array
145-
.iter()
146-
.zip(dimension.iter())
147-
.map(|(arr, dim)| compute_array_length(arr, dim))
148-
.collect::<Result<UInt64Array>>()?;
149-
150-
Ok(Arc::new(result) as ArrayRef)
162+
array_length_impl!(as_generic_list_array::<O>(&array[0])?, array.get(1))
151163
}
152164

153165
/// Returns the length of a concrete array dimension
@@ -185,6 +197,10 @@ fn compute_array_length(
185197
value = downcast_arg!(value, LargeListArray).value(0);
186198
current_dimension += 1;
187199
}
200+
FixedSizeList(_, _) => {
201+
value = downcast_arg!(value, FixedSizeListArray).value(0);
202+
current_dimension += 1;
203+
}
188204
_ => return Ok(None),
189205
}
190206
}

datafusion/sqllogictest/test_files/array.slt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5240,6 +5240,19 @@ NULL 10
52405240
NULL 10
52415241
NULL 10
52425242

5243+
# array_length for fixed sized list
5244+
5245+
query III
5246+
select array_length(arrow_cast(make_array(1, 2, 3, 4, 5), 'FixedSizeList(5, Int64)')), array_length(arrow_cast(make_array(1, 2, 3), 'FixedSizeList(3, Int64)')), array_length(arrow_cast(make_array([1, 2], [3, 4], [5, 6]), 'FixedSizeList(3, List(Int64))'));
5247+
----
5248+
5 3 3
5249+
5250+
query III
5251+
select array_length(arrow_cast(make_array(1, 2, 3, 4, 5), 'FixedSizeList(5, Int64)'), 1), array_length(arrow_cast(make_array(1, 2, 3), 'FixedSizeList(3, Int64)'), 1), array_length(arrow_cast(make_array([1, 2], [3, 4], [5, 6]), 'FixedSizeList(3, List(Int64))'), 1);
5252+
----
5253+
5 3 3
5254+
5255+
52435256
query RRR
52445257
select array_distance([2], [3]), list_distance([1], [2]), list_distance([1], [-2]);
52455258
----

0 commit comments

Comments
 (0)