diff --git a/arrow/src/datatypes/datatype.rs b/arrow/src/datatypes/datatype.rs index a740e8ecc019..f4d0bbe9d4e5 100644 --- a/arrow/src/datatypes/datatype.rs +++ b/arrow/src/datatypes/datatype.rs @@ -669,6 +669,45 @@ impl DataType { ) } + /// Compares the datatype with another for compatibility. + pub fn compatible_datatype(&self, other: &DataType) -> bool { + match (&self, other) { + (DataType::List(a), DataType::List(b)) + | (DataType::LargeList(a), DataType::LargeList(b)) => { + a.is_nullable() == b.is_nullable() + && a.data_type().compatible_datatype(b.data_type()) + } + (DataType::FixedSizeList(a, a_size), DataType::FixedSizeList(b, b_size)) => { + a_size == b_size + && a.is_nullable() == b.is_nullable() + && a.data_type().compatible_datatype(b.data_type()) + } + (DataType::Struct(a), DataType::Struct(b)) => { + a.iter() + .all(|a| match b.iter().find(|f| f.name().eq(a.name())) { + Some(b) => { + a.is_nullable() == b.is_nullable() + && a.data_type().compatible_datatype(b.data_type()) + } + None => a.is_nullable(), + }) + && b.iter() + .all(|b| match a.iter().find(|f| f.name().eq(b.name())) { + Some(a) => { + a.is_nullable() == b.is_nullable() + && a.data_type().compatible_datatype(b.data_type()) + } + None => b.is_nullable(), + }) + } + ( + DataType::Map(a_field, a_is_sorted), + DataType::Map(b_field, b_is_sorted), + ) => a_field == b_field && a_is_sorted == b_is_sorted, + _ => self == other, + } + } + /// Compares the datatype with another, ignoring nested field names /// and metadata. pub(crate) fn equals_datatype(&self, other: &DataType) -> bool {