Skip to content

Commit 3764fe7

Browse files
Fix array_concat with NULL arrays (#16348)
* Fix array_concat with NULL arrays to avoid Arrow concat error - Fix array_concat_inner to properly handle NULL list arrays by checking null_count - Add logic to create properly typed empty arrays for all-null inputs - Support NULL handling for List, LargeList, and FixedSizeList types - Add comprehensive test coverage for NULL array scenarios Fixes issue where 'select array_concat(NULL::integer[])' would throw 'Arrow error: Compute error: concat requires input of at least one array' * Simplify null count check and null array generation
1 parent 42e55bd commit 3764fe7

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

datafusion/functions-nested/src/concat.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::sync::Arc;
2323
use crate::make_array::make_array_inner;
2424
use crate::utils::{align_array_dimensions, check_datatypes, make_scalar_function};
2525
use arrow::array::{
26-
Array, ArrayRef, Capacities, GenericListArray, MutableArrayData, NullArray,
26+
Array, ArrayData, ArrayRef, Capacities, GenericListArray, MutableArrayData,
2727
NullBufferBuilder, OffsetSizeTrait,
2828
};
2929
use arrow::buffer::OffsetBuffer;
@@ -42,6 +42,7 @@ use datafusion_expr::{
4242
ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
4343
};
4444
use datafusion_macros::user_doc;
45+
use itertools::Itertools;
4546

4647
make_udf_expr_and_func!(
4748
ArrayAppend,
@@ -364,12 +365,23 @@ pub(crate) fn array_concat_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
364365
DataType::LargeList(_) => large_list = true,
365366
_ => (),
366367
}
367-
368-
all_null = false
368+
if arg.null_count() < arg.len() {
369+
all_null = false;
370+
}
369371
}
370372

371373
if all_null {
372-
Ok(Arc::new(NullArray::new(args[0].len())))
374+
// Return a null array with the same type as the first non-null-type argument
375+
let return_type = args
376+
.iter()
377+
.map(|arg| arg.data_type())
378+
.find_or_first(|d| !d.is_null())
379+
.unwrap(); // Safe because args is non-empty
380+
381+
Ok(arrow::array::make_array(ArrayData::new_null(
382+
return_type,
383+
args[0].len(),
384+
)))
373385
} else if large_list {
374386
concat_internal::<i64>(args)
375387
} else {

datafusion/sqllogictest/test_files/array.slt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3070,6 +3070,42 @@ select array_concat([]);
30703070
----
30713071
[]
30723072

3073+
# test with NULL array
3074+
query ?
3075+
select array_concat(NULL::integer[]);
3076+
----
3077+
NULL
3078+
3079+
# test with multiple NULL arrays
3080+
query ?
3081+
select array_concat(NULL::integer[], NULL::integer[]);
3082+
----
3083+
NULL
3084+
3085+
# test with NULL LargeList
3086+
query ?
3087+
select array_concat(arrow_cast(NULL::string[], 'LargeList(Utf8)'));
3088+
----
3089+
NULL
3090+
3091+
# test with NULL FixedSizeList
3092+
query ?
3093+
select array_concat(arrow_cast(NULL::string[], 'FixedSizeList(2, Utf8)'));
3094+
----
3095+
NULL
3096+
3097+
# test with mix of NULL and empty arrays
3098+
query ?
3099+
select array_concat(NULL::integer[], []);
3100+
----
3101+
[]
3102+
3103+
# test with mix of NULL and non-empty arrays
3104+
query ?
3105+
select array_concat(NULL::integer[], [1, 2, 3]);
3106+
----
3107+
[1, 2, 3]
3108+
30733109
# Concatenating strings arrays
30743110
query ?
30753111
select array_concat(

0 commit comments

Comments
 (0)