FindCommonType returns the common type that given types can convert to. Returns false if no implicit casts are needed to resolve the given types as the returned common type. https://www.postgresql.org/docs/15/typeconv-union-case.html
(ctx *sql.Context, types []*pgtypes.DoltgresType)
| 27 | // to resolve the given types as the returned common type. |
| 28 | // https://www.postgresql.org/docs/15/typeconv-union-case.html |
| 29 | func FindCommonType(ctx *sql.Context, types []*pgtypes.DoltgresType) (_ *pgtypes.DoltgresType, requiresCasts bool, err error) { |
| 30 | candidateType := pgtypes.Unknown |
| 31 | differentTypes := false |
| 32 | for _, typ := range types { |
| 33 | if typ.ID == candidateType.ID { |
| 34 | continue |
| 35 | } else if candidateType.ID == pgtypes.Unknown.ID { |
| 36 | candidateType = typ |
| 37 | } else { |
| 38 | candidateType = pgtypes.Unknown |
| 39 | differentTypes = true |
| 40 | } |
| 41 | } |
| 42 | if !differentTypes { |
| 43 | if candidateType.ID == pgtypes.Unknown.ID { |
| 44 | // We require implicit casts from `unknown` to `text` |
| 45 | return pgtypes.Text, true, nil |
| 46 | } |
| 47 | return candidateType, false, nil |
| 48 | } |
| 49 | // We have different types if we've made it this far, so we're guaranteed to require implicit casts |
| 50 | requiresCasts = true |
| 51 | for _, typ := range types { |
| 52 | if candidateType.ID == pgtypes.Unknown.ID { |
| 53 | candidateType = typ |
| 54 | } |
| 55 | if typ.ID != pgtypes.Unknown.ID && candidateType.TypCategory != typ.TypCategory { |
| 56 | return nil, false, errors.Errorf("types %s and %s cannot be matched", candidateType.String(), typ.String()) |
| 57 | } |
| 58 | } |
| 59 | castsColl, err := core.GetCastsCollectionFromContext(ctx, "") |
| 60 | if err != nil { |
| 61 | return nil, false, err |
| 62 | } |
| 63 | // Attempt to find the most general type (or the preferred type in the type category) |
| 64 | for _, typ := range types { |
| 65 | if typ.ID == pgtypes.Unknown.ID || typ.ID == candidateType.ID { |
| 66 | continue |
| 67 | } else if cast, err := castsColl.GetImplicitCast(ctx, typ, candidateType); err != nil || cast.ID.IsValid() { |
| 68 | if err != nil { |
| 69 | return nil, false, err |
| 70 | } |
| 71 | // typ can convert to the candidate type, so the candidate type is at least as general |
| 72 | continue |
| 73 | } else if cast, err = castsColl.GetImplicitCast(ctx, candidateType, typ); err != nil || cast.ID.IsValid() { |
| 74 | if err != nil { |
| 75 | return nil, false, err |
| 76 | } |
| 77 | // the candidate type can convert to typ, but not vice versa, so typ is likely more general |
| 78 | candidateType = typ |
| 79 | if candidateType.IsPreferred { |
| 80 | // We stop considering more types once we've found a preferred type |
| 81 | break |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | // Verify that all types have an implicit conversion to the candidate type |
| 86 | for _, typ := range types { |
no test coverage detected