IsTypeCompatible checks whether type target is compatible with type src they're compatible if - same null/not null and unsigned flag(maybe we can allow src not null flag, target null flag later) - have same evaluation type - target's flen and decimal should be bigger or equals to src's - elements in
(src types.FieldType, target types.FieldType)
| 65 | // - elements in target is superset of elements in src if they're enum or set type |
| 66 | // - same charset and collate if they're string types |
| 67 | func IsTypeCompatible(src types.FieldType, target types.FieldType) (typeEq, collateEq bool) { |
| 68 | collateEq = src.GetCollate() == target.GetCollate() |
| 69 | if mysql.HasNotNullFlag(src.GetFlag()) != mysql.HasNotNullFlag(target.GetFlag()) { |
| 70 | return false, collateEq |
| 71 | } |
| 72 | if mysql.HasUnsignedFlag(src.GetFlag()) != mysql.HasUnsignedFlag(target.GetFlag()) { |
| 73 | return false, collateEq |
| 74 | } |
| 75 | srcEType, dstEType := src.EvalType(), target.EvalType() |
| 76 | if srcEType != dstEType { |
| 77 | return false, collateEq |
| 78 | } |
| 79 | |
| 80 | getFLenAndDecimal := func(tp types.FieldType) (int, int) { |
| 81 | // ref FieldType.CompactStr |
| 82 | defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(tp.GetType()) |
| 83 | flen, decimal := tp.GetFlen(), tp.GetDecimal() |
| 84 | if flen == types.UnspecifiedLength { |
| 85 | flen = defaultFlen |
| 86 | } |
| 87 | if decimal == types.UnspecifiedLength { |
| 88 | decimal = defaultDecimal |
| 89 | } |
| 90 | return flen, decimal |
| 91 | } |
| 92 | srcFLen, srcDecimal := getFLenAndDecimal(src) |
| 93 | targetFLen, targetDecimal := getFLenAndDecimal(target) |
| 94 | if srcFLen > targetFLen || srcDecimal > targetDecimal { |
| 95 | return false, collateEq |
| 96 | } |
| 97 | |
| 98 | // if they're not enum or set type, elems will be empty |
| 99 | // and if they're not string types, charset and collate will be empty, |
| 100 | // so we check them anyway. |
| 101 | srcElems := src.GetElems() |
| 102 | targetElems := target.GetElems() |
| 103 | if len(srcElems) > len(targetElems) { |
| 104 | return false, collateEq |
| 105 | } |
| 106 | targetElemSet := make(map[string]struct{}) |
| 107 | for _, item := range targetElems { |
| 108 | targetElemSet[item] = struct{}{} |
| 109 | } |
| 110 | for _, item := range srcElems { |
| 111 | if _, ok := targetElemSet[item]; !ok { |
| 112 | return false, collateEq |
| 113 | } |
| 114 | } |
| 115 | return src.GetCharset() == target.GetCharset(), collateEq |
| 116 | } |
| 117 | |
| 118 | func GRPCConn(ctx context.Context, storeAddr string, tlsConf *tls.Config, opts ...grpc.DialOption) (*grpc.ClientConn, error) { |
| 119 | secureOpt := grpc.WithTransportCredentials(insecure.NewCredentials()) |