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 builtinNow(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) { fsp := int64(0) if len(args) == 1 { var err error fsp, err = types.ToInt64(args[0]) if err != nil { return nil, errors.Trace(err) } if int(fsp) > mysql.MaxFsp { return nil, errors.Errorf("Too big precision %d specified. Maximum is 6.", fsp) } else if fsp < 0 { return nil, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) } } t := mysql.Time{ Time: time.Now(), Type: mysql.TypeDatetime, // set unspecified for later round Fsp: mysql.UnspecifiedFsp, } return t.RoundFrac(int(fsp)) }
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: 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{}) { //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") } }
func extractTime(unit string, t mysql.Time) (int64, error) { switch strings.ToUpper(unit) { case "MICROSECOND": return int64(t.Nanosecond() / 1000), nil case "SECOND": return int64(t.Second()), nil case "MINUTE": return int64(t.Minute()), nil case "HOUR": return int64(t.Hour()), nil case "DAY": return int64(t.Day()), nil case "WEEK": _, week := t.ISOWeek() return int64(week), nil case "MONTH": return int64(t.Month()), nil case "QUARTER": m := int64(t.Month()) // 1 - 3 -> 1 // 4 - 6 -> 2 // 7 - 9 -> 3 // 10 - 12 -> 4 return (m + 2) / 3, nil case "YEAR": return int64(t.Year()), nil case "SECOND_MICROSECOND": return int64(t.Second())*1000000 + int64(t.Nanosecond())/1000, nil case "MINUTE_MICROSECOND": _, m, s := t.Clock() return int64(m)*100000000 + int64(s)*1000000 + int64(t.Nanosecond())/1000, nil case "MINUTE_SECOND": _, m, s := t.Clock() return int64(m*100 + s), nil case "HOUR_MICROSECOND": h, m, s := t.Clock() return int64(h)*10000000000 + int64(m)*100000000 + int64(s)*1000000 + int64(t.Nanosecond())/1000, nil case "HOUR_SECOND": h, m, s := t.Clock() return int64(h)*10000 + int64(m)*100 + int64(s), nil case "HOUR_MINUTE": h, m, _ := t.Clock() return int64(h)*100 + int64(m), nil case "DAY_MICROSECOND": h, m, s := t.Clock() d := t.Day() return int64(d*1000000+h*10000+m*100+s)*1000000 + int64(t.Nanosecond())/1000, nil case "DAY_SECOND": h, m, s := t.Clock() d := t.Day() return int64(d)*1000000 + int64(h)*10000 + int64(m)*100 + int64(s), nil case "DAY_MINUTE": h, m, _ := t.Clock() d := t.Day() return int64(d)*10000 + int64(h)*100 + int64(m), nil case "DAY_HOUR": h, _, _ := t.Clock() d := t.Day() return int64(d)*100 + int64(h), nil case "YEAR_MONTH": y, m, _ := t.Date() return int64(y)*100 + int64(m), nil default: return 0, errors.Errorf("invalid unit %s", unit) } }
func dumpBinaryDateTime(t mysql.Time, loc *time.Location) (data []byte) { if t.Type == mysql.TypeTimestamp && loc != nil { t.Time = t.In(loc) } switch t.Type { case mysql.TypeTimestamp, mysql.TypeDatetime: data = append(data, 11) data = append(data, dumpUint16(uint16(t.Year()))...) //year data = append(data, byte(t.Month()), byte(t.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(t.Year()))...) //year data = append(data, byte(t.Month()), byte(t.Day())) } return }
// CastValue casts a value based on column's type. func (c *Col) CastValue(ctx context.Context, val interface{}) (casted interface{}, err error) { if val == nil { return } switch c.Tp { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeYear, mysql.TypeBit: intVal, errCode := c.normalizeIntegerValue(val) if errCode == errCodeType { casted = intVal err = c.TypeError(val) return } return c.castIntegerValue(intVal, errCode) case mysql.TypeFloat, mysql.TypeDouble: return c.castFloatValue(val) case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: switch v := val.(type) { case int64: casted, err = mysql.ParseTimeFromNum(v, c.Tp, c.Decimal) if err != nil { err = newParseColError(err, c) } case string: casted, err = mysql.ParseTime(v, c.Tp, c.Decimal) if err != nil { err = newParseColError(err, c) } case mysql.Time: var t mysql.Time t, err = v.Convert(c.Tp) if err != nil { err = newParseColError(err, c) return } casted, err = t.RoundFrac(c.Decimal) if err != nil { err = newParseColError(err, c) } default: err = c.TypeError(val) } case mysql.TypeDuration: switch v := val.(type) { case string: casted, err = mysql.ParseDuration(v, c.Decimal) if err != nil { err = newParseColError(err, c) } case mysql.Time: var t mysql.Duration t, err = v.ConvertToDuration() if err != nil { err = newParseColError(err, c) return } casted, err = t.RoundFrac(c.Decimal) if err != nil { err = newParseColError(err, c) } case mysql.Duration: casted, err = v.RoundFrac(c.Decimal) default: err = c.TypeError(val) } case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString: strV := "" switch v := val.(type) { case mysql.Time: strV = v.String() case mysql.Duration: strV = v.String() case []byte: if c.Charset == charset.CharsetBin { casted = v return } strV = string(v) default: strV = fmt.Sprintf("%v", val) } if (c.Flen != types.UnspecifiedLength) && (len(strV) > c.Flen) { strV = strV[:c.Flen] } casted = strV case mysql.TypeDecimal, mysql.TypeNewDecimal: switch v := val.(type) { case string: casted, err = mysql.ParseDecimal(v) if err != nil { err = newParseColError(err, c) } case int8: casted = mysql.NewDecimalFromInt(int64(v), 0) case int16: casted = mysql.NewDecimalFromInt(int64(v), 0) case int32: casted = mysql.NewDecimalFromInt(int64(v), 0) case int64: casted = mysql.NewDecimalFromInt(int64(v), 0) case int: casted = mysql.NewDecimalFromInt(int64(v), 0) case uint8: casted = mysql.NewDecimalFromUint(uint64(v), 0) case uint16: casted = mysql.NewDecimalFromUint(uint64(v), 0) case uint32: casted = mysql.NewDecimalFromUint(uint64(v), 0) case uint64: casted = mysql.NewDecimalFromUint(uint64(v), 0) case uint: casted = mysql.NewDecimalFromUint(uint64(v), 0) case float32: casted = mysql.NewDecimalFromFloat(float64(v)) case float64: casted = mysql.NewDecimalFromFloat(float64(v)) case mysql.Decimal: casted = v } default: err = c.TypeError(val) } return }