@@ -35,8 +35,8 @@ pub use project::*;
3535pub use row_filter:: * ;
3636pub use select:: * ;
3737use vortex_array:: aliases:: hash_set:: HashSet ;
38- use vortex_array:: ArrayData ;
39- use vortex_dtype:: Field ;
38+ use vortex_array:: { ArrayDType as _ , ArrayData , Canonical , IntoArrayData as _ } ;
39+ use vortex_dtype:: { DType , Field } ;
4040use vortex_error:: { VortexResult , VortexUnwrap } ;
4141
4242use crate :: traversal:: { Node , ReferenceCollector } ;
@@ -49,11 +49,30 @@ pub trait VortexExpr: Debug + Send + Sync + DynEq + DynHash + Display {
4949 fn as_any ( & self ) -> & dyn Any ;
5050
5151 /// Compute result of expression on given batch producing a new batch
52- fn evaluate ( & self , batch : & ArrayData ) -> VortexResult < ArrayData > ;
52+ ///
53+ fn evaluate ( & self , batch : & ArrayData ) -> VortexResult < ArrayData > {
54+ let result = self . unchecked_evaluate ( batch) ?;
55+ debug_assert_eq ! ( result. dtype( ) , & self . return_dtype( batch. dtype( ) ) ?) ;
56+ Ok ( result)
57+ }
58+
59+ /// Compute result of expression on given batch producing a new batch
60+ ///
61+ /// "Unchecked" means that this function lacks a debug assertion that the returned array matches
62+ /// the [VortexExpr::return_dtype] method. Use instead the [VortexExpr::evaluate] function which
63+ /// includes such an assertion.
64+ fn unchecked_evaluate ( & self , batch : & ArrayData ) -> VortexResult < ArrayData > ;
5365
5466 fn children ( & self ) -> Vec < & ExprRef > ;
5567
5668 fn replacing_children ( self : Arc < Self > , children : Vec < ExprRef > ) -> ExprRef ;
69+
70+ /// Compute the type of the array returned by [VortexExpr::evaluate].
71+ fn return_dtype ( & self , scope_dtype : & DType ) -> VortexResult < DType > {
72+ let empty = Canonical :: empty ( scope_dtype) ?. into_array ( ) ;
73+ self . unchecked_evaluate ( & empty)
74+ . map ( |array| array. into_dtype ( ) )
75+ }
5776}
5877
5978pub trait VortexExprExt {
@@ -112,6 +131,34 @@ impl Eq for dyn VortexExpr {}
112131
113132dyn_hash:: hash_trait_object!( VortexExpr ) ;
114133
134+ #[ cfg( feature = "test-harness" ) ]
135+ pub mod test_harness {
136+ use vortex_dtype:: { DType , Nullability , PType , StructDType } ;
137+
138+ pub fn struct_dtype ( ) -> DType {
139+ DType :: Struct (
140+ StructDType :: new (
141+ [
142+ "a" . into ( ) ,
143+ "col1" . into ( ) ,
144+ "col2" . into ( ) ,
145+ "bool1" . into ( ) ,
146+ "bool2" . into ( ) ,
147+ ]
148+ . into ( ) ,
149+ vec ! [
150+ DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ,
151+ DType :: Primitive ( PType :: U16 , Nullability :: Nullable ) ,
152+ DType :: Primitive ( PType :: U16 , Nullability :: Nullable ) ,
153+ DType :: Bool ( Nullability :: NonNullable ) ,
154+ DType :: Bool ( Nullability :: NonNullable ) ,
155+ ] ,
156+ ) ,
157+ Nullability :: NonNullable ,
158+ )
159+ }
160+ }
161+
115162#[ cfg( test) ]
116163mod tests {
117164 use vortex_dtype:: { DType , Field , Nullability , PType , StructDType } ;
0 commit comments