@@ -865,4 +865,37 @@ mod tests {
865865 validate_struct_compatibility ( & phys_kv_fields, & log_kv_fields)
866866 . expect ( "Map value-struct evolution (additive) should be compatible" ) ;
867867 }
868+
869+ /// Validates that incompatible MAP value-struct changes are rejected.
870+ /// A type change on an existing field (Binary → Int32) must fail — this
871+ /// exercises the new (Map, Map) code path and confirms errors surface there,
872+ /// not silently through the fallback cast.
873+ #[ test]
874+ fn test_validate_map_value_struct_incompatibility ( ) {
875+ // Physical: Map(value: Struct({id: Binary}))
876+ // Logical: Map(value: Struct({id: Int32})) — type change, not additive
877+ let phys_kv_fields: Vec < Arc < Field > > = vec ! [
878+ Arc :: new( non_null_field( "key" , DataType :: Utf8 ) ) ,
879+ Arc :: new( field(
880+ "value" ,
881+ Struct ( vec![ Arc :: new( field( "id" , DataType :: Binary ) ) ] . into( ) ) ,
882+ ) ) ,
883+ ] ;
884+ let log_kv_fields: Vec < Arc < Field > > = vec ! [
885+ Arc :: new( non_null_field( "key" , DataType :: Utf8 ) ) ,
886+ Arc :: new( field(
887+ "value" ,
888+ Struct ( vec![ Arc :: new( field( "id" , DataType :: Int32 ) ) ] . into( ) ) ,
889+ ) ) ,
890+ ] ;
891+
892+ // Binary → Int32 is incompatible: must fail via the Map code path.
893+ let result = validate_struct_compatibility ( & phys_kv_fields, & log_kv_fields) ;
894+ assert ! ( result. is_err( ) ) ;
895+ let error_msg = result. unwrap_err ( ) . to_string ( ) ;
896+ assert ! (
897+ error_msg. contains( "id" ) ,
898+ "error should name the incompatible field"
899+ ) ;
900+ }
868901}
0 commit comments