19
19
20
20
use crate :: utils:: make_scalar_function;
21
21
use arrow:: array:: {
22
- Array , ArrayRef , Int64Array , LargeListArray , ListArray , OffsetSizeTrait , UInt64Array ,
22
+ Array , ArrayRef , FixedSizeListArray , Int64Array , LargeListArray , ListArray ,
23
+ OffsetSizeTrait , UInt64Array ,
23
24
} ;
24
25
use arrow:: datatypes:: {
25
26
DataType ,
26
27
DataType :: { FixedSizeList , LargeList , List , UInt64 } ,
27
28
} ;
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
+ } ;
29
32
use datafusion_common:: { exec_err, internal_datafusion_err, plan_err, Result } ;
30
33
use datafusion_expr:: {
31
34
ColumnarValue , Documentation , ScalarUDFImpl , Signature , Volatility ,
@@ -119,6 +122,23 @@ impl ScalarUDFImpl for ArrayLength {
119
122
}
120
123
}
121
124
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
+
122
142
/// Array_length SQL function
123
143
pub fn array_length_inner ( args : & [ ArrayRef ] ) -> Result < ArrayRef > {
124
144
if args. len ( ) != 1 && args. len ( ) != 2 {
@@ -128,26 +148,18 @@ pub fn array_length_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
128
148
match & args[ 0 ] . data_type ( ) {
129
149
List ( _) => general_array_length :: < i32 > ( args) ,
130
150
LargeList ( _) => general_array_length :: < i64 > ( args) ,
151
+ FixedSizeList ( _, _) => fixed_size_array_length ( args) ,
131
152
array_type => exec_err ! ( "array_length does not support type '{array_type:?}'" ) ,
132
153
}
133
154
}
134
155
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
+
135
160
/// Dispatch array length computation based on the offset type.
136
161
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 ) )
151
163
}
152
164
153
165
/// Returns the length of a concrete array dimension
@@ -185,6 +197,10 @@ fn compute_array_length(
185
197
value = downcast_arg ! ( value, LargeListArray ) . value ( 0 ) ;
186
198
current_dimension += 1 ;
187
199
}
200
+ FixedSizeList ( _, _) => {
201
+ value = downcast_arg ! ( value, FixedSizeListArray ) . value ( 0 ) ;
202
+ current_dimension += 1 ;
203
+ }
188
204
_ => return Ok ( None ) ,
189
205
}
190
206
}
0 commit comments