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 }
func parseDayInterval(value types.Datum) (int64, error) { switch value.Kind() { case types.KindString: vs := value.GetString() s := strings.ToLower(vs) if s == "false" { return 0, nil } else if s == "true" { return 1, nil } value.SetString(reg.FindString(vs)) } return value.ToInt64() }
func coerceArithmetic(a types.Datum) (d types.Datum, err error) { switch a.Kind() { case types.KindString, types.KindBytes: // MySQL will convert string to float for arithmetic operation f, err := types.StrToFloat(a.GetString()) if err != nil { return d, errors.Trace(err) } d.SetFloat64(f) return d, errors.Trace(err) case types.KindMysqlTime: // if time has no precision, return int64 t := a.GetMysqlTime() de := t.ToNumber() if t.Fsp == 0 { d.SetInt64(de.IntPart()) return d, nil } d.SetMysqlDecimal(de) return d, nil case types.KindMysqlDuration: // if duration has no precision, return int64 du := a.GetMysqlDuration() de := du.ToNumber() if du.Fsp == 0 { d.SetInt64(de.IntPart()) return d, nil } d.SetMysqlDecimal(de) return d, nil case types.KindMysqlHex: d.SetFloat64(a.GetMysqlHex().ToNumber()) return d, nil case types.KindMysqlBit: d.SetFloat64(a.GetMysqlBit().ToNumber()) return d, nil case types.KindMysqlEnum: d.SetFloat64(a.GetMysqlEnum().ToNumber()) return d, nil case types.KindMysqlSet: d.SetFloat64(a.GetMysqlSet().ToNumber()) return d, nil default: return a, nil } }
func convertDateFormat(ctx context.Context, arg types.Datum, b byte) (types.Datum, error) { var d types.Datum var err error switch b { case 'b': d, err = builtinMonthName([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(d.GetString()[:3]) } case 'M': d, err = builtinMonthName([]types.Datum{arg}, ctx) case 'm': d, err = builtinMonth([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'c': d, err = builtinMonth([]types.Datum{arg}, ctx) case 'D': d, err = abbrDayOfMonth(arg, ctx) case 'd': d, err = builtinDayOfMonth([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'e': d, err = builtinDayOfMonth([]types.Datum{arg}, ctx) case 'j': d, err = builtinDayOfYear([]types.Datum{arg}, ctx) if err == nil { d.SetString(fmt.Sprintf("%03d", d.GetInt64())) } case 'H', 'k': d, err = builtinHour([]types.Datum{arg}, ctx) if err == nil && b == 'H' && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'h', 'I', 'l': d, err = builtinHour([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { if d.GetInt64() > 12 { d.SetInt64(d.GetInt64() - 12) } else if d.GetInt64() == 0 { d.SetInt64(12) } d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'i': d, err = builtinMinute([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'p': d, err = builtinHour([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { if d.GetInt64() < 12 { d.SetString("AM") break } d.SetString("PM") } case 'r': d, err = to12Hour(arg, ctx) case 'T': d, err = builtinTime([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { duration := types.Duration{ Duration: d.GetMysqlDuration().Duration, Fsp: 0} d.SetMysqlDuration(duration) } case 'S', 's': d, err = builtinSecond([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'f': d, err = builtinMicroSecond([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%06d", d.GetInt64())) } case 'U': d, err = builtinWeek([]types.Datum{arg, types.NewIntDatum(0)}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'u': d, err = builtinWeek([]types.Datum{arg, types.NewIntDatum(1)}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'V': d, err = builtinWeek([]types.Datum{arg, types.NewIntDatum(2)}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'v': d, err = builtinWeek([]types.Datum{arg, types.NewIntDatum(3)}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%02d", d.GetInt64())) } case 'a': d, err = builtinDayName([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(d.GetString()[:3]) } case 'W': d, err = builtinDayName([]types.Datum{arg}, ctx) case 'w': d, err = builtinDayOfWeek([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetInt64(d.GetInt64() - 1) } case 'X': d, err = builtinYearWeek([]types.Datum{arg, types.NewIntDatum(2)}, ctx) if err == nil && !d.IsNull() { if d.GetInt64() == math.MaxUint32 { break } str := fmt.Sprintf("%04d", d.GetInt64()) d.SetString(fmt.Sprintf("%04s", str[:4])) } case 'x': d, err = builtinYearWeek([]types.Datum{arg, types.NewIntDatum(3)}, ctx) if err == nil && !d.IsNull() { if d.GetInt64() == math.MaxUint32 { break } str := fmt.Sprintf("%04d", d.GetInt64()) d.SetString(fmt.Sprintf("%04s", str[:4])) } case 'Y': d, err = builtinYear([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%04d", d.GetInt64())) } case 'y': d, err = builtinYear([]types.Datum{arg}, ctx) if err == nil && !d.IsNull() { str := fmt.Sprintf("%04d", d.GetInt64()) d.SetString(fmt.Sprintf("%02s", str[2:])) } default: d.SetString(string(b)) } if err == nil && !d.IsNull() { d.SetString(fmt.Sprintf("%v", d.GetValue())) } return d, errors.Trace(err) }
// 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 mysql.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 := mysql.Duration{Duration: time.Duration(datum.GetInt64())} datum.SetValue(dur) return datum, nil case mysql.TypeNewDecimal: if datum.Kind() == types.KindMysqlDecimal { if ft.Decimal >= 0 { dec := datum.GetMysqlDecimal().Truncate(int32(ft.Decimal)) datum.SetMysqlDecimal(dec) } return datum, nil } dec, err := mysql.ParseDecimal(datum.GetString()) if err != nil { return datum, errors.Trace(err) } if ft.Decimal >= 0 { dec = dec.Truncate(int32(ft.Decimal)) } datum.SetValue(dec) return datum, nil case mysql.TypeEnum: enum, err := mysql.ParseEnumValue(ft.Elems, datum.GetUint64()) if err != nil { return datum, errors.Trace(err) } datum.SetValue(enum) return datum, nil case mysql.TypeSet: set, err := mysql.ParseSetValue(ft.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: ft.Flen} datum.SetValue(bit) return datum, nil } return datum, nil }