Skip to content

Commit 52646df

Browse files
committed
feat[array]: move boolean ops to lazy binary expr
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent d687ea7 commit 52646df

1 file changed

Lines changed: 53 additions & 1 deletion

File tree

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,73 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use vortex_dtype::DType;
45
use vortex_error::VortexResult;
6+
use vortex_error::vortex_err;
7+
use vortex_scalar::Scalar;
58

69
use crate::Array;
710
use crate::ArrayRef;
11+
use crate::IntoArray;
12+
use crate::arrays::ConstantArray;
13+
use crate::arrays::ConstantVTable;
814
use crate::compute::BooleanOperator;
915
use crate::compute::arrow_boolean;
1016

1117
/// Execute a boolean operation between two arrays.
1218
///
1319
/// This is the entry point for boolean operations from the binary expression.
14-
/// Falls back to Arrow for the actual computation.
20+
/// Handles constant-constant directly, otherwise falls back to Arrow.
1521
pub(crate) fn execute_boolean(
1622
lhs: &dyn Array,
1723
rhs: &dyn Array,
1824
op: BooleanOperator,
1925
) -> VortexResult<ArrayRef> {
26+
if let Some(result) = constant_boolean(lhs, rhs, op)? {
27+
return Ok(result);
28+
}
2029
arrow_boolean(lhs.to_array(), rhs.to_array(), op)
2130
}
31+
32+
fn constant_boolean(
33+
lhs: &dyn Array,
34+
rhs: &dyn Array,
35+
op: BooleanOperator,
36+
) -> VortexResult<Option<ArrayRef>> {
37+
let (Some(lhs), Some(rhs)) = (
38+
lhs.as_opt::<ConstantVTable>(),
39+
rhs.as_opt::<ConstantVTable>(),
40+
) else {
41+
return Ok(None);
42+
};
43+
44+
let length = lhs.len();
45+
let nullable = lhs.dtype().is_nullable() || rhs.dtype().is_nullable();
46+
let lhs_val = lhs.scalar().as_bool().value();
47+
let rhs_val = rhs
48+
.scalar()
49+
.as_bool_opt()
50+
.ok_or_else(|| vortex_err!("expected rhs to be boolean"))?
51+
.value();
52+
53+
let result = match op {
54+
BooleanOperator::And => lhs_val.zip(rhs_val).map(|(l, r)| l & r),
55+
BooleanOperator::AndKleene => match (lhs_val, rhs_val) {
56+
(Some(false), _) | (_, Some(false)) => Some(false),
57+
(None, _) | (_, None) => None,
58+
(Some(l), Some(r)) => Some(l & r),
59+
},
60+
BooleanOperator::Or => lhs_val.zip(rhs_val).map(|(l, r)| l | r),
61+
BooleanOperator::OrKleene => match (lhs_val, rhs_val) {
62+
(Some(true), _) | (_, Some(true)) => Some(true),
63+
(None, _) | (_, None) => None,
64+
(Some(l), Some(r)) => Some(l | r),
65+
},
66+
};
67+
68+
let scalar = result
69+
.map(|b| Scalar::bool(b, nullable.into()))
70+
.unwrap_or_else(|| Scalar::null(DType::Bool(nullable.into())));
71+
72+
Ok(Some(ConstantArray::new(scalar, length).into_array()))
73+
}

0 commit comments

Comments
 (0)