in table/arrow_utils.go [963:1029]
func (sc *schemaCompatVisitor) isFieldCompat(lhs iceberg.NestedField) bool {
rhs, ok := sc.provided.FindFieldByID(lhs.ID)
if !ok {
if lhs.Required {
sc.errorData = append(sc.errorData,
[]string{"❌", lhs.String(), "missing"})
return false
}
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), "missing"})
return true
}
if lhs.Required && !rhs.Required {
sc.errorData = append(sc.errorData,
[]string{"❌", lhs.String(), rhs.String()})
return false
}
if lhs.Type.Equals(rhs.Type) {
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), rhs.String()})
return true
}
// we only check that parent node is also of the same type
// we check the type of the child nodes as we traverse them later
switch lhs.Type.(type) {
case *iceberg.StructType:
if rhs, ok := rhs.Type.(*iceberg.StructType); ok {
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), rhs.String()})
return true
}
case *iceberg.ListType:
if rhs, ok := rhs.Type.(*iceberg.ListType); ok {
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), rhs.String()})
return true
}
case *iceberg.MapType:
if rhs, ok := rhs.Type.(*iceberg.MapType); ok {
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), rhs.String()})
return true
}
}
if _, err := iceberg.PromoteType(rhs.Type, lhs.Type); err != nil {
sc.errorData = append(sc.errorData,
[]string{"❌", lhs.String(), rhs.String()})
return false
}
sc.errorData = append(sc.errorData,
[]string{"✅", lhs.String(), rhs.String()})
return true
}