@@ -1348,26 +1348,56 @@ fn build_is_null_column_expr(
1348
1348
/// The maximum number of entries in an `InList` that might be rewritten into
1349
1349
/// an OR chain
1350
1350
const MAX_LIST_VALUE_SIZE_REWRITE : usize = 20 ;
1351
+ /// Rewrite a predicate expression to a pruning predicate expression.
1352
+ /// See documentation for `PruningPredicate` for more information.
1353
+ pub struct PredicateRewriter {
1354
+ unhandled_hook : Arc < dyn UnhandledPredicateHook > ,
1355
+ }
1351
1356
1352
- /// Translate logical filter expression into pruning predicate
1353
- /// expression that will evaluate to FALSE if it can be determined no
1354
- /// rows between the min/max values could pass the predicates.
1355
- ///
1356
- /// Any predicates that can not be translated will be passed to `unhandled_hook`.
1357
- ///
1358
- /// Returns the pruning predicate as an [`PhysicalExpr`]
1359
- ///
1360
- /// Notice: Does not handle [`phys_expr::InListExpr`] greater than 20, which will fall back to calling `unhandled_hook`
1361
- pub fn rewrite_predicate_to_statistics_predicate (
1362
- expr : & Arc < dyn PhysicalExpr > ,
1363
- schema : & Schema ,
1364
- unhandled_hook : Option < Arc < dyn UnhandledPredicateHook > > ,
1365
- ) -> Arc < dyn PhysicalExpr > {
1366
- let unhandled_hook = unhandled_hook. unwrap_or ( default_unhandled_hook ( ) ) ;
1357
+ impl Default for PredicateRewriter {
1358
+ fn default ( ) -> Self {
1359
+ Self {
1360
+ unhandled_hook : default_unhandled_hook ( ) ,
1361
+ }
1362
+ }
1363
+ }
1367
1364
1368
- let mut required_columns = RequiredColumns :: new ( ) ;
1365
+ impl PredicateRewriter {
1366
+ /// Create a new `PredicateRewriter`
1367
+ pub fn new ( ) -> Self {
1368
+ Self :: default ( )
1369
+ }
1370
+
1371
+ /// Set the unhandled hook to be used when a predicate can not be rewritten
1372
+ pub fn with_unhandled_hook (
1373
+ self ,
1374
+ unhandled_hook : Arc < dyn UnhandledPredicateHook > ,
1375
+ ) -> Self {
1376
+ Self { unhandled_hook }
1377
+ }
1369
1378
1370
- build_predicate_expression ( expr, schema, & mut required_columns, & unhandled_hook)
1379
+ /// Translate logical filter expression into pruning predicate
1380
+ /// expression that will evaluate to FALSE if it can be determined no
1381
+ /// rows between the min/max values could pass the predicates.
1382
+ ///
1383
+ /// Any predicates that can not be translated will be passed to `unhandled_hook`.
1384
+ ///
1385
+ /// Returns the pruning predicate as an [`PhysicalExpr`]
1386
+ ///
1387
+ /// Notice: Does not handle [`phys_expr::InListExpr`] greater than 20, which will fall back to calling `unhandled_hook`
1388
+ pub fn rewrite_predicate_to_statistics_predicate (
1389
+ & self ,
1390
+ expr : & Arc < dyn PhysicalExpr > ,
1391
+ schema : & Schema ,
1392
+ ) -> Arc < dyn PhysicalExpr > {
1393
+ let mut required_columns = RequiredColumns :: new ( ) ;
1394
+ build_predicate_expression (
1395
+ expr,
1396
+ schema,
1397
+ & mut required_columns,
1398
+ & self . unhandled_hook ,
1399
+ )
1400
+ }
1371
1401
}
1372
1402
1373
1403
/// Translate logical filter expression into pruning predicate
@@ -3481,25 +3511,24 @@ mod tests {
3481
3511
Field :: new( "b" , DataType :: Int32 , true ) ,
3482
3512
] ) ;
3483
3513
3514
+ let rewriter = PredicateRewriter :: new ( )
3515
+ . with_unhandled_hook ( Arc :: new ( CustomUnhandledHook { } ) ) ;
3516
+
3484
3517
let transform_expr = |expr| {
3485
3518
let expr = logical2physical ( & expr, & schema_with_b) ;
3486
- rewrite_predicate_to_statistics_predicate (
3487
- & expr,
3488
- & schema,
3489
- Some ( Arc :: new ( CustomUnhandledHook { } ) ) ,
3490
- )
3519
+ rewriter. rewrite_predicate_to_statistics_predicate ( & expr, & schema)
3491
3520
} ;
3492
3521
3493
3522
// transform an arbitrary valid expression that we know is handled
3494
- let known_expression = col ( "a" ) . eq ( lit ( ScalarValue :: Int32 ( Some ( 12 ) ) ) ) ;
3495
- let known_expression_transformed = rewrite_predicate_to_statistics_predicate (
3496
- & logical2physical ( & known_expression , & schema ) ,
3497
- & schema,
3498
- None ,
3499
- ) ;
3523
+ let known_expression = col ( "a" ) . eq ( lit ( 12 ) ) ;
3524
+ let known_expression_transformed = PredicateRewriter :: new ( )
3525
+ . rewrite_predicate_to_statistics_predicate (
3526
+ & logical2physical ( & known_expression , & schema) ,
3527
+ & schema ,
3528
+ ) ;
3500
3529
3501
3530
// an expression referencing an unknown column (that is not in the schema) gets passed to the hook
3502
- let input = col ( "b" ) . eq ( lit ( ScalarValue :: Int32 ( Some ( 12 ) ) ) ) ;
3531
+ let input = col ( "b" ) . eq ( lit ( 12 ) ) ;
3503
3532
let expected = logical2physical ( & lit ( 42 ) , & schema) ;
3504
3533
let transformed = transform_expr ( input. clone ( ) ) ;
3505
3534
assert_eq ! ( transformed. to_string( ) , expected. to_string( ) ) ;
0 commit comments