@@ -43,6 +43,7 @@ use vortex_array::stats::StatsSet;
4343use vortex_array:: stream:: ArrayStreamAdapter ;
4444use vortex_array:: stream:: ArrayStreamExt ;
4545use vortex_array:: stream:: SendableArrayStream ;
46+ use vortex_error:: SharedVortexResult ;
4647use vortex_error:: VortexResult ;
4748use vortex_error:: vortex_bail;
4849use vortex_error:: vortex_err;
@@ -326,7 +327,7 @@ impl DataSource for MultiLayoutDataSource {
326327#[ derive( Clone ) ]
327328struct BoundScanRequest {
328329 projection : BoundExpression ,
329- filter : Option < BoundExpression > ,
330+ filter : SharedVortexResult < Option < BoundExpression > > ,
330331 row_range : Option < Range < u64 > > ,
331332 selection : Selection ,
332333 partition_selection : Selection ,
@@ -352,7 +353,8 @@ impl BoundScanRequest {
352353 projection : optimize_and_bind ( projection, dtype) ?,
353354 filter : filter
354355 . map ( |expr| optimize_and_bind ( expr, dtype) )
355- . transpose ( ) ?,
356+ . transpose ( )
357+ . map_err ( Arc :: new) ,
356358 row_range,
357359 selection,
358360 partition_selection,
@@ -503,7 +505,7 @@ fn reader_partition(
503505
504506 // Check file-level pruning: if the filter can be proven false for the entire row range
505507 // using file-level statistics, skip this reader entirely.
506- if let Some ( filter) = & request. filter {
508+ if let Ok ( Some ( filter) ) = & request. filter {
507509 let mask_len = usize:: try_from ( row_range. end - row_range. start ) . unwrap_or ( usize:: MAX ) ;
508510 let mask = Mask :: new_true ( mask_len) ;
509511 if let Ok ( pruning_future) = reader. pruning_evaluation ( & row_range, filter, mask)
@@ -559,7 +561,11 @@ impl Partition for MultiLayoutPartition {
559561 . limit
560562 . map_or ( row_count, |limit| row_count. min ( limit) ) ;
561563
562- if self . request . filter . is_some ( ) {
564+ let has_filter = match & self . request . filter {
565+ Ok ( filter) => filter. is_some ( ) ,
566+ Err ( _) => true ,
567+ } ;
568+ if has_filter {
563569 Precision :: inexact ( row_count)
564570 } else {
565571 Precision :: exact ( row_count)
@@ -572,10 +578,11 @@ impl Partition for MultiLayoutPartition {
572578
573579 fn execute ( self : Box < Self > ) -> VortexResult < SendableArrayStream > {
574580 let request = self . request ;
581+ let filter = request. filter ?;
575582 let mut builder = ScanBuilder :: new ( self . session , self . reader )
576583 . with_selection ( request. selection )
577584 . with_projection ( request. projection )
578- . with_some_filter ( request . filter )
585+ . with_some_filter ( filter)
579586 . with_some_limit ( request. limit )
580587 . with_ordered ( request. ordered ) ;
581588
@@ -596,6 +603,10 @@ impl Partition for MultiLayoutPartition {
596603mod tests {
597604 use rstest:: rstest;
598605 use vortex_array:: dtype:: Nullability ;
606+ use vortex_array:: dtype:: PType ;
607+ use vortex_array:: expr:: eq;
608+ use vortex_array:: expr:: lit;
609+ use vortex_array:: expr:: root;
599610
600611 use super :: * ;
601612 use crate :: scan:: test:: new_session;
@@ -630,4 +641,19 @@ mod tests {
630641 fn byte_size_precision ( #[ case] sizes : Vec < Option < u64 > > , #[ case] expected : Precision < u64 > ) {
631642 assert_eq ! ( deferred_source( sizes) . byte_size( ) , expected) ;
632643 }
644+
645+ #[ test]
646+ fn filter_binding_errors_are_deferred ( ) -> VortexResult < ( ) > {
647+ let dtype = DType :: Primitive ( PType :: U8 , Nullability :: NonNullable ) ;
648+ let request = ScanRequest {
649+ filter : Some ( eq ( root ( ) , lit ( 67_i32 ) ) ) ,
650+ ..ScanRequest :: default ( )
651+ } ;
652+
653+ let request = BoundScanRequest :: try_new ( request, & dtype) ?;
654+
655+ assert_eq ! ( request. projection. dtype( ) , & dtype) ;
656+ assert ! ( request. filter. is_err( ) ) ;
657+ Ok ( ( ) )
658+ }
633659}
0 commit comments