Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions vortex-array/src/arrays/constant/compute/between.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::IntoArray;
use crate::array::ArrayView;
use crate::arrays::Constant;
use crate::arrays::ConstantArray;
use crate::dtype::DType;
use crate::scalar::Scalar;
use crate::scalar_fn::fns::between::BetweenOptions;
use crate::scalar_fn::fns::between::BetweenReduce;
Expand All @@ -24,6 +25,19 @@ impl BetweenReduce for Constant {
.zip(lower.as_constant())
.zip(upper.as_constant())
{
let nullability = array.dtype().nullability()
| lower.dtype().nullability()
| upper.dtype().nullability();

// `Scalar` orders null below every value, so comparing a null constant would give a
// non-null false. The result is null instead.
if constant.is_null() {
return Ok(Some(
ConstantArray::new(Scalar::null(DType::Bool(nullability)), array.len())
.into_array(),
));
}

let BetweenOptions {
lower_strict,
upper_strict,
Expand All @@ -43,12 +57,7 @@ impl BetweenReduce for Constant {

let result = lower_result && upper_result;

let scalar = Scalar::bool(
result,
array.dtype().nullability()
| lower.dtype().nullability()
| upper.dtype().nullability(),
);
let scalar = Scalar::bool(result, nullability);
return Ok(Some(ConstantArray::new(scalar, array.len()).into_array()));
}

Expand Down
30 changes: 30 additions & 0 deletions vortex-array/src/scalar_fn/fns/between/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,36 @@ mod tests {
Ok(())
}

/// Compression stores an all-null chunk as a [`ConstantArray`]. Its rows must come out null
/// rather than false, since `NOT` turns a false row into a match.
#[rstest]
#[case::f64(Scalar::null_native::<f64>(), Scalar::from(-0.0f64), Scalar::from(0.0f64))]
#[case::i32(Scalar::null_native::<i32>(), Scalar::from(0i32), Scalar::from(0i32))]
fn constant_null_array(
#[case] null: Scalar,
#[case] lower: Scalar,
#[case] upper: Scalar,
) -> VortexResult<()> {
let ctx = &mut SESSION.create_execution_ctx();
let array = ConstantArray::new(null, 3).into_array();
let lower = ConstantArray::new(lower, 3).into_array();
let upper = ConstantArray::new(upper, 3).into_array();

let between = array.between(lower, upper, NON_STRICT)?;
let not_between = between.not()?;

assert_eq!(
between.execute::<BoolArray>(ctx)?.opt_bool_vec(ctx),
[None, None, None]
);
assert_eq!(
not_between.execute::<BoolArray>(ctx)?.opt_bool_vec(ctx),
[None, None, None]
);

Ok(())
}

#[test]
fn test_between_decimal() {
let ctx = &mut SESSION.create_execution_ctx();
Expand Down