func (t *Table) unflatten(rec interface{}, col *column.Col) (interface{}, error) { if rec == nil { return nil, nil } switch col.Tp { case mysql.TypeFloat: return float32(rec.(float64)), nil case mysql.TypeDouble: return rec.(float64), nil case mysql.TypeTiny: if mysql.HasUnsignedFlag(col.Flag) { return uint8(rec.(uint64)), nil } return int8(rec.(int64)), nil case mysql.TypeShort, mysql.TypeYear: if mysql.HasUnsignedFlag(col.Flag) { return uint16(rec.(uint64)), nil } return int16(rec.(int64)), nil case mysql.TypeInt24, mysql.TypeLong: if mysql.HasUnsignedFlag(col.Flag) { return uint32(rec.(uint64)), nil } return int32(rec.(int64)), nil case mysql.TypeLonglong: if mysql.HasUnsignedFlag(col.Flag) { return rec.(uint64), nil } return rec.(int64), nil case mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, mysql.TypeVarchar, mysql.TypeString: return rec, nil case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: var t mysql.Time t.Type = col.Tp t.Fsp = col.Decimal err := t.Unmarshal(rec.([]byte)) if err != nil { return nil, errors.Trace(err) } return t, nil case mysql.TypeDuration: return mysql.Duration{Duration: time.Duration(rec.(int64)), Fsp: col.Decimal}, nil case mysql.TypeNewDecimal, mysql.TypeDecimal: return mysql.ParseDecimal(rec.(string)) } log.Error(string(col.Tp), rec, reflect.TypeOf(rec)) return nil, nil }
// String joins the information of FieldType and // returns a string. func (ft *FieldType) String() string { ts := FieldTypeToStr(ft.Tp, ft.Charset) ans := []string{ts} if ft.Flen != UnspecifiedLength { if ft.Decimal == UnspecifiedLength { ans = append(ans, fmt.Sprintf("(%d)", ft.Flen)) } else { ans = append(ans, fmt.Sprintf("(%d, %d)", ft.Flen, ft.Decimal)) } } else if ft.Decimal != UnspecifiedLength { ans = append(ans, fmt.Sprintf("(%d)", ft.Decimal)) } if mysql.HasUnsignedFlag(ft.Flag) { ans = append(ans, "UNSIGNED") } if mysql.HasZerofillFlag(ft.Flag) { ans = append(ans, "ZEROFILL") } if mysql.HasBinaryFlag(ft.Flag) { ans = append(ans, "BINARY") } if ft.Charset != "" && ft.Charset != charset.CharsetBin && (IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp)) { ans = append(ans, fmt.Sprintf("CHARACTER SET %s", ft.Charset)) } if ft.Collate != "" && ft.Collate != charset.CharsetBin && (IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp)) { ans = append(ans, fmt.Sprintf("COLLATE %s", ft.Collate)) } return strings.Join(ans, " ") }
// GetTypeDesc gets the description for column type. func (c *Col) GetTypeDesc() string { var buf bytes.Buffer buf.WriteString(types.FieldTypeToStr(c.Tp, c.Charset)) switch c.Tp { case mysql.TypeSet, mysql.TypeEnum: // Format is ENUM ('e1', 'e2') or SET ('e1', 'e2') // If elem contain ', we will convert ' -> '' elems := make([]string, len(c.Elems)) for i := range elems { elems[i] = strings.Replace(c.Elems[i], "'", "''", -1) } buf.WriteString(fmt.Sprintf("('%s')", strings.Join(elems, "','"))) default: if c.Flen != -1 { if c.Decimal == -1 { buf.WriteString(fmt.Sprintf("(%d)", c.Flen)) } else { buf.WriteString(fmt.Sprintf("(%d,%d)", c.Flen, c.Decimal)) } } } if mysql.HasUnsignedFlag(c.Flag) { buf.WriteString(" UNSIGNED") } return buf.String() }
// GetTypeDesc gets the description for column type. func (c *Col) GetTypeDesc() string { desc := c.FieldType.CompactStr() if mysql.HasUnsignedFlag(c.Flag) { desc += " UNSIGNED" } return desc }
func (c *Col) getTypeStr() string { ans := []string{types.FieldTypeToStr(c.Tp, c.Charset)} if c.Flen != -1 { if c.Decimal == -1 { ans = append(ans, fmt.Sprintf("(%d)", c.Flen)) } else { ans = append(ans, fmt.Sprintf("(%d, %d)", c.Flen, c.Decimal)) } } if mysql.HasUnsignedFlag(c.Flag) { ans = append(ans, "UNSIGNED") } if mysql.HasZerofillFlag(c.Flag) { ans = append(ans, "ZEROFILL") } if mysql.HasBinaryFlag(c.Flag) { ans = append(ans, "BINARY") } if c.Charset != "" && c.Charset != charset.CharsetBin { ans = append(ans, fmt.Sprintf("CHARACTER SET %s", c.Charset)) } if c.Collate != "" { ans = append(ans, fmt.Sprintf("COLLATE %s", c.Collate)) } return strings.Join(ans, " ") }
// String implements the Expression String interface. func (f *FunctionCast) String() string { tpStr := "" if f.Tp.Tp == mysql.TypeLonglong { if mysql.HasUnsignedFlag(f.Tp.Flag) { tpStr = "UNSIGNED" } else { tpStr = "SIGNED" } } else { tpStr = f.Tp.String() } return fmt.Sprintf("CAST(%s AS %s)", f.Expr.String(), tpStr) }
func (c *Col) getTypeDesc() string { ans := []string{types.FieldTypeToStr(c.Tp, c.Charset)} if c.Flen != -1 { if c.Decimal == -1 { ans = append(ans, fmt.Sprintf("(%d)", c.Flen)) } else { ans = append(ans, fmt.Sprintf("(%d, %d)", c.Flen, c.Decimal)) } } if mysql.HasUnsignedFlag(c.Flag) { ans = append(ans, "UNSIGNED") } return strings.Join(ans, " ") }
// String implements the Expression String interface. func (f *FunctionCast) String() string { tpStr := "" if f.Tp.Tp == mysql.TypeLonglong { if mysql.HasUnsignedFlag(f.Tp.Flag) { tpStr = "UNSIGNED" } else { tpStr = "SIGNED" } } else { tpStr = f.Tp.String() } if f.FunctionType == ConvertFunction { return fmt.Sprintf("CONVERT(%s, %s)", f.Expr.String(), tpStr) } else if f.FunctionType == BinaryOperator { return fmt.Sprintf("BINARY %s", f.Expr.String()) } return fmt.Sprintf("CAST(%s AS %s)", f.Expr.String(), tpStr) }
func (c *Col) getTypeDesc() string { ans := []string{types.FieldTypeToStr(c.Tp, c.Charset)} switch c.Tp { case mysql.TypeSet, mysql.TypeEnum: // Format is ENUM ('e1', 'e2') or SET ('e1', 'e2') ans = append(ans, fmt.Sprintf("('%s')", strings.Join(c.Elems, "','"))) default: if c.Flen != -1 { if c.Decimal == -1 { ans = append(ans, fmt.Sprintf("(%d)", c.Flen)) } else { ans = append(ans, fmt.Sprintf("(%d, %d)", c.Flen, c.Decimal)) } } } if mysql.HasUnsignedFlag(c.Flag) { ans = append(ans, "UNSIGNED") } return strings.Join(ans, " ") }
// String joins the information of FieldType and // returns a string. func (ft *FieldType) String() string { ts := FieldTypeToStr(ft.Tp, ft.Charset) ans := []string{ts} switch ft.Tp { case mysql.TypeEnum, mysql.TypeSet: // Format is ENUM ('e1', 'e2') or SET ('e1', 'e2') ans = append(ans, fmt.Sprintf("('%s')", strings.Join(ft.Elems, "','"))) default: if ft.Flen != UnspecifiedLength { if ft.Decimal == UnspecifiedLength { ans = append(ans, fmt.Sprintf("(%d)", ft.Flen)) } else { ans = append(ans, fmt.Sprintf("(%d, %d)", ft.Flen, ft.Decimal)) } } else if ft.Decimal != UnspecifiedLength { ans = append(ans, fmt.Sprintf("(%d)", ft.Decimal)) } } if mysql.HasUnsignedFlag(ft.Flag) { ans = append(ans, "UNSIGNED") } if mysql.HasZerofillFlag(ft.Flag) { ans = append(ans, "ZEROFILL") } if mysql.HasBinaryFlag(ft.Flag) { ans = append(ans, "BINARY") } if ft.Charset != "" && ft.Charset != charset.CharsetBin && (IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp)) { ans = append(ans, fmt.Sprintf("CHARACTER SET %s", ft.Charset)) } if ft.Collate != "" && ft.Collate != charset.CharsetBin && (IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp)) { ans = append(ans, fmt.Sprintf("COLLATE %s", ft.Collate)) } return strings.Join(ans, " ") }
// String joins the information of FieldType and // returns a string. func (ft *FieldType) String() string { strs := []string{ft.CompactStr()} if mysql.HasUnsignedFlag(ft.Flag) { strs = append(strs, "UNSIGNED") } if mysql.HasZerofillFlag(ft.Flag) { strs = append(strs, "ZEROFILL") } if mysql.HasBinaryFlag(ft.Flag) { strs = append(strs, "BINARY") } if IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp) { if ft.Charset != "" && ft.Charset != charset.CharsetBin { strs = append(strs, fmt.Sprintf("CHARACTER SET %s", ft.Charset)) } if ft.Collate != "" && ft.Collate != charset.CharsetBin { strs = append(strs, fmt.Sprintf("COLLATE %s", ft.Collate)) } } return strings.Join(strs, " ") }
func (c *Col) normalizeIntegerFromFloat(v float64) (val int64, errCode int) { if v > 0 { v = math.Floor(v + 0.5) } else { v = math.Ceil(v - 0.5) } if mysql.HasUnsignedFlag(c.Flag) { if v < 0 { errCode = errCodeOverflowLower } else if v > math.MaxUint64 { errCode = errCodeOverflowUpper } } else { if v < math.MinInt64 { errCode = errCodeOverflowLower } else if v > math.MaxInt64 { errCode = errCodeOverflowUpper } } val = int64(v) return }
// Eval implements the Expression Eval interface. func (f *FunctionCast) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) { value, err := f.Expr.Eval(ctx, args) if err != nil { return nil, err } // Casting nil to any type returns null if value == nil { return nil, nil } // TODO: we need a better function convert between any two types according to FieldType. // Not only check Type, but also consider Flen/Decimal/Charset and so on. nv, err := types.Convert(value, f.Tp) if err != nil { return nil, err } if f.Tp.Tp == mysql.TypeString && f.Tp.Charset == charset.CharsetBin { nv = []byte(nv.(string)) } if f.Tp.Flen != types.UnspecifiedLength { switch f.Tp.Tp { case mysql.TypeString: v := nv.(string) if len(v) > int(f.Tp.Flen) { v = v[:f.Tp.Flen] } return v, nil } } if f.Tp.Tp == mysql.TypeLonglong { if mysql.HasUnsignedFlag(f.Tp.Flag) { return uint64(nv.(int64)), nil } } return nv, nil }
// Convert converts the val with type tp. func Convert(val interface{}, target *FieldType) (v interface{}, err error) { tp := target.Tp if val == nil { return nil, nil } switch tp { // TODO: implement mysql types convert when "CAST() AS" syntax are supported. case mysql.TypeFloat: x, err := ToFloat64(val) if err != nil { return invConv(val, tp) } // For float and following double type, we will only truncate it for float(M, D) format. // If no D is set, we will handle it like origin float whether M is set or not. if target.Flen != UnspecifiedLength && target.Decimal != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float32(x), nil case mysql.TypeDouble: x, err := ToFloat64(val) if err != nil { return invConv(val, tp) } if target.Flen != UnspecifiedLength && target.Decimal != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float64(x), nil case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString: x, err := ToString(val) if err != nil { return invConv(val, tp) } // TODO: consider target.Charset/Collate x = truncateStr(x, target.Flen) if target.Charset == charset.CharsetBin { return []byte(x), nil } return x, nil case mysql.TypeDuration: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Duration: return x.RoundFrac(fsp) case mysql.Time: t, err := x.ConvertToDuration() if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseDuration(x, fsp) default: return invConv(val, tp) } case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Time: t, err := x.Convert(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case mysql.Duration: t, err := x.ConvertToTime(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseTime(x, tp, fsp) case int64: return mysql.ParseTimeFromNum(x, tp, fsp) default: return invConv(val, tp) } case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: unsigned := mysql.HasUnsignedFlag(target.Flag) if unsigned { return convertToUint(val, target) } return convertToInt(val, target) case mysql.TypeBit: x, err := convertToUint(val, target) if err != nil { return x, errors.Trace(err) } // check bit boundary, if bit has n width, the boundary is // in [0, (1 << n) - 1] width := target.Flen if width == 0 || width == mysql.UnspecifiedBitWidth { width = mysql.MinBitWidth } maxValue := uint64(1)<<uint64(width) - 1 if x > maxValue { return maxValue, overflow(val, tp) } return mysql.Bit{Value: x, Width: width}, nil case mysql.TypeDecimal, mysql.TypeNewDecimal: x, err := ToDecimal(val) if err != nil { return invConv(val, tp) } if target.Decimal != UnspecifiedLength { x = x.Round(int32(target.Decimal)) } // TODO: check Flen return x, nil case mysql.TypeYear: var ( intVal int64 err error ) switch x := val.(type) { case string: intVal, err = StrToInt(x) case mysql.Time: return int64(x.Year()), nil case mysql.Duration: return int64(time.Now().Year()), nil default: intVal, err = ToInt64(x) } if err != nil { return invConv(val, tp) } y, err := mysql.AdjustYear(int(intVal)) if err != nil { return invConv(val, tp) } return int64(y), nil case mysql.TypeEnum: var ( e mysql.Enum err error ) switch x := val.(type) { case string: e, err = mysql.ParseEnumName(target.Elems, x) case []byte: e, err = mysql.ParseEnumName(target.Elems, string(x)) default: var number uint64 number, err = ToUint64(x) if err != nil { return nil, errors.Trace(err) } e, err = mysql.ParseEnumValue(target.Elems, number) } if err != nil { return invConv(val, tp) } return e, nil case mysql.TypeSet: var ( s mysql.Set err error ) switch x := val.(type) { case string: s, err = mysql.ParseSetName(target.Elems, x) case []byte: s, err = mysql.ParseSetName(target.Elems, string(x)) default: var number uint64 number, err = ToUint64(x) if err != nil { return nil, errors.Trace(err) } s, err = mysql.ParseSetValue(target.Elems, number) } if err != nil { return invConv(val, tp) } return s, nil default: panic("should never happen") } }
// Convert converts the val with type tp. func Convert(val interface{}, target *FieldType) (v interface{}, err error) { //NTYPE tp := target.Tp if val == nil { return nil, nil } switch tp { // TODO: implement mysql types convert when "CAST() AS" syntax are supported. case mysql.TypeFloat: x, err := ToFloat64(val) if err != nil { return invConv(val, tp) } if target.Flen != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float32(x), nil case mysql.TypeDouble: x, err := ToFloat64(val) if err != nil { return invConv(val, tp) } if target.Flen != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float64(x), nil case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString: x, err := ToString(val) if err != nil { return invConv(val, tp) } // TODO: consider target.Charset/Collate x = truncateStr(x, target.Flen) if target.Charset == charset.CharsetBin { return []byte(x), nil } return x, nil case mysql.TypeDuration: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Duration: return x.RoundFrac(fsp) case mysql.Time: t, err := x.ConvertToDuration() if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseDuration(x, fsp) default: return invConv(val, tp) } case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Time: t, err := x.Convert(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case mysql.Duration: t, err := x.ConvertToTime(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseTime(x, tp, fsp) case int64: return mysql.ParseTimeFromNum(x, tp, fsp) default: return invConv(val, tp) } case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: unsigned := mysql.HasUnsignedFlag(target.Flag) if unsigned { return convertToUint(val, target) } return convertToInt(val, target) case mysql.TypeBit: x, err := convertToUint(val, target) if err != nil { return x, errors.Trace(err) } // check bit boundary, if bit has n width, the boundary is // in [0, (1 << n) - 1] width := target.Flen if width == 0 { width = mysql.MinBitWidth } else if width == mysql.UnspecifiedBitWidth { width = mysql.MaxBitWidth } maxValue := uint64(1)<<uint64(width) - 1 if x > maxValue { return maxValue, overflow(val, tp) } return x, nil case mysql.TypeDecimal, mysql.TypeNewDecimal: x, err := ToDecimal(val) if err != nil { return invConv(val, tp) } if target.Decimal != UnspecifiedLength { x = x.Round(int32(target.Decimal)) } // TODO: check Flen return x, nil case mysql.TypeYear: var ( intVal int64 err error ) switch x := val.(type) { case string: intVal, err = StrToInt(x) case mysql.Time: return int64(x.Year()), nil case mysql.Duration: return int64(time.Now().Year()), nil default: intVal, err = ToInt64(x) } if err != nil { return invConv(val, tp) } y, err := mysql.AdjustYear(int(intVal)) if err != nil { return invConv(val, tp) } return int64(y), nil default: panic("should never happen") } }
// Cast casts val to certain types and does not return error. func Cast(val interface{}, target *FieldType) (v interface{}) { //NTYPE tp := target.Tp switch tp { case mysql.TypeString: x, _ := ToString(val) // TODO: consider target.Charset/Collate x = truncateStr(x, target.Flen) if target.Charset == charset.CharsetBin { return []byte(x) } return x case mysql.TypeDuration: var dur mysql.Duration fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Duration: dur, _ = x.RoundFrac(fsp) case mysql.Time: dur, _ = x.ConvertToDuration() dur, _ = dur.RoundFrac(fsp) case string: dur, _ = mysql.ParseDuration(x, fsp) } return dur case mysql.TypeDatetime, mysql.TypeDate: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } var t mysql.Time t.Type = tp switch x := val.(type) { case mysql.Time: t, _ = x.Convert(tp) t, _ = t.RoundFrac(fsp) case mysql.Duration: t, _ = x.ConvertToTime(tp) t, _ = t.RoundFrac(fsp) case string: t, _ = mysql.ParseTime(x, tp, fsp) case int64: t, _ = mysql.ParseTimeFromNum(x, tp, fsp) } return t case mysql.TypeLonglong: if mysql.HasUnsignedFlag(target.Flag) { v, _ = ToUint64(val) } else { v, _ = ToInt64(val) } return case mysql.TypeNewDecimal: x, _ := ToDecimal(val) if target.Decimal != UnspecifiedLength { x = x.Round(int32(target.Decimal)) } // TODO: check Flen return x default: panic("should never happen") } }
func (c *Col) isUnsignedLongLongType() bool { return mysql.HasUnsignedFlag(c.Flag) && c.Tp == mysql.TypeLonglong }
// Convert converts the val with type tp. func Convert(val interface{}, target *FieldType) (v interface{}, err error) { //NTYPE tp := target.Tp if val == nil { return nil, nil } switch tp { // TODO: implement mysql types convert when "CAST() AS" syntax are supported. case mysql.TypeFloat: x, err := ToFloat64(val) if err != nil { return InvConv(val, tp) } if target.Flen != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float32(x), nil case mysql.TypeDouble: x, err := ToFloat64(val) if err != nil { return InvConv(val, tp) } if target.Flen != UnspecifiedLength { x, err = TruncateFloat(x, target.Flen, target.Decimal) if err != nil { return nil, errors.Trace(err) } } return float64(x), nil case mysql.TypeString: x, err := ToString(val) if err != nil { return InvConv(val, tp) } // TODO: consider target.Charset/Collate x = truncateStr(x, target.Flen) if target.Charset == charset.CharsetBin { return []byte(x), nil } return x, nil case mysql.TypeBlob: x, err := ToString(val) if err != nil { return InvConv(val, tp) } x = truncateStr(x, target.Flen) if target.Charset == charset.CharsetBin { return []byte(x), nil } return x, nil case mysql.TypeDuration: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Duration: return x.RoundFrac(fsp) case mysql.Time: t, err := x.ConvertToDuration() if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseDuration(x, fsp) default: return InvConv(val, tp) } case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate: fsp := mysql.DefaultFsp if target.Decimal != UnspecifiedLength { fsp = target.Decimal } switch x := val.(type) { case mysql.Time: t, err := x.Convert(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case mysql.Duration: t, err := x.ConvertToTime(tp) if err != nil { return nil, errors.Trace(err) } return t.RoundFrac(fsp) case string: return mysql.ParseTime(x, tp, fsp) default: return InvConv(val, tp) } case mysql.TypeLonglong: x, err := ToInt64(val) if err != nil { return InvConv(val, tp) } // TODO: We should first convert to uint64 then check unsigned flag. if mysql.HasUnsignedFlag(target.Flag) { return uint64(x), nil } return x, nil case mysql.TypeNewDecimal: x, err := ToDecimal(val) if err != nil { return InvConv(val, tp) } if target.Decimal != UnspecifiedLength { x = x.Round(int32(target.Decimal)) } // TODO: check Flen return x, nil case mysql.TypeYear: var ( intVal int64 err error ) switch x := val.(type) { case string: intVal, err = StrToInt(x) case mysql.Time: return int16(x.Year()), nil case mysql.Duration: return int16(time.Now().Year()), nil default: intVal, err = ToInt64(x) } if err != nil { return InvConv(val, tp) } y, err := mysql.AdjustYear(int(intVal)) if err != nil { return InvConv(val, tp) } return int16(y), nil default: panic("should never happen") } }
func (c *Col) castIntegerValue(val int64, errCode int) (casted interface{}, err error) { unsigned := mysql.HasUnsignedFlag(c.Flag) var overflow bool switch c.Tp { case mysql.TypeTiny: if unsigned { if val > math.MaxUint8 || errCode == errCodeOverflowUpper { overflow = true casted = uint8(math.MaxUint8) } else if val < 0 || errCode == errCodeOverflowLower { overflow = true casted = uint8(0) } else { casted = uint8(val) } } else { if val > math.MaxInt8 || errCode == errCodeOverflowUpper { overflow = true casted = int8(math.MaxInt8) } else if val < math.MinInt8 || errCode == errCodeOverflowLower { overflow = true casted = int8(math.MinInt8) } else { casted = int8(val) } } case mysql.TypeShort: if unsigned { if val > math.MaxUint16 || errCode == errCodeOverflowUpper { overflow = true casted = uint16(math.MaxUint16) } else if val < 0 || errCode == errCodeOverflowLower { overflow = true casted = uint16(0) } else { casted = uint16(val) } } else { if val > math.MaxInt16 || errCode == errCodeOverflowUpper { overflow = true casted = int16(math.MaxInt16) } else if val < math.MinInt16 || errCode == errCodeOverflowLower { overflow = true casted = int16(math.MinInt16) } else { casted = int16(val) } } case mysql.TypeYear: if val > int64(mysql.MaxYear) || errCode == errCodeOverflowUpper { overflow = true casted = mysql.MaxYear } else if val < int64(mysql.MinYear) { overflow = true casted = mysql.MinYear } else { casted, _ = mysql.AdjustYear(int(val)) } case mysql.TypeInt24: if unsigned { if val < 0 || errCode == errCodeOverflowLower { overflow = true casted = uint32(0) } else if val > 1<<24-1 || errCode == errCodeOverflowUpper { overflow = true casted = uint32(1<<24 - 1) } else { casted = uint32(val) } } else { if val > 1<<23-1 || errCode == errCodeOverflowUpper { overflow = true casted = int32(1<<23 - 1) } else if val < -1<<23 || errCode == errCodeOverflowLower { overflow = true casted = int32(-1 << 23) } else { casted = int32(val) } } case mysql.TypeLong: if unsigned { if val > math.MaxUint32 || errCode == errCodeOverflowUpper { overflow = true casted = uint32(math.MaxUint32) } else if (val < 0 && errCode != errCodeOverflowMaxInt64) || errCode == errCodeOverflowLower { overflow = true casted = uint32(0) } else { casted = uint32(val) } } else { if val > math.MaxInt32 || errCode == errCodeOverflowUpper { overflow = true casted = int32(math.MaxInt32) } else if val < math.MinInt32 || errCode == errCodeOverflowLower { overflow = true casted = int32(math.MinInt32) } else { casted = int32(val) } } case mysql.TypeLonglong: // TypeLonglong overflow has already been handled by normalizeInteger if unsigned { if errCode == errCodeOverflowUpper { overflow = true casted = uint64(math.MaxUint64) } else if (val < 0 && errCode != errCodeOverflowMaxInt64) || errCode == errCodeOverflowLower { overflow = true casted = uint64(0) } else { casted = uint64(val) } } else { if errCode == errCodeOverflowUpper { overflow = true casted = int64(math.MaxInt64) } else if errCode == errCodeOverflowLower { overflow = true casted = int64(math.MinInt64) } else { casted = int64(val) } } case mysql.TypeBit: // Convert bit as uint64 if errCode == errCodeOverflowUpper { overflow = true casted = uint64(math.MaxUint64) } else if (val < 0 && errCode != errCodeOverflowMaxInt64) || errCode == errCodeOverflowLower { overflow = true casted = uint64(0) } else { casted = uint64(val) } } if overflow { err = types.Overflow(val, c.Tp) } return }