@@ -7,8 +7,10 @@ use std::fmt::Debug;
77use std:: sync:: Arc ;
88
99use vortex_error:: VortexResult ;
10+ use vortex_error:: vortex_ensure;
1011use vortex_session:: VortexSession ;
1112
13+ use crate :: dtype:: DType ;
1214use crate :: expr:: Expression ;
1315use crate :: expr:: or_collect;
1416use crate :: scalar_fn:: ScalarFnId ;
@@ -54,28 +56,45 @@ pub(crate) trait StatsRewriteRule: Debug + Send + Sync + 'static {
5456/// Context passed to stats rewrite rules.
5557pub ( crate ) struct StatsRewriteCtx < ' a > {
5658 session : & ' a VortexSession ,
59+ scope : & ' a DType ,
5760}
5861
5962impl < ' a > StatsRewriteCtx < ' a > {
6063 /// Create a rewrite context for `session`.
61- pub ( crate ) fn new ( session : & ' a VortexSession ) -> Self {
62- Self { session }
64+ pub ( crate ) fn new ( session : & ' a VortexSession , scope : & ' a DType ) -> Self {
65+ Self { session, scope }
6366 }
6467
6568 /// Returns the session that owns the rewrite registry.
6669 pub ( crate ) fn session ( & self ) -> & ' a VortexSession {
6770 self . session
6871 }
6972
73+ /// Return the dtype of `expr` within this rewrite scope.
74+ pub ( crate ) fn return_dtype ( & self , expr : & Expression ) -> VortexResult < DType > {
75+ expr. return_dtype ( self . scope )
76+ }
77+
7078 /// Rewrite `expr` into a stats-backed falsifier.
7179 pub ( crate ) fn falsify ( & self , expr : & Expression ) -> VortexResult < Option < Expression > > {
80+ self . ensure_predicate ( expr) ?;
7281 rewrite ( expr, self , StatsRewriteRule :: falsify)
7382 }
7483
7584 /// Rewrite `expr` into a stats-backed satisfier.
7685 pub ( crate ) fn satisfy ( & self , expr : & Expression ) -> VortexResult < Option < Expression > > {
86+ self . ensure_predicate ( expr) ?;
7787 rewrite ( expr, self , StatsRewriteRule :: satisfy)
7888 }
89+
90+ fn ensure_predicate ( & self , expr : & Expression ) -> VortexResult < ( ) > {
91+ let dtype = self . return_dtype ( expr) ?;
92+ vortex_ensure ! (
93+ matches!( dtype, DType :: Bool ( _) ) ,
94+ "Stats rewrites require a boolean predicate, got {dtype}" ,
95+ ) ;
96+ Ok ( ( ) )
97+ }
7998}
8099
81100fn rewrite (
@@ -112,6 +131,9 @@ mod tests {
112131
113132 use super :: StatsRewriteCtx ;
114133 use super :: StatsRewriteRule ;
134+ use crate :: dtype:: DType ;
135+ use crate :: dtype:: Nullability ;
136+ use crate :: dtype:: PType ;
115137 use crate :: expr:: Expression ;
116138 use crate :: expr:: lit;
117139 use crate :: expr:: or;
@@ -152,6 +174,7 @@ mod tests {
152174 #[ test]
153175 fn combines_multiple_falsifiers_with_or ( ) -> VortexResult < ( ) > {
154176 let session = VortexSession :: empty ( ) . with :: < StatsRewriteSession > ( ) ;
177+ let dtype = DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ;
155178 session. stats_rewrites ( ) . register ( StaticLiteralRule {
156179 falsifier : Some ( lit ( false ) ) ,
157180 satisfier : None ,
@@ -161,13 +184,17 @@ mod tests {
161184 satisfier : None ,
162185 } ) ;
163186
164- assert_eq ! ( lit( 7 ) . falsify( & session) ?, Some ( or( lit( false ) , lit( true ) ) ) ) ;
187+ assert_eq ! (
188+ lit( true ) . falsify( & dtype, & session) ?,
189+ Some ( or( lit( false ) , lit( true ) ) )
190+ ) ;
165191 Ok ( ( ) )
166192 }
167193
168194 #[ test]
169195 fn combines_multiple_satisfiers_with_or ( ) -> VortexResult < ( ) > {
170196 let session = VortexSession :: empty ( ) . with :: < StatsRewriteSession > ( ) ;
197+ let dtype = DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ;
171198 session. stats_rewrites ( ) . register ( StaticLiteralRule {
172199 falsifier : None ,
173200 satisfier : Some ( lit ( false ) ) ,
@@ -177,16 +204,29 @@ mod tests {
177204 satisfier : Some ( lit ( true ) ) ,
178205 } ) ;
179206
180- assert_eq ! ( lit( 7 ) . satisfy( & session) ?, Some ( or( lit( false ) , lit( true ) ) ) ) ;
207+ assert_eq ! (
208+ lit( true ) . satisfy( & dtype, & session) ?,
209+ Some ( or( lit( false ) , lit( true ) ) )
210+ ) ;
181211 Ok ( ( ) )
182212 }
183213
184214 #[ test]
185215 fn unregistered_expression_has_no_rewrite ( ) -> VortexResult < ( ) > {
186216 let session = VortexSession :: empty ( ) . with :: < StatsRewriteSession > ( ) ;
217+ let dtype = DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ;
187218
188- assert_eq ! ( lit( 7 ) . falsify( & session) ?, None ) ;
189- assert_eq ! ( lit( 7 ) . satisfy( & session) ?, None ) ;
219+ assert_eq ! ( lit( true ) . falsify( & dtype , & session) ?, None ) ;
220+ assert_eq ! ( lit( true ) . satisfy( & dtype , & session) ?, None ) ;
190221 Ok ( ( ) )
191222 }
223+
224+ #[ test]
225+ fn non_predicate_expression_errors ( ) {
226+ let session = VortexSession :: empty ( ) . with :: < StatsRewriteSession > ( ) ;
227+ let dtype = DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ;
228+
229+ assert ! ( lit( 7 ) . falsify( & dtype, & session) . is_err( ) ) ;
230+ assert ! ( lit( 7 ) . satisfy( & dtype, & session) . is_err( ) ) ;
231+ }
192232}
0 commit comments