Skip to content

Commit

Permalink
expression: fix decimal of function FROM_UNIXTIME (#14936) (#15270)
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot authored Mar 12, 2020
1 parent 051a873 commit bf82a71
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 34 deletions.
23 changes: 4 additions & 19 deletions expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,6 @@ func (c *fromUnixTimeFunctionClass) getFunction(ctx sessionctx.Context, args []E
argTps = append(argTps, types.ETString)
}

_, isArg0Con := args[0].(*Constant)
isArg0Str := args[0].GetType().EvalType() == types.ETString
bf := newBaseBuiltinFuncWithTp(ctx, args, retTp, argTps...)

Expand All @@ -1583,19 +1582,10 @@ func (c *fromUnixTimeFunctionClass) getFunction(ctx sessionctx.Context, args []E
}

// Calculate the time fsp.
switch {
case isArg0Str:
bf.tp.Decimal = int(types.MaxFsp)
case isArg0Con:
arg0, arg0IsNull, err0 := args[0].EvalDecimal(ctx, chunk.Row{})
if err0 != nil {
return nil, err0
}

bf.tp.Decimal = int(types.MaxFsp)
if !arg0IsNull {
fsp := int(arg0.GetDigitsFrac())
bf.tp.Decimal = mathutil.Min(fsp, int(types.MaxFsp))
bf.tp.Decimal = int(types.MaxFsp)
if !isArg0Str {
if args[0].GetType().Decimal != types.UnspecifiedLength {
bf.tp.Decimal = mathutil.Min(bf.tp.Decimal, args[0].GetType().Decimal)
}
}

Expand Down Expand Up @@ -1638,14 +1628,9 @@ func evalFromUnixTime(ctx sessionctx.Context, fsp int, row chunk.Row, arg Expres
if err != nil && !terror.ErrorEqual(err, types.ErrTruncated) {
return res, true, err
}
fracDigitsNumber := int(unixTimeStamp.GetDigitsFrac())
if fsp < 0 {
fsp = types.MaxFsp
}
fsp = mathutil.Max(fracDigitsNumber, fsp)
if fsp > types.MaxFsp {
fsp = types.MaxFsp
}

sc := ctx.GetSessionVars().StmtCtx
tmp := time.Unix(integralPart, fractionalPart).In(sc.TimeZone)
Expand Down
39 changes: 24 additions & 15 deletions expression/builtin_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1150,16 +1150,16 @@ func (s *testEvaluatorSuite) TestFromUnixTime(c *C) {
fractionalPart int64
decimal float64
format string
ansLen int
expect string
}{
{false, 1451606400, 0, 0, "", 19},
{true, 1451606400, 123456000, 1451606400.123456, "", 26},
{true, 1451606400, 999999000, 1451606400.999999, "", 26},
{true, 1451606400, 999999900, 1451606400.9999999, "", 19},
{false, 1451606400, 0, 0, `%Y %D %M %h:%i:%s %x`, 19},
{true, 1451606400, 123456000, 1451606400.123456, `%Y %D %M %h:%i:%s %x`, 26},
{true, 1451606400, 999999000, 1451606400.999999, `%Y %D %M %h:%i:%s %x`, 26},
{true, 1451606400, 999999900, 1451606400.9999999, `%Y %D %M %h:%i:%s %x`, 19},
{false, 1451606400, 0, 0, "", "2016-01-01 08:00:00"},
{true, 1451606400, 123456000, 1451606400.123456, "", "2016-01-01 08:00:00.123456"},
{true, 1451606400, 999999000, 1451606400.999999, "", "2016-01-01 08:00:00.999999"},
{true, 1451606400, 999999900, 1451606400.9999999, "", "2016-01-01 08:00:01.000000"},
{false, 1451606400, 0, 0, `%Y %D %M %h:%i:%s %x`, "2016-01-01 08:00:00"},
{true, 1451606400, 123456000, 1451606400.123456, `%Y %D %M %h:%i:%s %x`, "2016-01-01 08:00:00.123456"},
{true, 1451606400, 999999000, 1451606400.999999, `%Y %D %M %h:%i:%s %x`, "2016-01-01 08:00:00.999999"},
{true, 1451606400, 999999900, 1451606400.9999999, `%Y %D %M %h:%i:%s %x`, "2016-01-01 08:00:01.000000"},
}
sc := s.ctx.GetSessionVars().StmtCtx
originTZ := sc.TimeZone
Expand All @@ -1176,23 +1176,32 @@ func (s *testEvaluatorSuite) TestFromUnixTime(c *C) {
timestamp.SetFloat64(t.decimal)
}
// result of from_unixtime() is dependent on specific time zone.
unixTime := time.Unix(t.integralPart, t.fractionalPart).Round(time.Microsecond).String()[:t.ansLen]
if len(t.format) == 0 {
f, err := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{timestamp}))
constants := s.datumsToConstants([]types.Datum{timestamp})
if !t.isDecimal {
constants[0].GetType().Decimal = 0
}

f, err := fc.getFunction(s.ctx, constants)
c.Assert(err, IsNil)

v, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
ans := v.GetMysqlTime()
c.Assert(ans.String(), Equals, unixTime)
c.Assert(ans.String(), Equals, t.expect, Commentf("%+v", t))
} else {
format := types.NewStringDatum(t.format)
f, err := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{timestamp, format}))
constants := s.datumsToConstants([]types.Datum{timestamp, format})
if !t.isDecimal {
constants[0].GetType().Decimal = 0
}
f, err := fc.getFunction(s.ctx, constants)
c.Assert(err, IsNil)
v, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
result, err := builtinDateFormat(s.ctx, []types.Datum{types.NewStringDatum(unixTime), format})
result, err := builtinDateFormat(s.ctx, []types.Datum{types.NewStringDatum(t.expect), format})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, result.GetString())
c.Assert(v.GetString(), Equals, result.GetString(), Commentf("%+v", t))
}
}

Expand Down
16 changes: 16 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2474,6 +2474,14 @@ func (s *testIntegrationSuite) TestBuiltin(c *C) {
result = tk.MustQuery("select from_unixtime(1451606400)")
unixTime := time.Unix(1451606400, 0).String()[:19]
result.Check(testkit.Rows(unixTime))
result = tk.MustQuery("select from_unixtime(14516064000/10)")
result.Check(testkit.Rows("2016-01-01 08:00:00.0000"))
result = tk.MustQuery("select from_unixtime('14516064000'/10)")
result.Check(testkit.Rows("2016-01-01 08:00:00.000000"))
result = tk.MustQuery("select from_unixtime(cast(1451606400 as DECIMAL))")
result.Check(testkit.Rows("2016-01-01 08:00:00"))
result = tk.MustQuery("select from_unixtime(cast(1451606400 as DECIMAL(65,1)))")
result.Check(testkit.Rows("2016-01-01 08:00:00.0"))
result = tk.MustQuery("select from_unixtime(1451606400.123456)")
unixTime = time.Unix(1451606400, 123456000).String()[:26]
result.Check(testkit.Rows(unixTime))
Expand All @@ -2485,6 +2493,14 @@ func (s *testIntegrationSuite) TestBuiltin(c *C) {
result.Check(testkit.Rows(unixTime))
result = tk.MustQuery("select from_unixtime(1511247196661)")
result.Check(testkit.Rows("<nil>"))
result = tk.MustQuery("select from_unixtime('1451606400.123');")
result.Check(testkit.Rows("2016-01-01 08:00:00.123000"))

tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int);")
tk.MustExec("insert into t value(1451606400);")
result = tk.MustQuery("select from_unixtime(a) from t;")
result.Check(testkit.Rows("2016-01-01 08:00:00"))

// test strcmp
result = tk.MustQuery("select strcmp('abc', 'def')")
Expand Down

0 comments on commit bf82a71

Please sign in to comment.