func dumpTextValue(mysqlType uint8, value types.Datum) ([]byte, error) { switch value.Kind() { case types.KindInt64: return strconv.AppendInt(nil, value.GetInt64(), 10), nil case types.KindUint64: return strconv.AppendUint(nil, value.GetUint64(), 10), nil case types.KindFloat32: return strconv.AppendFloat(nil, value.GetFloat64(), 'f', -1, 32), nil case types.KindFloat64: return strconv.AppendFloat(nil, value.GetFloat64(), 'f', -1, 64), nil case types.KindString, types.KindBytes: return value.GetBytes(), nil case types.KindMysqlTime: return hack.Slice(value.GetMysqlTime().String()), nil case types.KindMysqlDuration: return hack.Slice(value.GetMysqlDuration().String()), nil case types.KindMysqlDecimal: return hack.Slice(value.GetMysqlDecimal().String()), nil case types.KindMysqlEnum: return hack.Slice(value.GetMysqlEnum().String()), nil case types.KindMysqlSet: return hack.Slice(value.GetMysqlSet().String()), nil case types.KindMysqlBit: return hack.Slice(value.GetMysqlBit().ToString()), nil case types.KindMysqlHex: return hack.Slice(value.GetMysqlHex().ToString()), nil default: return nil, errInvalidType.Gen("invalid type %T", value) } }
func datumExpr(d types.Datum) *tipb.Expr { expr := new(tipb.Expr) switch d.Kind() { case types.KindInt64: expr.Tp = tipb.ExprType_Int64 expr.Val = codec.EncodeInt(nil, d.GetInt64()) case types.KindUint64: expr.Tp = tipb.ExprType_Uint64 expr.Val = codec.EncodeUint(nil, d.GetUint64()) case types.KindString: expr.Tp = tipb.ExprType_String expr.Val = d.GetBytes() case types.KindBytes: expr.Tp = tipb.ExprType_Bytes expr.Val = d.GetBytes() case types.KindFloat32: expr.Tp = tipb.ExprType_Float32 expr.Val = codec.EncodeFloat(nil, d.GetFloat64()) case types.KindFloat64: expr.Tp = tipb.ExprType_Float64 expr.Val = codec.EncodeFloat(nil, d.GetFloat64()) case types.KindMysqlDuration: expr.Tp = tipb.ExprType_MysqlDuration expr.Val = codec.EncodeInt(nil, int64(d.GetMysqlDuration().Duration)) case types.KindMysqlDecimal: expr.Tp = tipb.ExprType_MysqlDecimal expr.Val = codec.EncodeDecimal(nil, d) default: expr.Tp = tipb.ExprType_Null } return expr }
func unflatten(datum types.Datum, tp *types.FieldType) (types.Datum, error) { if datum.IsNull() { return datum, nil } switch tp.Tp { case mysql.TypeFloat: datum.SetFloat32(float32(datum.GetFloat64())) return datum, nil case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, mysql.TypeVarchar, mysql.TypeString: return datum, nil case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: var t mysql.Time t.Type = tp.Tp t.Fsp = tp.Decimal err := t.Unmarshal(datum.GetBytes()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(t) return datum, nil case mysql.TypeDuration: dur := mysql.Duration{Duration: time.Duration(datum.GetInt64())} datum.SetValue(dur) return datum, nil case mysql.TypeNewDecimal, mysql.TypeDecimal: dec, err := mysql.ParseDecimal(datum.GetString()) if err != nil { return datum, errors.Trace(err) } if tp.Decimal >= 0 { dec = dec.Truncate(int32(tp.Decimal)) } datum.SetValue(dec) return datum, nil case mysql.TypeEnum: enum, err := mysql.ParseEnumValue(tp.Elems, datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(enum) return datum, nil case mysql.TypeSet: set, err := mysql.ParseSetValue(tp.Elems, datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(set) return datum, nil case mysql.TypeBit: bit := mysql.Bit{Value: datum.GetUint64(), Width: tp.Flen} datum.SetValue(bit) return datum, nil } log.Error(tp.Tp, datum) return datum, nil }
// Unflatten converts a raw datum to a column datum. func Unflatten(datum types.Datum, ft *types.FieldType, inIndex bool) (types.Datum, error) { if datum.IsNull() { return datum, nil } switch ft.Tp { case mysql.TypeFloat: datum.SetFloat32(float32(datum.GetFloat64())) return datum, nil case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, mysql.TypeVarchar, mysql.TypeString: return datum, nil case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: var t types.Time t.Type = ft.Tp t.Fsp = ft.Decimal var err error err = t.FromPackedUint(datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetMysqlTime(t) return datum, nil case mysql.TypeDuration: dur := types.Duration{Duration: time.Duration(datum.GetInt64())} datum.SetValue(dur) return datum, nil case mysql.TypeEnum: enum, err := types.ParseEnumValue(ft.Elems, datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(enum) return datum, nil case mysql.TypeSet: set, err := types.ParseSetValue(ft.Elems, datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(set) return datum, nil case mysql.TypeBit: bit := types.Bit{Value: datum.GetUint64(), Width: ft.Flen} datum.SetValue(bit) return datum, nil } return datum, nil }
func computeMul(a, b types.Datum) (d types.Datum, err error) { switch a.Kind() { case types.KindInt64: switch b.Kind() { case types.KindInt64: r, err1 := types.MulInt64(a.GetInt64(), b.GetInt64()) d.SetInt64(r) return d, errors.Trace(err1) case types.KindUint64: r, err1 := types.MulInteger(b.GetUint64(), a.GetInt64()) d.SetUint64(r) return d, errors.Trace(err1) } case types.KindUint64: switch b.Kind() { case types.KindInt64: r, err1 := types.MulInteger(a.GetUint64(), b.GetInt64()) d.SetUint64(r) return d, errors.Trace(err1) case types.KindUint64: r, err1 := types.MulUint64(a.GetUint64(), b.GetUint64()) d.SetUint64(r) return d, errors.Trace(err1) } case types.KindFloat64: switch b.Kind() { case types.KindFloat64: r := a.GetFloat64() * b.GetFloat64() d.SetFloat64(r) return d, nil } case types.KindMysqlDecimal: switch b.Kind() { case types.KindMysqlDecimal: r := a.GetMysqlDecimal().Mul(b.GetMysqlDecimal()) d.SetMysqlDecimal(r) return d, nil } } _, err = types.InvOp2(a.GetValue(), b.GetValue(), opcode.Mul) return d, errors.Trace(err) }
func computeMinus(a, b types.Datum) (d types.Datum, err error) { switch a.Kind() { case types.KindInt64: switch b.Kind() { case types.KindInt64: r, err1 := types.SubInt64(a.GetInt64(), b.GetInt64()) d.SetInt64(r) return d, errors.Trace(err1) case types.KindUint64: r, err1 := types.SubIntWithUint(a.GetInt64(), b.GetUint64()) d.SetUint64(r) return d, errors.Trace(err1) } case types.KindUint64: switch b.Kind() { case types.KindInt64: r, err1 := types.SubUintWithInt(a.GetUint64(), b.GetInt64()) d.SetUint64(r) return d, errors.Trace(err1) case types.KindUint64: r, err1 := types.SubUint64(a.GetUint64(), b.GetUint64()) d.SetUint64(r) return d, errors.Trace(err1) } case types.KindFloat64: switch b.Kind() { case types.KindFloat64: r := a.GetFloat64() - b.GetFloat64() d.SetFloat64(r) return d, nil } case types.KindMysqlDecimal: switch b.Kind() { case types.KindMysqlDecimal: r := a.GetMysqlDecimal().Sub(b.GetMysqlDecimal()) d.SetMysqlDecimal(r) return d, nil } } _, err = types.InvOp2(a.GetValue(), b.GetValue(), opcode.Minus) return d, errors.Trace(err) }
func computeDiv(a, b types.Datum) (d types.Datum, err error) { // MySQL support integer divison Div and division operator / // we use opcode.Div for division operator and will use another for integer division later. // for division operator, we will use float64 for calculation. switch a.Kind() { case types.KindFloat64: y, err1 := b.ToFloat64() if err1 != nil { return d, errors.Trace(err1) } if y == 0 { return d, nil } x := a.GetFloat64() d.SetFloat64(x / y) return d, nil default: // the scale of the result is the scale of the first operand plus // the value of the div_precision_increment system variable (which is 4 by default) // we will use 4 here xa, err1 := a.ToDecimal() if err != nil { return d, errors.Trace(err1) } xb, err1 := b.ToDecimal() if err1 != nil { return d, errors.Trace(err1) } if f, _ := xb.Float64(); f == 0 { // division by zero return null return d, nil } d.SetMysqlDecimal(xa.Div(xb)) return d, nil } }
func (b *executorBuilder) datumToPBExpr(client kv.Client, d types.Datum) *tipb.Expr { var tp tipb.ExprType var val []byte switch d.Kind() { case types.KindNull: tp = tipb.ExprType_Null case types.KindInt64: tp = tipb.ExprType_Int64 val = codec.EncodeInt(nil, d.GetInt64()) case types.KindUint64: tp = tipb.ExprType_Uint64 val = codec.EncodeUint(nil, d.GetUint64()) case types.KindString: tp = tipb.ExprType_String val = d.GetBytes() case types.KindBytes: tp = tipb.ExprType_Bytes val = d.GetBytes() case types.KindFloat32: tp = tipb.ExprType_Float32 val = codec.EncodeFloat(nil, d.GetFloat64()) case types.KindFloat64: tp = tipb.ExprType_Float64 val = codec.EncodeFloat(nil, d.GetFloat64()) case types.KindMysqlDuration: tp = tipb.ExprType_MysqlDuration val = codec.EncodeInt(nil, int64(d.GetMysqlDuration().Duration)) case types.KindMysqlDecimal: tp = tipb.ExprType_MysqlDecimal val = codec.EncodeDecimal(nil, d.GetMysqlDecimal()) default: return nil } if !client.SupportRequestType(kv.ReqTypeSelect, int64(tp)) { return nil } return &tipb.Expr{Tp: tp.Enum(), Val: val} }
func computeMod(a, b types.Datum) (d types.Datum, err error) { switch a.Kind() { case types.KindInt64: x := a.GetInt64() switch b.Kind() { case types.KindInt64: y := b.GetInt64() if y == 0 { return d, nil } d.SetInt64(x % y) return d, nil case types.KindUint64: y := b.GetUint64() if y == 0 { return d, nil } else if x < 0 { d.SetInt64(-int64(uint64(-x) % y)) // first is int64, return int64. return d, nil } d.SetInt64(int64(uint64(x) % y)) return d, nil } case types.KindUint64: x := a.GetUint64() switch b.Kind() { case types.KindInt64: y := b.GetInt64() if y == 0 { return d, nil } else if y < 0 { // first is uint64, return uint64. d.SetUint64(uint64(x % uint64(-y))) return d, nil } d.SetUint64(x % uint64(y)) return d, nil case types.KindUint64: y := b.GetUint64() if y == 0 { return d, nil } d.SetUint64(x % y) return d, nil } case types.KindFloat64: x := a.GetFloat64() switch b.Kind() { case types.KindFloat64: y := b.GetFloat64() if y == 0 { return d, nil } d.SetFloat64(math.Mod(x, y)) return d, nil } case types.KindMysqlDecimal: x := a.GetMysqlDecimal() switch b.Kind() { case types.KindMysqlDecimal: y := b.GetMysqlDecimal() xf, _ := x.Float64() yf, _ := y.Float64() if yf == 0 { return d, nil } d.SetFloat64(math.Mod(xf, yf)) return d, nil } } _, err = types.InvOp2(a.GetValue(), b.GetValue(), opcode.Mod) return d, errors.Trace(err) }