@@ -43,7 +43,7 @@ use arrow::compute::kernels::cmp::eq;
4343use arrow:: compute:: kernels:: length:: length;
4444use arrow:: compute:: { SortColumn , SortOptions , nullif, partition} ;
4545use arrow:: datatypes:: {
46- ArrowNativeType , DataType , Field , Int32Type , Int64Type , SchemaRef ,
46+ ArrowNativeType , DataType , Field , Int32Type , Int64Type , Metadata , SchemaRef ,
4747} ;
4848#[ cfg( feature = "sql" ) ]
4949use sqlparser:: { ast:: Ident , dialect:: GenericDialect , parser:: Parser } ;
@@ -559,6 +559,7 @@ pub struct SingleRowListArrayBuilder {
559559 /// Specify the field name for the resulting array. Defaults to value used in
560560 /// [`Field::new_list_field`]
561561 field_name : Option < String > ,
562+ field_metadata : Metadata ,
562563}
563564
564565impl SingleRowListArrayBuilder {
@@ -568,6 +569,7 @@ impl SingleRowListArrayBuilder {
568569 arr,
569570 nullable : true ,
570571 field_name : None ,
572+ field_metadata : Metadata :: default ( ) ,
571573 }
572574 }
573575
@@ -583,10 +585,12 @@ impl SingleRowListArrayBuilder {
583585 self
584586 }
585587
586- /// Copies field name and nullable from the specified field
587- pub fn with_field ( self , field : & Field ) -> Self {
588- self . with_field_name ( Some ( field. name ( ) . to_owned ( ) ) )
589- . with_nullable ( field. is_nullable ( ) )
588+ /// Copies field name, nullability, and metadata from the specified field
589+ pub fn with_field ( mut self , field : & Field ) -> Self {
590+ self . field_name = Some ( field. name ( ) . to_owned ( ) ) ;
591+ self . nullable = field. is_nullable ( ) ;
592+ self . field_metadata = field. metadata ( ) . clone ( ) ;
593+ self
590594 }
591595
592596 /// Build a single element [`ListArray`]
@@ -659,13 +663,14 @@ impl SingleRowListArrayBuilder {
659663 arr,
660664 nullable,
661665 field_name,
666+ field_metadata,
662667 } = self ;
663668 let data_type = arr. data_type ( ) . to_owned ( ) ;
664669 let field = match field_name {
665670 Some ( name) => Field :: new ( name, data_type, nullable) ,
666671 None => Field :: new_list_field ( data_type, nullable) ,
667672 } ;
668- ( Arc :: new ( field) , arr)
673+ ( Arc :: new ( field. with_metadata ( field_metadata ) ) , arr)
669674 }
670675}
671676
@@ -1606,6 +1611,7 @@ pub fn apply_parent_nulls(
16061611
16071612#[ cfg( test) ]
16081613mod tests {
1614+ use std:: collections:: HashMap ;
16091615 use std:: sync:: Arc ;
16101616
16111617 use super :: * ;
@@ -1617,6 +1623,20 @@ mod tests {
16171623 #[ cfg( feature = "sql" ) ]
16181624 use sqlparser:: ast:: Ident ;
16191625
1626+ #[ test]
1627+ fn test_list_scalar_cast_preserves_target_element_metadata ( ) -> Result < ( ) > {
1628+ let input =
1629+ ListArray :: from_iter_primitive :: < Int32Type , _ , _ > ( vec ! [ Some ( vec![ Some ( 1 ) ] ) ] ) ;
1630+ let item = Field :: new ( "item" , DataType :: Int32 , true )
1631+ . with_metadata ( HashMap :: from ( [ ( "PARQUET:field_id" . into ( ) , "2" . into ( ) ) ] ) ) ;
1632+ let target = DataType :: List ( Arc :: new ( item) ) ;
1633+
1634+ let casted = ScalarValue :: List ( Arc :: new ( input) ) . cast_to ( & target) ?;
1635+ assert_eq ! ( casted. data_type( ) , target) ;
1636+ assert_eq ! ( casted. to_array_of_size( 2 ) ?. data_type( ) , & target) ;
1637+ Ok ( ( ) )
1638+ }
1639+
16201640 #[ test]
16211641 fn test_apply_parent_nulls_sliced ( ) -> Result < ( ) > {
16221642 let child = Arc :: new (
0 commit comments