@@ -733,6 +733,7 @@ pub fn comparison_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option<D
733733 . or_else ( || string_temporal_coercion ( lhs_type, rhs_type) )
734734 . or_else ( || binary_coercion ( lhs_type, rhs_type) )
735735 . or_else ( || struct_coercion ( lhs_type, rhs_type) )
736+ . or_else ( || map_coercion ( lhs_type, rhs_type) )
736737}
737738
738739/// Similar to [`comparison_coercion`] but prefers numeric if compares with
@@ -987,6 +988,25 @@ fn coerce_fields(common_type: DataType, lhs: &FieldRef, rhs: &FieldRef) -> Field
987988 Arc :: new ( Field :: new ( name, common_type, is_nullable) )
988989}
989990
991+ /// coerce two types if they are Maps by coercing their inner 'entries' fields' types
992+ /// using struct coercion
993+ fn map_coercion ( lhs_type : & DataType , rhs_type : & DataType ) -> Option < DataType > {
994+ use arrow:: datatypes:: DataType :: * ;
995+ match ( lhs_type, rhs_type) {
996+ ( Map ( lhs_field, lhs_ordered) , Map ( rhs_field, rhs_ordered) ) => {
997+ struct_coercion ( lhs_field. data_type ( ) , rhs_field. data_type ( ) ) . map (
998+ |key_value_type| {
999+ Map (
1000+ Arc :: new ( ( * * lhs_field) . clone ( ) . with_data_type ( key_value_type) ) ,
1001+ * lhs_ordered && * rhs_ordered,
1002+ )
1003+ } ,
1004+ )
1005+ }
1006+ _ => None ,
1007+ }
1008+ }
1009+
9901010/// Returns the output type of applying mathematics operations such as
9911011/// `+` to arguments of `lhs_type` and `rhs_type`.
9921012fn mathematics_numerical_coercion (
@@ -2483,4 +2503,49 @@ mod tests {
24832503 ) ;
24842504 Ok ( ( ) )
24852505 }
2506+
2507+ #[ test]
2508+ fn test_map_coercion ( ) -> Result < ( ) > {
2509+ let lhs = Field :: new_map (
2510+ "lhs" ,
2511+ "entries" ,
2512+ Arc :: new ( Field :: new ( "keys" , DataType :: Utf8 , false ) ) ,
2513+ Arc :: new ( Field :: new ( "values" , DataType :: LargeUtf8 , false ) ) ,
2514+ true ,
2515+ false ,
2516+ ) ;
2517+ let rhs = Field :: new_map (
2518+ "rhs" ,
2519+ "kvp" ,
2520+ Arc :: new ( Field :: new ( "k" , DataType :: Utf8 , false ) ) ,
2521+ Arc :: new ( Field :: new ( "v" , DataType :: Utf8 , true ) ) ,
2522+ false ,
2523+ true ,
2524+ ) ;
2525+
2526+ let expected = Field :: new_map (
2527+ "expected" ,
2528+ "entries" , // struct coercion takes lhs name
2529+ Arc :: new ( Field :: new (
2530+ "keys" , // struct coercion takes lhs name
2531+ DataType :: Utf8 ,
2532+ false ,
2533+ ) ) ,
2534+ Arc :: new ( Field :: new (
2535+ "values" , // struct coercion takes lhs name
2536+ DataType :: LargeUtf8 , // lhs is large string
2537+ true , // rhs is nullable
2538+ ) ) ,
2539+ false , // both sides must be sorted
2540+ true , // rhs is nullable
2541+ ) ;
2542+
2543+ test_coercion_binary_rule ! (
2544+ lhs. data_type( ) ,
2545+ rhs. data_type( ) ,
2546+ Operator :: Eq ,
2547+ expected. data_type( ) . clone( )
2548+ ) ;
2549+ Ok ( ( ) )
2550+ }
24862551}
0 commit comments