diff --git a/expression/builtin_time.go b/expression/builtin_time.go index 84c7f6ee8ad36..c099b65519dcf 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -2330,5 +2330,19 @@ type builtinUTCTimeSig struct { // eval evals a builtinUTCTimeSig. // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-time func (b *builtinUTCTimeSig) eval(row []types.Datum) (d types.Datum, err error) { - return d, errFunctionNotExists.GenByArgs("UTC_TIME") + const utctimeFormat = "15:04:05.000000" + args, err := b.evalArgs(row) + if err != nil { + return types.Datum{}, errors.Trace(err) + } + fsp := 0 + sc := b.ctx.GetSessionVars().StmtCtx + if len(args) == 1 && !args[0].IsNull() { + if fsp, err = checkFsp(sc, args[0]); err != nil { + d.SetNull() + return d, errors.Trace(err) + } + } + d.SetString(time.Now().UTC().Format(utctimeFormat)) + return convertToDuration(b.ctx.GetSessionVars().StmtCtx, d, fsp) } diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index e09cd5dc0f3a6..b0e99baa16804 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -611,6 +611,33 @@ func (s *testEvaluatorSuite) TestCurrentTime(c *C) { c.Assert(err, NotNil) } +func (s *testEvaluatorSuite) TestUTCTime(c *C) { + defer testleak.AfterTest(c)() + + tfStr := "15:04:05" + last := time.Now().UTC() + fc := funcs[ast.UTCTime] + + tests := []struct { + param interface{} + expect int + }{{nil, 8}, {0, 8}, {3, 12}, {6, 15}, {-1, 0}, {7, 0}} + + for _, test := range tests { + f, err := fc.getFunction(datumsToConstants(types.MakeDatums(test.param)), s.ctx) + c.Assert(err, IsNil) + v, err := f.eval(nil) + if test.expect > 0 { + c.Assert(err, IsNil) + n := v.GetMysqlDuration() + c.Assert(n.String(), HasLen, test.expect) + c.Assert(n.String(), GreaterEqual, last.Format(tfStr)) + } else { + c.Assert(err, NotNil) + } + } +} + func (s *testEvaluatorSuite) TestUTCDate(c *C) { defer testleak.AfterTest(c)() last := time.Now().UTC() diff --git a/plan/typeinferer.go b/plan/typeinferer.go index ff4f3d357bf75..4937232e6d2a6 100644 --- a/plan/typeinferer.go +++ b/plan/typeinferer.go @@ -381,7 +381,7 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) { tp = types.NewFieldType(mysql.TypeLonglong) tp.Flag |= mysql.UnsignedFlag // time related - case ast.Curtime, ast.CurrentTime, ast.TimeDiff, ast.MakeTime, ast.SecToTime: + case ast.Curtime, ast.CurrentTime, ast.TimeDiff, ast.MakeTime, ast.SecToTime, ast.UTCTime: tp = types.NewFieldType(mysql.TypeDuration) tp.Decimal = v.getFsp(x) case ast.Curdate, ast.CurrentDate, ast.Date, ast.FromDays, ast.MakeDate: diff --git a/plan/typeinferer_test.go b/plan/typeinferer_test.go index 7625d9bcdb7b9..2e948fbe0cbb9 100644 --- a/plan/typeinferer_test.go +++ b/plan/typeinferer_test.go @@ -158,6 +158,8 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) { {"maketime(12, 15, 30)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag}, {"sec_to_time(2378)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag}, {"current_timestamp()", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag}, + {"utc_time()", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag}, + {"utc_time(3)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag}, {"utc_timestamp()", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag}, {"microsecond('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag}, {"second('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag},