// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_extract func builtinExtract(args []types.Datum, _ context.Context) (d types.Datum, err error) { unit := args[0].GetString() vd := args[1] if vd.Kind() == types.KindNull { d.SetNull() return d, nil } f := types.NewFieldType(mysql.TypeDatetime) f.Decimal = mysql.MaxFsp val, err := vd.ConvertTo(f) if err != nil { d.SetNull() return d, errors.Trace(err) } if val.Kind() == types.KindNull { d.SetNull() return d, nil } if val.Kind() != types.KindMysqlTime { err = errors.Errorf("need time type, but got %T", val) d.SetNull() return d, err } t := val.GetMysqlTime() n, err1 := mysql.ExtractTimeNum(unit, t) if err1 != nil { d.SetNull() return d, errors.Trace(err1) } d.SetInt64(n) return d, nil }
func (e *Evaluator) funcExtract(v *ast.FuncExtractExpr) bool { val := v.Date.GetValue() if val == nil { v.SetValue(nil) return true } f := types.NewFieldType(mysql.TypeDatetime) f.Decimal = mysql.MaxFsp var err error val, err = types.Convert(val, f) if err != nil { e.err = errors.Trace(err) return false } if val == nil { v.SetValue(nil) return true } t, ok := val.(mysql.Time) if !ok { e.err = ErrInvalidOperation.Gen("need time type, but got %T", val) return false } n, err1 := mysql.ExtractTimeNum(v.Unit, t) if err1 != nil { e.err = errors.Trace(err1) return false } v.SetValue(n) return true }
// Eval implements the Expression Eval interface. func (e *Extract) Eval(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) { v, err := e.Date.Eval(ctx, args) if v == nil || err != nil { return nil, errors.Trace(err) } f := types.NewFieldType(mysql.TypeDatetime) f.Decimal = mysql.MaxFsp v, err = types.Convert(v, f) if v == nil || err != nil { return nil, errors.Trace(err) } t, ok := v.(mysql.Time) if !ok { return nil, errors.Errorf("need time type, but got %T", v) } n, err1 := mysql.ExtractTimeNum(e.Unit, t) if err1 != nil { return nil, errors.Trace(err1) } return n, nil }