// 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 }
// See http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_from-unixtime func builtinFromUnixTime(args []types.Datum, ctx context.Context) (d types.Datum, err error) { sc := ctx.GetSessionVars().StmtCtx unixTimeStamp, err := args[0].ToDecimal(sc) if err != nil { return d, errors.Trace(err) } // 0 <= unixTimeStamp <= INT32_MAX if unixTimeStamp.IsNegative() { return } integralPart, err := unixTimeStamp.ToInt() if err == types.ErrTruncated { err = nil } if err != nil { return d, errors.Trace(err) } if integralPart > int64(math.MaxInt32) { return } // Split the integral part and fractional part of a decimal timestamp. // e.g. for timestamp 12345.678, // first get the integral part 12345, // then (12345.678 - 12345) * (10^9) to get the decimal part and convert it to nanosecond precision. integerDecimalTp := new(types.MyDecimal).FromInt(integralPart) fracDecimalTp := new(types.MyDecimal) err = types.DecimalSub(unixTimeStamp, integerDecimalTp, fracDecimalTp) if err != nil { return d, errors.Trace(err) } nano := new(types.MyDecimal).FromInt(int64(time.Second)) x := new(types.MyDecimal) err = types.DecimalMul(fracDecimalTp, nano, x) if err != nil { return d, errors.Trace(err) } fractionalPart, err := x.ToInt() // here fractionalPart is result multiplying the original fractional part by 10^9. if err == types.ErrTruncated { err = nil } if err != nil { return d, errors.Trace(err) } _, fracDigitsNumber := unixTimeStamp.PrecisionAndFrac() fsp := fracDigitsNumber if fracDigitsNumber > types.MaxFsp { fsp = types.MaxFsp } tr, err := types.RoundFrac(time.Unix(integralPart, fractionalPart), fsp) if err != nil { return d, errors.Trace(err) } t := types.Time{ Time: types.FromGoTime(tr), Type: mysql.TypeDatetime, Fsp: fsp, } if args[0].Kind() == types.KindString { // Keep consistent with MySQL. t.Fsp = types.MaxFsp } d.SetMysqlTime(t) if len(args) == 1 { return } return builtinDateFormat([]types.Datum{d, args[1]}, ctx) }