|
18 | 18 | //! [`ScalarUDFImpl`] definitions for array_sort function. |
19 | 19 |
|
20 | 20 | use crate::utils::make_scalar_function; |
21 | | -use arrow::array::{Array, ArrayRef, ListArray, NullBufferBuilder}; |
| 21 | +use arrow::array::{new_null_array, Array, ArrayRef, ListArray, NullBufferBuilder}; |
22 | 22 | use arrow::buffer::OffsetBuffer; |
23 | 23 | use arrow::datatypes::DataType::{FixedSizeList, LargeList, List}; |
24 | 24 | use arrow::datatypes::{DataType, Field}; |
25 | 25 | use arrow::{compute, compute::SortOptions}; |
26 | 26 | use datafusion_common::cast::{as_list_array, as_string_array}; |
27 | 27 | use datafusion_common::{exec_err, Result}; |
28 | 28 | use datafusion_expr::{ |
29 | | - ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility, |
| 29 | + ArrayFunctionArgument, ArrayFunctionSignature, ColumnarValue, Documentation, |
| 30 | + ScalarUDFImpl, Signature, TypeSignature, Volatility, |
30 | 31 | }; |
31 | 32 | use datafusion_macros::user_doc; |
32 | 33 | use std::any::Any; |
@@ -87,7 +88,30 @@ impl Default for ArraySort { |
87 | 88 | impl ArraySort { |
88 | 89 | pub fn new() -> Self { |
89 | 90 | Self { |
90 | | - signature: Signature::variadic_any(Volatility::Immutable), |
| 91 | + signature: Signature::one_of( |
| 92 | + vec![ |
| 93 | + TypeSignature::ArraySignature(ArrayFunctionSignature::Array { |
| 94 | + arguments: vec![ArrayFunctionArgument::Array], |
| 95 | + array_coercion: None, |
| 96 | + }), |
| 97 | + TypeSignature::ArraySignature(ArrayFunctionSignature::Array { |
| 98 | + arguments: vec![ |
| 99 | + ArrayFunctionArgument::Array, |
| 100 | + ArrayFunctionArgument::String, |
| 101 | + ], |
| 102 | + array_coercion: None, |
| 103 | + }), |
| 104 | + TypeSignature::ArraySignature(ArrayFunctionSignature::Array { |
| 105 | + arguments: vec![ |
| 106 | + ArrayFunctionArgument::Array, |
| 107 | + ArrayFunctionArgument::String, |
| 108 | + ArrayFunctionArgument::String, |
| 109 | + ], |
| 110 | + array_coercion: None, |
| 111 | + }), |
| 112 | + ], |
| 113 | + Volatility::Immutable, |
| 114 | + ), |
91 | 115 | aliases: vec!["list_sort".to_string()], |
92 | 116 | } |
93 | 117 | } |
@@ -115,6 +139,7 @@ impl ScalarUDFImpl for ArraySort { |
115 | 139 | field.data_type().clone(), |
116 | 140 | true, |
117 | 141 | )))), |
| 142 | + DataType::Null => Ok(DataType::Null), |
118 | 143 | _ => exec_err!( |
119 | 144 | "Not reachable, data_type should be List, LargeList or FixedSizeList" |
120 | 145 | ), |
@@ -143,6 +168,10 @@ pub fn array_sort_inner(args: &[ArrayRef]) -> Result<ArrayRef> { |
143 | 168 | return exec_err!("array_sort expects one to three arguments"); |
144 | 169 | } |
145 | 170 |
|
| 171 | + if args[1..].iter().any(|array| array.is_null(0)) { |
| 172 | + return Ok(new_null_array(args[0].data_type(), args[0].len())); |
| 173 | + } |
| 174 | + |
146 | 175 | let sort_option = match args.len() { |
147 | 176 | 1 => None, |
148 | 177 | 2 => { |
@@ -196,12 +225,16 @@ pub fn array_sort_inner(args: &[ArrayRef]) -> Result<ArrayRef> { |
196 | 225 | .map(|a| a.as_ref()) |
197 | 226 | .collect::<Vec<&dyn Array>>(); |
198 | 227 |
|
199 | | - let list_arr = ListArray::new( |
200 | | - Arc::new(Field::new_list_field(data_type, true)), |
201 | | - OffsetBuffer::from_lengths(array_lengths), |
202 | | - Arc::new(compute::concat(elements.as_slice())?), |
203 | | - buffer, |
204 | | - ); |
| 228 | + let list_arr = if elements.is_empty() { |
| 229 | + ListArray::new_null(Arc::new(Field::new_list_field(data_type, true)), row_count) |
| 230 | + } else { |
| 231 | + ListArray::new( |
| 232 | + Arc::new(Field::new_list_field(data_type, true)), |
| 233 | + OffsetBuffer::from_lengths(array_lengths), |
| 234 | + Arc::new(compute::concat(elements.as_slice())?), |
| 235 | + buffer, |
| 236 | + ) |
| 237 | + }; |
205 | 238 | Ok(Arc::new(list_arr)) |
206 | 239 | } |
207 | 240 |
|
|
0 commit comments