diff --git a/datafusion/functions-nested/src/extract.rs b/datafusion/functions-nested/src/extract.rs index 900b408bffbba..b1c22822dfdc7 100644 --- a/datafusion/functions-nested/src/extract.rs +++ b/datafusion/functions-nested/src/extract.rs @@ -970,7 +970,7 @@ where #[user_doc( doc_section(label = "Array Functions"), - description = "Returns the first non-null element in the array.", + description = "Returns the first non-null element in the array. Returns NULL if the array is empty or NULL.", syntax_example = "array_any_value(array)", sql_example = r#"```sql > select array_any_value([NULL, 1, 2, 3]); @@ -1062,13 +1062,21 @@ where for (row_index, offset_window) in array.offsets().windows(2).enumerate() { let start = offset_window[0]; + let end = offset_window[1]; - // array is null + // the list element is null if array.is_null(row_index) { mutable.try_extend_nulls(1)?; continue; } + // the list element is empty; there is no value to take, so the result + // is NULL. + if start == end { + mutable.try_extend_nulls(1)?; + continue; + } + let row_value = array.value(row_index); match row_value.nulls() { Some(row_nulls_buffer) => { diff --git a/datafusion/sqllogictest/test_files/array/array_any_value.slt b/datafusion/sqllogictest/test_files/array/array_any_value.slt index 6579e88ac7dba..c8976e8493261 100644 --- a/datafusion/sqllogictest/test_files/array/array_any_value.slt +++ b/datafusion/sqllogictest/test_files/array/array_any_value.slt @@ -145,6 +145,35 @@ select array_any_value(make_array(NULL, 1, 2, 3, 4, 5)), array_any_value(column1 1 41 1 51 +# array_any_value with empty (length-0) list elements +# A non-null but empty list must yield NULL, including a trailing empty element +# whose start offset equals the values length +statement ok +create table any_value_empty (id int, tags bigint[]) as values + (1, make_array(10)), + (2, cast(make_array() as bigint[])), + (3, make_array(20, 30)), + (4, cast(make_array() as bigint[])); + +query II +select id, array_any_value(tags) from any_value_empty order by id; +---- +1 10 +2 NULL +3 20 +4 NULL + +query II +select id, array_any_value(arrow_cast(tags, 'LargeList(Int64)')) from any_value_empty order by id; +---- +1 10 +2 NULL +3 20 +4 NULL + +statement ok +drop table any_value_empty; + # make_array with nulls query ??????? select make_array(make_array('a','b'), null), diff --git a/docs/source/user-guide/sql/scalar_functions.md b/docs/source/user-guide/sql/scalar_functions.md index cb748f57d9967..a285b9e5f5cff 100644 --- a/docs/source/user-guide/sql/scalar_functions.md +++ b/docs/source/user-guide/sql/scalar_functions.md @@ -3430,7 +3430,7 @@ any_match(array, predicate) ### `array_any_value` -Returns the first non-null element in the array. +Returns the first non-null element in the array. Returns NULL if the array is empty or NULL. ```sql array_any_value(array)