@@ -44,6 +44,7 @@ use iceberg_rust::{
4444 } ,
4545 table:: ManifestPath ,
4646} ;
47+ use rust_decimal:: Decimal ;
4748
4849pub ( crate ) struct PruneManifests < ' table , ' manifests > {
4950 partition_fields : & ' table [ BoundPartitionField < ' table > ] ,
@@ -254,6 +255,9 @@ fn any_iter_to_array(
254255 DataType :: Float64 => ScalarValue :: iter_to_array ( iter. map ( |opt| {
255256 ScalarValue :: Float64 ( opt. and_then ( |value| Some ( * value. downcast :: < f64 > ( ) . ok ( ) ?) ) )
256257 } ) ) ,
258+ DataType :: Date32 => ScalarValue :: iter_to_array ( iter. map ( |opt| {
259+ ScalarValue :: Date32 ( opt. and_then ( |value| Some ( * value. downcast :: < i32 > ( ) . ok ( ) ?) ) )
260+ } ) ) ,
257261 DataType :: Date64 => ScalarValue :: iter_to_array ( iter. map ( |opt| {
258262 ScalarValue :: Date64 ( opt. and_then ( |value| Some ( * value. downcast :: < i64 > ( ) . ok ( ) ?) ) )
259263 } ) ) ,
@@ -280,6 +284,20 @@ fn any_iter_to_array(
280284 DataType :: Binary => ScalarValue :: iter_to_array ( iter. map ( |opt| {
281285 ScalarValue :: Binary ( opt. and_then ( |value| Some ( * value. downcast :: < Vec < u8 > > ( ) . ok ( ) ?) ) )
282286 } ) ) ,
287+ // Only prune when the stored scale matches the column's scale.
288+ DataType :: Decimal128 ( precision, scale) => {
289+ let ( precision, scale) = ( * precision, * scale) ;
290+ ScalarValue :: iter_to_array ( iter. map ( move |opt| {
291+ ScalarValue :: Decimal128 (
292+ opt. and_then ( |value| {
293+ let d = * value. downcast :: < Decimal > ( ) . ok ( ) ?;
294+ ( d. scale ( ) == scale as u32 ) . then ( || d. mantissa ( ) )
295+ } ) ,
296+ precision,
297+ scale,
298+ )
299+ } ) )
300+ }
283301 _ => Err ( DataFusionError :: Internal (
284302 "Arrow datatype not supported for pruning." . to_string ( ) ,
285303 ) ) ,
@@ -487,9 +505,12 @@ fn value_to_scalarvalue(value: Value) -> Result<ScalarValue, Error> {
487505#[ cfg( test) ]
488506mod tests {
489507 use super :: * ;
490- use datafusion:: arrow:: array:: { Array , TimestampMicrosecondArray } ;
508+ use datafusion:: arrow:: array:: {
509+ Array , Date32Array , Decimal128Array , TimestampMicrosecondArray ,
510+ } ;
491511 use datafusion:: arrow:: datatypes:: Field ;
492512 use datafusion:: common:: config:: ConfigOptions ;
513+ use rust_decimal:: Decimal ;
493514 use std:: sync:: Arc ;
494515
495516 /// Helper: invoke `DateTransform` directly with a transform name and scalar value.
@@ -718,6 +739,39 @@ mod tests {
718739 assert_eq ! ( result, input) ;
719740 }
720741
742+ #[ test]
743+ fn any_iter_to_array_date32 ( ) {
744+ let iter = vec ! [ Some ( Value :: Date ( 19797 ) . into_any( ) ) , None ] . into_iter ( ) ;
745+ let array = any_iter_to_array ( iter, & DataType :: Date32 ) . unwrap ( ) ;
746+ let dates = array. as_any ( ) . downcast_ref :: < Date32Array > ( ) . unwrap ( ) ;
747+ assert_eq ! ( dates. value( 0 ) , 19797 ) ;
748+ assert ! ( dates. is_null( 1 ) ) ;
749+ }
750+
751+ #[ test]
752+ fn any_iter_to_array_decimal128 ( ) {
753+ let iter = vec ! [
754+ Some ( Value :: Decimal ( Decimal :: new( 12345 , 2 ) ) . into_any( ) ) ,
755+ None ,
756+ ]
757+ . into_iter ( ) ;
758+ let array = any_iter_to_array ( iter, & DataType :: Decimal128 ( 10 , 2 ) ) . unwrap ( ) ;
759+ let dec = array. as_any ( ) . downcast_ref :: < Decimal128Array > ( ) . unwrap ( ) ;
760+ assert_eq ! ( dec. value( 0 ) , 12345 ) ;
761+ assert ! ( dec. is_null( 1 ) ) ;
762+ assert_eq ! ( dec. precision( ) , 10 ) ;
763+ assert_eq ! ( dec. scale( ) , 2 ) ;
764+ }
765+
766+ #[ test]
767+ fn any_iter_to_array_decimal128_scale_mismatch_is_null ( ) {
768+ // Stored scale (2) != column scale (4): emit null rather than misread the mantissa.
769+ let iter = std:: iter:: once ( Some ( Value :: Decimal ( Decimal :: new ( 12345 , 2 ) ) . into_any ( ) ) ) ;
770+ let array = any_iter_to_array ( iter, & DataType :: Decimal128 ( 10 , 4 ) ) . unwrap ( ) ;
771+ let dec = array. as_any ( ) . downcast_ref :: < Decimal128Array > ( ) . unwrap ( ) ;
772+ assert ! ( dec. is_null( 0 ) ) ;
773+ }
774+
721775 #[ test]
722776 fn any_iter_to_array_preserves_timezone ( ) {
723777 for val in [ Value :: Timestamp ( TS_MICROS ) , Value :: TimestampTZ ( TS_MICROS ) ] {
0 commit comments