@@ -326,7 +326,8 @@ fn ensure_field_compatibility(
326326 if !DFSchema :: datatype_is_logically_equal (
327327 datafusion_field. data_type ( ) ,
328328 substrait_field. data_type ( ) ,
329- ) {
329+ ) && !is_safe_widening ( datafusion_field. data_type ( ) , substrait_field. data_type ( ) )
330+ {
330331 return substrait_err ! (
331332 "Field '{}' in Substrait schema has a different type ({}) than the corresponding field in the table schema ({})." ,
332333 substrait_field. name( ) ,
@@ -348,6 +349,25 @@ fn ensure_field_compatibility(
348349 Ok ( ( ) )
349350}
350351
352+ /// Ensures that the given datafusion type can safely promoted to
353+ /// Substrait type, declared in the plan, without loss of precision.
354+ fn is_safe_widening ( datafusion_type : & DataType , substrait_type : & DataType ) -> bool {
355+ matches ! (
356+ ( datafusion_type, substrait_type) ,
357+ // Signed integer widening
358+ ( DataType :: Int8 , DataType :: Int16 | DataType :: Int32 | DataType :: Int64 )
359+ | ( DataType :: Int16 , DataType :: Int32 | DataType :: Int64 )
360+ | ( DataType :: Int32 , DataType :: Int64 )
361+ // Unsigned integer widening
362+ | ( DataType :: UInt8 , DataType :: UInt16 | DataType :: UInt32 | DataType :: UInt64 )
363+ | ( DataType :: UInt16 , DataType :: UInt32 | DataType :: UInt64 )
364+ | ( DataType :: UInt32 , DataType :: UInt64 )
365+ // Float widening
366+ | ( DataType :: Float16 , DataType :: Float32 | DataType :: Float64 )
367+ | ( DataType :: Float32 , DataType :: Float64 )
368+ )
369+ }
370+
351371/// Returns true if the DataFusion and Substrait nullabilities are compatible, false otherwise
352372fn compatible_nullabilities (
353373 datafusion_nullability : bool ,
0 commit comments