1919
2020use crate :: utils:: make_scalar_function;
2121use arrow:: array:: {
22- Array , ArrayRef , Int64Array , LargeListArray , ListArray , OffsetSizeTrait , UInt64Array ,
22+ Array , ArrayRef , FixedSizeListArray , Int64Array , LargeListArray , ListArray ,
23+ OffsetSizeTrait , UInt64Array ,
2324} ;
2425use 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+ } ;
2932use datafusion_common:: { exec_err, internal_datafusion_err, plan_err, Result } ;
3033use 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
123143pub 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.
136161fn 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 }
0 commit comments