@@ -25,7 +25,8 @@ use arrow::array::{
25
25
} ;
26
26
use arrow:: datatypes:: { DataType , Field } ;
27
27
28
- use datafusion_common:: { not_impl_err, plan_err, DataFusionError , Result } ;
28
+ use datafusion_common:: utils:: ListCoercion ;
29
+ use datafusion_common:: { not_impl_err, DataFusionError , Result } ;
29
30
30
31
use std:: any:: Any ;
31
32
@@ -39,12 +40,15 @@ use arrow::compute::cast;
39
40
use arrow:: datatypes:: DataType :: {
40
41
Dictionary , FixedSizeList , LargeList , LargeUtf8 , List , Null , Utf8 , Utf8View ,
41
42
} ;
42
- use datafusion_common:: cast:: { as_large_list_array, as_list_array} ;
43
+ use datafusion_common:: cast:: {
44
+ as_fixed_size_list_array, as_large_list_array, as_list_array,
45
+ } ;
43
46
use datafusion_common:: exec_err;
44
47
use datafusion_common:: types:: logical_string;
45
48
use datafusion_expr:: {
46
- Coercion , ColumnarValue , Documentation , ScalarUDFImpl , Signature , TypeSignature ,
47
- TypeSignatureClass , Volatility ,
49
+ ArrayFunctionArgument , ArrayFunctionSignature , Coercion , ColumnarValue ,
50
+ Documentation , ScalarUDFImpl , Signature , TypeSignature , TypeSignatureClass ,
51
+ Volatility ,
48
52
} ;
49
53
use datafusion_functions:: downcast_arg;
50
54
use datafusion_macros:: user_doc;
@@ -159,7 +163,26 @@ impl Default for ArrayToString {
159
163
impl ArrayToString {
160
164
pub fn new ( ) -> Self {
161
165
Self {
162
- signature : Signature :: variadic_any ( Volatility :: Immutable ) ,
166
+ signature : Signature :: one_of (
167
+ vec ! [
168
+ TypeSignature :: ArraySignature ( ArrayFunctionSignature :: Array {
169
+ arguments: vec![
170
+ ArrayFunctionArgument :: Array ,
171
+ ArrayFunctionArgument :: String ,
172
+ ArrayFunctionArgument :: String ,
173
+ ] ,
174
+ array_coercion: Some ( ListCoercion :: FixedSizedListToList ) ,
175
+ } ) ,
176
+ TypeSignature :: ArraySignature ( ArrayFunctionSignature :: Array {
177
+ arguments: vec![
178
+ ArrayFunctionArgument :: Array ,
179
+ ArrayFunctionArgument :: String ,
180
+ ] ,
181
+ array_coercion: Some ( ListCoercion :: FixedSizedListToList ) ,
182
+ } ) ,
183
+ ] ,
184
+ Volatility :: Immutable ,
185
+ ) ,
163
186
aliases : vec ! [
164
187
String :: from( "list_to_string" ) ,
165
188
String :: from( "array_join" ) ,
@@ -182,13 +205,8 @@ impl ScalarUDFImpl for ArrayToString {
182
205
& self . signature
183
206
}
184
207
185
- fn return_type ( & self , arg_types : & [ DataType ] ) -> Result < DataType > {
186
- Ok ( match arg_types[ 0 ] {
187
- List ( _) | LargeList ( _) | FixedSizeList ( _, _) => Utf8 ,
188
- _ => {
189
- return plan_err ! ( "The array_to_string function can only accept List/LargeList/FixedSizeList." ) ;
190
- }
191
- } )
208
+ fn return_type ( & self , _arg_types : & [ DataType ] ) -> Result < DataType > {
209
+ Ok ( Utf8 )
192
210
}
193
211
194
212
fn invoke_with_args (
@@ -282,16 +300,10 @@ impl ScalarUDFImpl for StringToArray {
282
300
}
283
301
284
302
fn return_type ( & self , arg_types : & [ DataType ] ) -> Result < DataType > {
285
- Ok ( match arg_types[ 0 ] {
286
- Utf8 | Utf8View | LargeUtf8 => {
287
- List ( Arc :: new ( Field :: new_list_field ( arg_types[ 0 ] . clone ( ) , true ) ) )
288
- }
289
- _ => {
290
- return plan_err ! (
291
- "The string_to_array function can only accept Utf8, Utf8View or LargeUtf8."
292
- ) ;
293
- }
294
- } )
303
+ Ok ( List ( Arc :: new ( Field :: new_list_field (
304
+ arg_types[ 0 ] . clone ( ) ,
305
+ true ,
306
+ ) ) ) )
295
307
}
296
308
297
309
fn invoke_with_args (
@@ -368,6 +380,20 @@ pub(super) fn array_to_string_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
368
380
369
381
Ok ( arg)
370
382
}
383
+ FixedSizeList ( ..) => {
384
+ let list_array = as_fixed_size_list_array ( & arr) ?;
385
+ for i in 0 ..list_array. len ( ) {
386
+ compute_array_to_string (
387
+ arg,
388
+ list_array. value ( i) ,
389
+ delimiter. clone ( ) ,
390
+ null_string. clone ( ) ,
391
+ with_null_string,
392
+ ) ?;
393
+ }
394
+
395
+ Ok ( arg)
396
+ }
371
397
LargeList ( ..) => {
372
398
let list_array = as_large_list_array ( & arr) ?;
373
399
for i in 0 ..list_array. len ( ) {
@@ -449,9 +475,8 @@ pub(super) fn array_to_string_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
449
475
Ok ( StringArray :: from ( res) )
450
476
}
451
477
452
- let arr_type = arr. data_type ( ) ;
453
- let string_arr = match arr_type {
454
- List ( _) | FixedSizeList ( _, _) => {
478
+ let string_arr = match arr. data_type ( ) {
479
+ List ( _) => {
455
480
let list_array = as_list_array ( & arr) ?;
456
481
generate_string_array :: < i32 > (
457
482
list_array,
@@ -469,29 +494,8 @@ pub(super) fn array_to_string_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
469
494
with_null_string,
470
495
) ?
471
496
}
472
- _ => {
473
- let mut arg = String :: from ( "" ) ;
474
- let mut res: Vec < Option < String > > = Vec :: new ( ) ;
475
- // delimiter length is 1
476
- assert_eq ! ( delimiters. len( ) , 1 ) ;
477
- let delimiter = delimiters[ 0 ] . unwrap ( ) ;
478
- let s = compute_array_to_string (
479
- & mut arg,
480
- Arc :: clone ( arr) ,
481
- delimiter. to_string ( ) ,
482
- null_string,
483
- with_null_string,
484
- ) ?
485
- . clone ( ) ;
486
-
487
- if !s. is_empty ( ) {
488
- let s = s. strip_suffix ( delimiter) . unwrap ( ) . to_string ( ) ;
489
- res. push ( Some ( s) ) ;
490
- } else {
491
- res. push ( Some ( s) ) ;
492
- }
493
- StringArray :: from ( res)
494
- }
497
+ // Signature guards against this arm
498
+ _ => return exec_err ! ( "array_to_string expects list as first argument" ) ,
495
499
} ;
496
500
497
501
Ok ( Arc :: new ( string_arr) )
0 commit comments