Skip to content

Commit 0164659

Browse files
committed
u
Signed-off-by: Joe Isaacs <[email protected]>
1 parent acbb439 commit 0164659

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

vortex-array/src/arrays/expr/array.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,58 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use vortex_dtype::DType;
5-
use vortex_error::VortexResult;
5+
use vortex_error::{VortexResult, vortex_ensure};
66

77
use crate::expr::Expression;
88
use crate::stats::ArrayStats;
99
use crate::{Array, ArrayRef};
1010

11+
/// A array that represents an expression to be evaluated over a child array.
12+
///
13+
/// `ExprArray` enables deferred evaluation of expressions by wrapping a child array
14+
/// with an expression that operates on it. The expression is not evaluated until the
15+
/// array is canonicalized/executed.
16+
///
17+
/// # Examples
18+
///
19+
/// ```ignore
20+
/// // Create an expression that filters an integer array
21+
/// let data = PrimitiveArray::from_iter([1, 2, 3, 4, 5]);
22+
/// let expr = gt(root(), lit(3)); // $ > 3
23+
/// let expr_array = ExprArray::new_infer_dtype(data.into_array(), expr)?;
24+
///
25+
/// // The expression is evaluated when canonicalized
26+
/// let result = expr_array.to_canonical(); // Returns BoolArray([false, false, false, true, true])
27+
/// ```
28+
///
29+
/// # Type Safety
30+
///
31+
/// The `dtype` field must match `expr.return_dtype(child.dtype())`. This invariant
32+
/// is enforced by the safe constructors ([`try_new`](ExprArray::try_new) and
33+
/// [`new_infer_dtype`](ExprArray::new_infer_dtype)) but can be bypassed
34+
/// with [`unchecked_new`](ExprArray::unchecked_new) for performance-critical code.
1135
#[derive(Clone, Debug)]
1236
pub struct ExprArray {
37+
/// The underlying array that the expression will operate on.
1338
pub(super) child: ArrayRef,
39+
/// The expression to evaluate over the child array.
1440
pub(super) expr: Expression,
41+
/// The data type of the result after evaluating the expression.
1542
pub(super) dtype: DType,
43+
/// Statistics about the resulting array (may be computed lazily).
1644
pub(super) stats: ArrayStats,
1745
}
1846

1947
impl ExprArray {
2048
/// Creates a new ExprArray with the dtype validated to match the expression's return type.
2149
pub fn try_new(child: ArrayRef, expr: Expression, dtype: DType) -> VortexResult<Self> {
22-
assert_eq!(dtype, expr.return_dtype(child.dtype())?);
50+
let expected_dtype = expr.return_dtype(child.dtype())?;
51+
vortex_ensure!(
52+
dtype == expected_dtype,
53+
"ExprArray dtype mismatch: expected {}, got {}",
54+
expected_dtype,
55+
dtype
56+
);
2357
Ok(unsafe { Self::unchecked_new(child, expr, dtype) })
2458
}
2559

@@ -34,6 +68,7 @@ impl ExprArray {
3468
child,
3569
expr,
3670
dtype,
71+
// TODO(joe): Propagate or compute statistics from the child array and expression.
3772
stats: ArrayStats::default(),
3873
}
3974
}

vortex-array/src/arrays/expr/vtable/mod.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub struct ExprEncoding;
2727
impl VTable for ExprVTable {
2828
type Array = ExprArray;
2929
type Encoding = ExprEncoding;
30-
type Metadata = ExprDisplay;
30+
type Metadata = ExprArrayMetadata;
3131

3232
type ArrayVTable = Self;
3333
type CanonicalVTable = Self;
@@ -47,7 +47,7 @@ impl VTable for ExprVTable {
4747
}
4848

4949
fn metadata(array: &ExprArray) -> VortexResult<Self::Metadata> {
50-
Ok(ExprDisplay(array.expr.clone()))
50+
Ok(ExprArrayMetadata((array.expr.clone(), array.dtype.clone())))
5151
}
5252

5353
fn serialize(_metadata: Self::Metadata) -> VortexResult<Option<Vec<u8>>> {
@@ -62,26 +62,27 @@ impl VTable for ExprVTable {
6262
_encoding: &ExprEncoding,
6363
dtype: &DType,
6464
len: usize,
65-
metadata: &Self::Metadata,
65+
ExprArrayMetadata((expr, root_dtype)): &Self::Metadata,
6666
buffers: &[ByteBuffer],
6767
children: &dyn ArrayChildren,
6868
) -> VortexResult<ExprArray> {
6969
if !buffers.is_empty() {
7070
vortex_bail!("Expected 0 buffers, got {}", buffers.len());
7171
}
7272

73-
let Ok(child) = children.get(0, dtype, len) else {
73+
let Ok(child) = children.get(0, root_dtype, len) else {
7474
vortex_bail!("Expected 1 child, got {}", children.len());
7575
};
7676

77-
ExprArray::try_new(child, metadata.0.clone(), dtype.clone())
77+
ExprArray::try_new(child, expr.clone(), dtype.clone())
7878
}
7979
}
8080

81-
pub struct ExprDisplay(Expression);
81+
pub struct ExprArrayMetadata((Expression, DType));
8282

83-
impl Debug for ExprDisplay {
83+
impl Debug for ExprArrayMetadata {
8484
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85-
self.0.fmt_sql(f)
85+
// Since this is used in display method we can omit the dtype.
86+
self.0.0.fmt_sql(f)
8687
}
8788
}

0 commit comments

Comments
 (0)