func builtinNow(args []types.Datum, _ context.Context) (d types.Datum, err error) { // TODO: if NOW is used in stored function or trigger, NOW will return the beginning time // of the execution. fsp := 0 if len(args) == 1 && args[0].Kind() != types.KindNull { if fsp, err = checkFsp(args[0]); err != nil { d.SetNull() return d, errors.Trace(err) } } t := mysql.Time{ Time: time.Now(), Type: mysql.TypeDatetime, // set unspecified for later round Fsp: mysql.UnspecifiedFsp, } tr, err := t.RoundFrac(int(fsp)) if err != nil { d.SetNull() return d, errors.Trace(err) } d.SetMysqlTime(tr) return d, nil }
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 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.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 }
func (s *testCodecSuite) TestTime(c *C) { defer testleak.AfterTest(c)() tbl := []string{ "2011-01-01 00:00:00", "2011-01-01 00:00:00", "0001-01-01 00:00:00", } for _, t := range tbl { m := types.NewDatum(parseTime(c, t)) b, err := EncodeKey(nil, m) c.Assert(err, IsNil) v, err := Decode(b) c.Assert(err, IsNil) var t mysql.Time t.Type = mysql.TypeDatetime t.FromPackedUint(v[0].GetUint64()) c.Assert(types.NewDatum(t), DeepEquals, m) } tblCmp := []struct { Arg1 string Arg2 string Ret int }{ {"2011-10-10 00:00:00", "2000-12-12 11:11:11", 1}, {"2000-10-10 00:00:00", "2001-10-10 00:00:00", -1}, {"2000-10-10 00:00:00", "2000-10-10 00:00:00", 0}, } for _, t := range tblCmp { m1 := types.NewDatum(parseTime(c, t.Arg1)) m2 := types.NewDatum(parseTime(c, t.Arg2)) b1, err := EncodeKey(nil, m1) c.Assert(err, IsNil) b2, err := EncodeKey(nil, m2) c.Assert(err, IsNil) ret := bytes.Compare(b1, b2) c.Assert(ret, Equals, t.Ret) } }
func builtinNow(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) { // TODO: if NOW is used in stored function or trigger, NOW will return the beginning time // of the execution. fsp := 0 if len(args) == 1 { var err error if fsp, err = checkFsp(args[0]); err != nil { return nil, errors.Trace(err) } } t := mysql.Time{ Time: time.Now(), Type: mysql.TypeDatetime, // set unspecified for later round Fsp: mysql.UnspecifiedFsp, } return t.RoundFrac(int(fsp)) }
func (d *Datum) compareMysqlTime(time mysql.Time) (int, error) { switch d.k { case KindString, KindBytes: dt, err := mysql.ParseDatetime(d.GetString()) return dt.Compare(time), err case KindMysqlTime: return d.GetMysqlTime().Compare(time), nil default: fVal, _ := time.ToNumber().ToFloat64() return d.compareFloat64(fVal) } }
func dumpBinaryDateTime(t mysql.Time, loc *time.Location) (data []byte) { if t.Type == mysql.TypeTimestamp && loc != nil { t.Time = t.In(loc) } year, mon, day := t.Year(), t.Month(), t.Day() if t.IsZero() { year, mon, day = 1, time.January, 1 } switch t.Type { case mysql.TypeTimestamp, mysql.TypeDatetime: data = append(data, 11) data = append(data, dumpUint16(uint16(year))...) data = append(data, byte(mon), byte(day), byte(t.Hour()), byte(t.Minute()), byte(t.Second())) data = append(data, dumpUint32(uint32((t.Nanosecond() / 1000)))...) case mysql.TypeDate, mysql.TypeNewDate: data = append(data, 4) data = append(data, dumpUint16(uint16(year))...) //year data = append(data, byte(mon), byte(day)) } return }
func getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (interface{}, error) { value := mysql.Time{ Type: tp, Fsp: fsp, } defaultTime, err := getSystemTimestamp(ctx) if err != nil { return nil, errors.Trace(err) } switch x := v.(type) { case string: if x == CurrentTimestamp { value.Time = defaultTime } else if x == ZeroTimestamp { value, _ = mysql.ParseTimeFromNum(0, tp, fsp) } else { value, err = mysql.ParseTime(x, tp, fsp) if err != nil { return nil, errors.Trace(err) } } case Value: x.Val = types.RawData(x.Val) switch xval := x.Val.(type) { case string: value, err = mysql.ParseTime(xval, tp, fsp) if err != nil { return nil, errors.Trace(err) } case int64: value, err = mysql.ParseTimeFromNum(int64(xval), tp, fsp) if err != nil { return nil, errors.Trace(err) } case nil: return nil, nil default: return nil, errors.Trace(errDefaultValue) } case *Ident: if x.Equal(CurrentTimeExpr) { return CurrentTimestamp, nil } return nil, errors.Trace(errDefaultValue) case *UnaryOperation: // support some expression, like `-1` m := map[interface{}]interface{}{} v := Eval(x, nil, m) ft := types.NewFieldType(mysql.TypeLonglong) xval, err := types.Convert(v, ft) if err != nil { return nil, errors.Trace(err) } value, err = mysql.ParseTimeFromNum(xval.(int64), tp, fsp) if err != nil { return nil, errors.Trace(err) } default: return nil, nil } return value, nil }
// Cast casts val to certain types and does not return error. func Cast(val interface{}, target *FieldType) (v interface{}) { 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) case *DataItem: return Cast(x.Data, target) } 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) case *DataItem: return Cast(x.Data, target) } 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 getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (d types.Datum, err error) { value := mysql.Time{ Type: tp, Fsp: fsp, } defaultTime, err := getSystemTimestamp(ctx) if err != nil { return d, errors.Trace(err) } switch x := v.(type) { case string: upperX := strings.ToUpper(x) if upperX == CurrentTimestamp { value.Time = defaultTime } else if upperX == ZeroTimestamp { value, _ = mysql.ParseTimeFromNum(0, tp, fsp) } else { value, err = mysql.ParseTime(x, tp, fsp) if err != nil { return d, errors.Trace(err) } } case *ast.ValueExpr: switch x.Kind() { case types.KindString: value, err = mysql.ParseTime(x.GetString(), tp, fsp) if err != nil { return d, errors.Trace(err) } case types.KindInt64: value, err = mysql.ParseTimeFromNum(x.GetInt64(), tp, fsp) if err != nil { return d, errors.Trace(err) } case types.KindNull: return d, nil default: return d, errors.Trace(errDefaultValue) } case *ast.FuncCallExpr: if x.FnName.L == currentTimestampL { d.SetString(CurrentTimestamp) return d, nil } return d, errors.Trace(errDefaultValue) case *ast.UnaryOperationExpr: // support some expression, like `-1` v, err := Eval(ctx, x) if err != nil { return d, errors.Trace(err) } ft := types.NewFieldType(mysql.TypeLonglong) xval, err := v.ConvertTo(ft) if err != nil { return d, errors.Trace(err) } value, err = mysql.ParseTimeFromNum(xval.GetInt64(), tp, fsp) if err != nil { return d, errors.Trace(err) } default: return d, nil } d.SetMysqlTime(value) return d, nil }