This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new 3dfce7d33c bug: Fix NULL handling in array_slice, introduce
`NullHandling` enum to `Signature` (#14289)
3dfce7d33c is described below
commit 3dfce7d33c19d6e7941b58cb7e83194c066347ca
Author: Joseph Koshakow <[email protected]>
AuthorDate: Mon Feb 3 06:42:10 2025 -0500
bug: Fix NULL handling in array_slice, introduce `NullHandling` enum to
`Signature` (#14289)
* bug: Fix NULL handling in array_slice
This commit fixes the array_slice function so that if any arguments are
NULL, the result is NULL. Previously, array_slice would return an
internal error if any of the arguments were NULL. This behavior matches
the behavior of DuckDB for array_slice.
Fixes #10548
* Fix optimizer error
* Fix clippy
* PoC for strict functions
* Generate all null values
* Add NullHandling enum
* Update array_slice signature
* Switch to trait method
* fmt
* Fix typo
* Handle batch inputs
* Fix comment
* Update array_pop methods null handling
---
datafusion/expr-common/src/signature.rs | 21 +++--
datafusion/expr/src/lib.rs | 4 +-
datafusion/expr/src/type_coercion/functions.rs | 13 ++-
datafusion/expr/src/udf.rs | 19 +++++
datafusion/functions-nested/src/extract.rs | 75 +++++++++++++-----
datafusion/physical-expr/src/scalar_function.rs | 12 ++-
datafusion/sqllogictest/test_files/array.slt | 100 +++++++++++++++---------
7 files changed, 172 insertions(+), 72 deletions(-)
diff --git a/datafusion/expr-common/src/signature.rs
b/datafusion/expr-common/src/signature.rs
index 56f3029a4d..1bfae28af8 100644
--- a/datafusion/expr-common/src/signature.rs
+++ b/datafusion/expr-common/src/signature.rs
@@ -19,6 +19,7 @@
//! and return types of functions in DataFusion.
use std::fmt::Display;
+use std::num::NonZeroUsize;
use crate::type_coercion::aggregates::NUMERICS;
use arrow::datatypes::{DataType, IntervalUnit, TimeUnit};
@@ -236,9 +237,9 @@ pub enum ArrayFunctionSignature {
/// The first argument should be non-list or list, and the second argument
should be List/LargeList.
/// The first argument's list dimension should be one dimension less than
the second argument's list dimension.
ElementAndArray,
- /// Specialized Signature for Array functions of the form (List/LargeList,
Index)
- /// The first argument should be List/LargeList/FixedSizedList, and the
second argument should be Int64.
- ArrayAndIndex,
+ /// Specialized Signature for Array functions of the form (List/LargeList,
Index+)
+ /// The first argument should be List/LargeList/FixedSizedList, and the
next n arguments should be Int64.
+ ArrayAndIndexes(NonZeroUsize),
/// Specialized Signature for Array functions of the form (List/LargeList,
Element, Optional Index)
ArrayAndElementAndOptionalIndex,
/// Specialized Signature for ArrayEmpty and similar functions
@@ -265,8 +266,12 @@ impl Display for ArrayFunctionSignature {
ArrayFunctionSignature::ElementAndArray => {
write!(f, "element, array")
}
- ArrayFunctionSignature::ArrayAndIndex => {
- write!(f, "array, index")
+ ArrayFunctionSignature::ArrayAndIndexes(count) => {
+ write!(f, "array")?;
+ for _ in 0..count.get() {
+ write!(f, ", index")?;
+ }
+ Ok(())
}
ArrayFunctionSignature::Array => {
write!(f, "array")
@@ -600,9 +605,13 @@ impl Signature {
}
/// Specialized Signature for ArrayElement and similar functions
pub fn array_and_index(volatility: Volatility) -> Self {
+ Self::array_and_indexes(volatility, NonZeroUsize::new(1).expect("1 is
non-zero"))
+ }
+ /// Specialized Signature for ArraySlice and similar functions
+ pub fn array_and_indexes(volatility: Volatility, count: NonZeroUsize) ->
Self {
Signature {
type_signature: TypeSignature::ArraySignature(
- ArrayFunctionSignature::ArrayAndIndex,
+ ArrayFunctionSignature::ArrayAndIndexes(count),
),
volatility,
}
diff --git a/datafusion/expr/src/lib.rs b/datafusion/expr/src/lib.rs
index aaa65c676a..46c0f5a3dd 100644
--- a/datafusion/expr/src/lib.rs
+++ b/datafusion/expr/src/lib.rs
@@ -95,8 +95,8 @@ pub use udaf::{
SetMonotonicity, StatisticsArgs,
};
pub use udf::{
- scalar_doc_sections, ReturnInfo, ReturnTypeArgs, ScalarFunctionArgs,
ScalarUDF,
- ScalarUDFImpl,
+ scalar_doc_sections, NullHandling, ReturnInfo, ReturnTypeArgs,
ScalarFunctionArgs,
+ ScalarUDF, ScalarUDFImpl,
};
pub use udwf::{window_doc_sections, ReversedUDWF, WindowUDF, WindowUDFImpl};
pub use window_frame::{WindowFrame, WindowFrameBound, WindowFrameUnits};
diff --git a/datafusion/expr/src/type_coercion/functions.rs
b/datafusion/expr/src/type_coercion/functions.rs
index 650619e6de..8cebf7c3db 100644
--- a/datafusion/expr/src/type_coercion/functions.rs
+++ b/datafusion/expr/src/type_coercion/functions.rs
@@ -671,13 +671,20 @@ fn get_valid_types(
ArrayFunctionSignature::ElementAndArray => {
array_append_or_prepend_valid_types(current_types, false)?
}
- ArrayFunctionSignature::ArrayAndIndex => {
- if current_types.len() != 2 {
+ ArrayFunctionSignature::ArrayAndIndexes(count) => {
+ if current_types.len() != count.get() + 1 {
return Ok(vec![vec![]]);
}
array(¤t_types[0]).map_or_else(
|| vec![vec![]],
- |array_type| vec![vec![array_type, DataType::Int64]],
+ |array_type| {
+ let mut inner = Vec::with_capacity(count.get() + 1);
+ inner.push(array_type);
+ for _ in 0..count.get() {
+ inner.push(DataType::Int64);
+ }
+ vec![inner]
+ },
)
}
ArrayFunctionSignature::ArrayAndElementAndOptionalIndex => {
diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs
index aa6a5cddad..7c91b6b3b4 100644
--- a/datafusion/expr/src/udf.rs
+++ b/datafusion/expr/src/udf.rs
@@ -200,6 +200,11 @@ impl ScalarUDF {
self.inner.return_type_from_args(args)
}
+ /// Returns the behavior that this function has when any of the inputs are
Null.
+ pub fn null_handling(&self) -> NullHandling {
+ self.inner.null_handling()
+ }
+
/// Do the function rewrite
///
/// See [`ScalarUDFImpl::simplify`] for more details.
@@ -417,6 +422,15 @@ impl ReturnInfo {
}
}
+/// A function's behavior when the input is Null.
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
+pub enum NullHandling {
+ /// Null inputs are passed into the function implementation.
+ PassThrough,
+ /// Any Null input causes the function to return Null.
+ Propagate,
+}
+
/// Trait for implementing user defined scalar functions.
///
/// This trait exposes the full API for implementing user defined functions and
@@ -589,6 +603,11 @@ pub trait ScalarUDFImpl: Debug + Send + Sync {
true
}
+ /// Returns the behavior that this function has when any of the inputs are
Null.
+ fn null_handling(&self) -> NullHandling {
+ NullHandling::PassThrough
+ }
+
/// Invoke the function on `args`, returning the appropriate result
///
/// Note: This method is deprecated and will be removed in future releases.
diff --git a/datafusion/functions-nested/src/extract.rs
b/datafusion/functions-nested/src/extract.rs
index cce10d2bf6..c87a96dca7 100644
--- a/datafusion/functions-nested/src/extract.rs
+++ b/datafusion/functions-nested/src/extract.rs
@@ -27,6 +27,7 @@ use arrow::array::MutableArrayData;
use arrow::array::OffsetSizeTrait;
use arrow::buffer::OffsetBuffer;
use arrow::datatypes::DataType;
+use arrow_buffer::NullBufferBuilder;
use arrow_schema::DataType::{FixedSizeList, LargeList, List};
use arrow_schema::Field;
use datafusion_common::cast::as_int64_array;
@@ -35,12 +36,13 @@ use datafusion_common::cast::as_list_array;
use datafusion_common::{
exec_err, internal_datafusion_err, plan_err, DataFusionError, Result,
};
-use datafusion_expr::Expr;
+use datafusion_expr::{ArrayFunctionSignature, Expr, TypeSignature};
use datafusion_expr::{
- ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
+ ColumnarValue, Documentation, NullHandling, ScalarUDFImpl, Signature,
Volatility,
};
use datafusion_macros::user_doc;
use std::any::Any;
+use std::num::NonZeroUsize;
use std::sync::Arc;
use crate::utils::make_scalar_function;
@@ -330,7 +332,26 @@ pub(super) struct ArraySlice {
impl ArraySlice {
pub fn new() -> Self {
Self {
- signature: Signature::variadic_any(Volatility::Immutable),
+ signature: Signature::one_of(
+ vec![
+ TypeSignature::ArraySignature(
+ ArrayFunctionSignature::ArrayAndIndexes(
+ NonZeroUsize::new(1).expect("1 is non-zero"),
+ ),
+ ),
+ TypeSignature::ArraySignature(
+ ArrayFunctionSignature::ArrayAndIndexes(
+ NonZeroUsize::new(2).expect("2 is non-zero"),
+ ),
+ ),
+ TypeSignature::ArraySignature(
+ ArrayFunctionSignature::ArrayAndIndexes(
+ NonZeroUsize::new(3).expect("3 is non-zero"),
+ ),
+ ),
+ ],
+ Volatility::Immutable,
+ ),
aliases: vec![String::from("list_slice")],
}
}
@@ -374,6 +395,10 @@ impl ScalarUDFImpl for ArraySlice {
Ok(arg_types[0].clone())
}
+ fn null_handling(&self) -> NullHandling {
+ NullHandling::Propagate
+ }
+
fn invoke_batch(
&self,
args: &[ColumnarValue],
@@ -430,8 +455,6 @@ fn array_slice_inner(args: &[ArrayRef]) -> Result<ArrayRef>
{
}
LargeList(_) => {
let array = as_large_list_array(&args[0])?;
- let from_array = as_int64_array(&args[1])?;
- let to_array = as_int64_array(&args[2])?;
general_array_slice::<i64>(array, from_array, to_array, stride)
}
_ => exec_err!("array_slice does not support type: {:?}",
array_data_type),
@@ -451,9 +474,8 @@ where
let original_data = values.to_data();
let capacity = Capacities::Array(original_data.len());
- // use_nulls: false, we don't need nulls but empty array for array_slice,
so we don't need explicit nulls but adjust offset to indicate nulls.
let mut mutable =
- MutableArrayData::with_capacities(vec![&original_data], false,
capacity);
+ MutableArrayData::with_capacities(vec![&original_data], true,
capacity);
// We have the slice syntax compatible with DuckDB v0.8.1.
// The rule `adjusted_from_index` and `adjusted_to_index` follows the rule
of array_slice in duckdb.
@@ -516,30 +538,33 @@ where
}
let mut offsets = vec![O::usize_as(0)];
+ let mut null_builder = NullBufferBuilder::new(array.len());
for (row_index, offset_window) in array.offsets().windows(2).enumerate() {
let start = offset_window[0];
let end = offset_window[1];
let len = end - start;
- // len 0 indicate array is null, return empty array in this row.
+ // If any input is null, return null.
+ if array.is_null(row_index)
+ || from_array.is_null(row_index)
+ || to_array.is_null(row_index)
+ {
+ mutable.extend_nulls(1);
+ offsets.push(offsets[row_index] + O::usize_as(1));
+ null_builder.append_null();
+ continue;
+ }
+ null_builder.append_non_null();
+
+ // Empty arrays always return an empty array.
if len == O::usize_as(0) {
offsets.push(offsets[row_index]);
continue;
}
- // If index is null, we consider it as the minimum / maximum index of
the array.
- let from_index = if from_array.is_null(row_index) {
- Some(O::usize_as(0))
- } else {
- adjusted_from_index::<O>(from_array.value(row_index), len)?
- };
-
- let to_index = if to_array.is_null(row_index) {
- Some(len - O::usize_as(1))
- } else {
- adjusted_to_index::<O>(to_array.value(row_index), len)?
- };
+ let from_index = adjusted_from_index::<O>(from_array.value(row_index),
len)?;
+ let to_index = adjusted_to_index::<O>(to_array.value(row_index), len)?;
if let (Some(from), Some(to)) = (from_index, to_index) {
let stride = stride.map(|s| s.value(row_index));
@@ -613,7 +638,7 @@ where
Arc::new(Field::new_list_field(array.value_type(), true)),
OffsetBuffer::<O>::new(offsets.into()),
arrow_array::make_array(data),
- None,
+ null_builder.finish(),
)?))
}
@@ -665,6 +690,10 @@ impl ScalarUDFImpl for ArrayPopFront {
Ok(arg_types[0].clone())
}
+ fn null_handling(&self) -> NullHandling {
+ NullHandling::Propagate
+ }
+
fn invoke_batch(
&self,
args: &[ColumnarValue],
@@ -765,6 +794,10 @@ impl ScalarUDFImpl for ArrayPopBack {
Ok(arg_types[0].clone())
}
+ fn null_handling(&self) -> NullHandling {
+ NullHandling::Propagate
+ }
+
fn invoke_batch(
&self,
args: &[ColumnarValue],
diff --git a/datafusion/physical-expr/src/scalar_function.rs
b/datafusion/physical-expr/src/scalar_function.rs
index 936adbc098..1cd4b673ce 100644
--- a/datafusion/physical-expr/src/scalar_function.rs
+++ b/datafusion/physical-expr/src/scalar_function.rs
@@ -45,7 +45,8 @@ use datafusion_expr::interval_arithmetic::Interval;
use datafusion_expr::sort_properties::ExprProperties;
use datafusion_expr::type_coercion::functions::data_types_with_scalar_udf;
use datafusion_expr::{
- expr_vec_fmt, ColumnarValue, Expr, ReturnTypeArgs, ScalarFunctionArgs,
ScalarUDF,
+ expr_vec_fmt, ColumnarValue, Expr, NullHandling, ReturnTypeArgs,
ScalarFunctionArgs,
+ ScalarUDF,
};
/// Physical expression of a scalar function
@@ -186,6 +187,15 @@ impl PhysicalExpr for ScalarFunctionExpr {
.map(|e| e.evaluate(batch))
.collect::<Result<Vec<_>>>()?;
+ if self.fun.null_handling() == NullHandling::Propagate
+ && args.iter().any(
+ |arg| matches!(arg, ColumnarValue::Scalar(scalar) if
scalar.is_null()),
+ )
+ {
+ let null_value = ScalarValue::try_from(&self.return_type)?;
+ return Ok(ColumnarValue::Scalar(null_value));
+ }
+
let input_empty = args.is_empty();
let input_all_scalar = args
.iter()
diff --git a/datafusion/sqllogictest/test_files/array.slt
b/datafusion/sqllogictest/test_files/array.slt
index 46dbb48166..ce66acd670 100644
--- a/datafusion/sqllogictest/test_files/array.slt
+++ b/datafusion/sqllogictest/test_files/array.slt
@@ -950,9 +950,9 @@ select column1[2:4], column2[1:4], column3[3:4] from arrays;
[[5, 6]] [NULL, 5.5, 6.6] [NULL, u]
[[7, 8]] [7.7, 8.8, 9.9] [l, o]
[[9, 10]] [10.1, NULL, 12.2] [t]
-[] [13.3, 14.4, 15.5] [e, t]
-[[13, 14]] [] []
-[[NULL, 18]] [16.6, 17.7, 18.8] []
+NULL [13.3, 14.4, 15.5] [e, t]
+[[13, 14]] NULL []
+[[NULL, 18]] [16.6, 17.7, 18.8] NULL
# multiple index with columns #2 (zero index)
query ???
@@ -962,9 +962,9 @@ select column1[0:5], column2[0:3], column3[0:9] from arrays;
[[3, 4], [5, 6]] [NULL, 5.5, 6.6] [i, p, NULL, u, m]
[[5, 6], [7, 8]] [7.7, 8.8, 9.9] [d, NULL, l, o, r]
[[7, NULL], [9, 10]] [10.1, NULL, 12.2] [s, i, t]
-[] [13.3, 14.4, 15.5] [a, m, e, t]
-[[11, 12], [13, 14]] [] [,]
-[[15, 16], [NULL, 18]] [16.6, 17.7, 18.8] []
+NULL [13.3, 14.4, 15.5] [a, m, e, t]
+[[11, 12], [13, 14]] NULL [,]
+[[15, 16], [NULL, 18]] [16.6, 17.7, 18.8] NULL
# TODO: support negative index
# multiple index with columns #3 (negative index)
@@ -1026,9 +1026,9 @@ select column1[2:4:2], column2[1:4:2], column3[3:4:2]
from arrays;
[[5, 6]] [NULL, 6.6] [NULL]
[[7, 8]] [7.7, 9.9] [l]
[[9, 10]] [10.1, 12.2] [t]
-[] [13.3, 15.5] [e]
-[[13, 14]] [] []
-[[NULL, 18]] [16.6, 18.8] []
+NULL [13.3, 15.5] [e]
+[[13, 14]] NULL []
+[[NULL, 18]] [16.6, 18.8] NULL
# multiple index with columns #2 (zero index)
query ???
@@ -1038,9 +1038,9 @@ select column1[0:5:2], column2[0:3:2], column3[0:9:2]
from arrays;
[[3, 4]] [NULL, 6.6] [i, NULL, m]
[[5, 6]] [7.7, 9.9] [d, l, r]
[[7, NULL]] [10.1, 12.2] [s, t]
-[] [13.3, 15.5] [a, e]
-[[11, 12]] [] [,]
-[[15, 16]] [16.6, 18.8] []
+NULL [13.3, 15.5] [a, e]
+[[11, 12]] NULL [,]
+[[15, 16]] [16.6, 18.8] NULL
### Array function tests
@@ -1579,7 +1579,7 @@ select array_pop_back(column1) from arrayspop;
[3, 4, 5]
[6, 7, 8, NULL]
[NULL, NULL]
-[]
+NULL
[NULL, 10, 11]
query ?
@@ -1589,7 +1589,7 @@ select array_pop_back(arrow_cast(column1,
'LargeList(Int64)')) from arrayspop;
[3, 4, 5]
[6, 7, 8, NULL]
[NULL, NULL]
-[]
+NULL
[NULL, 10, 11]
query ?
@@ -1599,7 +1599,7 @@ select array_pop_back(column1) from large_arrayspop;
[3, 4, 5]
[6, 7, 8, NULL]
[NULL, NULL]
-[]
+NULL
[NULL, 10, 11]
query ?
@@ -1609,7 +1609,7 @@ select array_pop_back(arrow_cast(column1,
'LargeList(Int64)')) from large_arrays
[3, 4, 5]
[6, 7, 8, NULL]
[NULL, NULL]
-[]
+NULL
[NULL, 10, 11]
## array_pop_front (aliases: `list_pop_front`)
@@ -1817,18 +1817,26 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4,
5), 'LargeList(Int64)'), 0,
[1, 2, 3, 4] [h, e, l]
# array_slice scalar function #8 (with NULL and positive number)
-query error
+query ??
select array_slice(make_array(1, 2, 3, 4, 5), NULL, 4),
array_slice(make_array('h', 'e', 'l', 'l', 'o'), NULL, 3);
+----
+NULL NULL
-query error
+query ??
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
NULL, 4), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'),
'LargeList(Utf8)'), NULL, 3);
+----
+NULL NULL
# array_slice scalar function #9 (with positive number and NULL)
-query error
+query ??
select array_slice(make_array(1, 2, 3, 4, 5), 2, NULL),
array_slice(make_array('h', 'e', 'l', 'l', 'o'), 3, NULL);
+----
+NULL NULL
-query error
+query ??
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
2, NULL), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'),
'LargeList(Utf8)'), 3, NULL);
+----
+NULL NULL
# array_slice scalar function #10 (with zero-zero)
query ??
@@ -1842,12 +1850,15 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4,
5), 'LargeList(Int64)'), 0,
[] []
# array_slice scalar function #11 (with NULL-NULL)
-query error
+query ??
select array_slice(make_array(1, 2, 3, 4, 5), NULL),
array_slice(make_array('h', 'e', 'l', 'l', 'o'), NULL);
+----
+NULL NULL
-query error
+query ??
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
NULL), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'),
'LargeList(Utf8)'), NULL);
-
+----
+NULL NULL
# array_slice scalar function #12 (with zero and negative number)
query ??
@@ -1861,18 +1872,26 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4,
5), 'LargeList(Int64)'), 0,
[1, 2] [h, e, l]
# array_slice scalar function #13 (with negative number and NULL)
-query error
+query ??
select array_slice(make_array(1, 2, 3, 4, 5), -2, NULL),
array_slice(make_array('h', 'e', 'l', 'l', 'o'), -3, NULL);
+----
+NULL NULL
-query error
+query ??
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
-2, NULL), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'),
'LargeList(Utf8)'), -3, NULL);
+----
+NULL NULL
# array_slice scalar function #14 (with NULL and negative number)
-query error
+query ??
select array_slice(make_array(1, 2, 3, 4, 5), NULL, -4),
array_slice(make_array('h', 'e', 'l', 'l', 'o'), NULL, -3);
+----
+NULL NULL
-query error
+query ??
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
NULL, -4), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'),
'LargeList(Utf8)'), NULL, -3);
+----
+NULL NULL
# array_slice scalar function #15 (with negative indexes)
query ??
@@ -1982,9 +2001,9 @@ select array_slice(column1, column2, column3) from slices;
[12, 13, 14, 15, 16, 17]
[]
[]
-[]
-[41, 42, 43, 44, 45, 46]
-[55, 56, 57, 58, 59, 60]
+NULL
+NULL
+NULL
query ?
select array_slice(arrow_cast(column1, 'LargeList(Int64)'), column2, column3)
from slices;
@@ -1993,9 +2012,9 @@ select array_slice(arrow_cast(column1,
'LargeList(Int64)'), column2, column3) fr
[12, 13, 14, 15, 16, 17]
[]
[]
-[]
-[41, 42, 43, 44, 45, 46]
-[55, 56, 57, 58, 59, 60]
+NULL
+NULL
+NULL
# TODO: support NULLS in output instead of `[]`
# array_slice with columns and scalars
@@ -2006,9 +2025,9 @@ select array_slice(make_array(1, 2, 3, 4, 5), column2,
column3), array_slice(col
[2] [13, 14, 15, 16, 17] [12, 13, 14, 15]
[] [] [21, 22, 23, NULL, 25]
[] [33, 34] []
-[4, 5] [] []
-[1, 2, 3, 4, 5] [43, 44, 45, 46] [41, 42, 43, 44, 45]
-[5] [NULL, 54, 55, 56, 57, 58, 59, 60] [55]
+[4, 5] NULL NULL
+NULL [43, 44, 45, 46] NULL
+NULL NULL [55]
query ???
select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'),
column2, column3), array_slice(arrow_cast(column1, 'LargeList(Int64)'), 3,
column3), array_slice(arrow_cast(column1, 'LargeList(Int64)'), column2, 5) from
slices;
@@ -2017,9 +2036,9 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5),
'LargeList(Int64)'), co
[2] [13, 14, 15, 16, 17] [12, 13, 14, 15]
[] [] [21, 22, 23, NULL, 25]
[] [33, 34] []
-[4, 5] [] []
-[1, 2, 3, 4, 5] [43, 44, 45, 46] [41, 42, 43, 44, 45]
-[5] [NULL, 54, 55, 56, 57, 58, 59, 60] [55]
+[4, 5] NULL NULL
+NULL [43, 44, 45, 46] NULL
+NULL NULL [55]
# Test issue: https://github.com/apache/datafusion/issues/10425
# `from` may be larger than `to` and `stride` is positive
@@ -2036,6 +2055,9 @@ select array_slice(a, -1, 2, 1), array_slice(a, -1, 2),
query error DataFusion error: Error during planning: array_slice does not
support zero arguments
select array_slice();
+query error Failed to coerce arguments
+select array_slice(3.5, NULL, NULL);
+
## array_any_value (aliases: list_any_value)
# Testing with empty arguments should result in an error
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]