Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
// 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, " ")
}
Exemplo n.º 3
0
// 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()
}
Exemplo n.º 4
0
// 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
}
Exemplo n.º 5
0
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, " ")
}
Exemplo n.º 6
0
// 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)
}
Exemplo n.º 7
0
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, " ")
}
Exemplo n.º 8
0
// 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)
}
Exemplo n.º 9
0
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, " ")
}
Exemplo n.º 10
0
// 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, " ")
}
Exemplo n.º 11
0
// 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, " ")
}
Exemplo n.º 12
0
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
}
Exemplo n.º 13
0
Arquivo: cast.go Projeto: npk/tidb
// 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
}
Exemplo n.º 14
0
// 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")
	}
}
Exemplo n.º 15
0
// 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")
	}
}
Exemplo n.º 16
0
// 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")
	}
}
Exemplo n.º 17
0
func (c *Col) isUnsignedLongLongType() bool {
	return mysql.HasUnsignedFlag(c.Flag) && c.Tp == mysql.TypeLonglong
}
Exemplo n.º 18
0
// 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")
	}
}
Exemplo n.º 19
0
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
}