@@ -141,8 +141,8 @@ impl DeleteFilter {
141141 return Ok ( None ) ;
142142 }
143143
144- // TODO: handle case-insensitive case
145- let bound_predicate = combined_predicate . bind ( file_scan_task. schema . clone ( ) , false ) ?;
144+ let bound_predicate = combined_predicate
145+ . bind ( file_scan_task. schema . clone ( ) , file_scan_task . case_sensitive ) ?;
146146 Ok ( Some ( bound_predicate) )
147147 }
148148
@@ -211,8 +211,9 @@ pub(crate) mod tests {
211211
212212 use super :: * ;
213213 use crate :: arrow:: caching_delete_file_loader:: CachingDeleteFileLoader ;
214+ use crate :: expr:: Reference ;
214215 use crate :: io:: FileIO ;
215- use crate :: spec:: { DataFileFormat , Schema } ;
216+ use crate :: spec:: { DataFileFormat , Datum , NestedField , PrimitiveType , Schema , Type } ;
216217
217218 type ArrowSchemaRef = Arc < ArrowSchema > ;
218219
@@ -344,6 +345,7 @@ pub(crate) mod tests {
344345 partition: None ,
345346 partition_spec: None ,
346347 name_mapping: None ,
348+ case_sensitive: false ,
347349 } ,
348350 FileScanTask {
349351 start: 0 ,
@@ -358,6 +360,7 @@ pub(crate) mod tests {
358360 partition: None ,
359361 partition_spec: None ,
360362 name_mapping: None ,
363+ case_sensitive: false ,
361364 } ,
362365 ] ;
363366
@@ -380,4 +383,57 @@ pub(crate) mod tests {
380383 ] ;
381384 Arc :: new ( arrow_schema:: Schema :: new ( fields) )
382385 }
386+
387+ #[ tokio:: test]
388+ async fn test_build_equality_delete_predicate_case_sensitive ( ) {
389+ let schema = Arc :: new (
390+ Schema :: builder ( )
391+ . with_schema_id ( 1 )
392+ . with_fields ( vec ! [
393+ NestedField :: required( 1 , "Id" , Type :: Primitive ( PrimitiveType :: Long ) ) . into( ) ,
394+ ] )
395+ . build ( )
396+ . unwrap ( ) ,
397+ ) ;
398+
399+ // ---------- fake FileScanTask ----------
400+ let task = FileScanTask {
401+ start : 0 ,
402+ length : 0 ,
403+ record_count : None ,
404+ data_file_path : "data.parquet" . to_string ( ) ,
405+ data_file_format : crate :: spec:: DataFileFormat :: Parquet ,
406+ schema : schema. clone ( ) ,
407+ project_field_ids : vec ! [ ] ,
408+ predicate : None ,
409+ deletes : vec ! [ FileScanTaskDeleteFile {
410+ file_path: "eq-del.parquet" . to_string( ) ,
411+ file_type: DataContentType :: EqualityDeletes ,
412+ partition_spec_id: 0 ,
413+ equality_ids: None ,
414+ } ] ,
415+ partition : None ,
416+ partition_spec : None ,
417+ name_mapping : None ,
418+ case_sensitive : true ,
419+ } ;
420+
421+ let filter = DeleteFilter :: default ( ) ;
422+
423+ // ---------- insert equality delete predicate ----------
424+ let pred = Reference :: new ( "id" ) . equal_to ( Datum :: long ( 10 ) ) ;
425+
426+ let ( tx, rx) = tokio:: sync:: oneshot:: channel ( ) ;
427+ filter. insert_equality_delete ( "eq-del.parquet" , rx) ;
428+
429+ tx. send ( pred) . unwrap ( ) ;
430+
431+ // ---------- should FAIL ----------
432+ let result = filter. build_equality_delete_predicate ( & task) . await ;
433+
434+ assert ! (
435+ result. is_err( ) ,
436+ "case_sensitive=true should fail when column case mismatches"
437+ ) ;
438+ }
383439}
0 commit comments