Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression: fix TIMESTAMP func get wrong result with decimal (#15185) #20088

Merged
merged 5 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -4851,7 +4851,7 @@ func (c *timestampFunctionClass) getFunction(ctx sessionctx.Context, args []Expr
}
isFloat := false
switch args[0].GetType().Tp {
case mysql.TypeFloat, mysql.TypeDouble, mysql.TypeNewDecimal:
case mysql.TypeFloat, mysql.TypeDouble, mysql.TypeNewDecimal, mysql.TypeLonglong:
isFloat = true
}
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, evalTps...)
Expand Down
38 changes: 38 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,44 @@ func (s *testIntegrationSuite2) TestTimeBuiltin(c *C) {
result = tk.MustQuery("select time(\"-- --1\");")
result.Check(testkit.Rows("00:00:00"))
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1292 Truncated incorrect time value: '-- --1'"))

// fix issue #15185
result = tk.MustQuery(`select timestamp(11111.1111)`)
result.Check(testkit.Rows("2001-11-11 00:00:00.0000"))
result = tk.MustQuery(`select timestamp(cast(11111.1111 as decimal(60, 5)))`)
result.Check(testkit.Rows("2001-11-11 00:00:00.00000"))
result = tk.MustQuery(`select timestamp(1021121141105.4324)`)
result.Check(testkit.Rows("0102-11-21 14:11:05.4324"))
result = tk.MustQuery(`select timestamp(cast(1021121141105.4324 as decimal(60, 5)))`)
result.Check(testkit.Rows("0102-11-21 14:11:05.43240"))
result = tk.MustQuery(`select timestamp(21121141105.101)`)
result.Check(testkit.Rows("2002-11-21 14:11:05.101"))
result = tk.MustQuery(`select timestamp(cast(21121141105.101 as decimal(60, 5)))`)
result.Check(testkit.Rows("2002-11-21 14:11:05.10100"))
result = tk.MustQuery(`select timestamp(1121141105.799055)`)
result.Check(testkit.Rows("2000-11-21 14:11:05.799055"))
result = tk.MustQuery(`select timestamp(cast(1121141105.799055 as decimal(60, 5)))`)
result.Check(testkit.Rows("2000-11-21 14:11:05.79906"))
result = tk.MustQuery(`select timestamp(121141105.123)`)
result.Check(testkit.Rows("2000-01-21 14:11:05.123"))
result = tk.MustQuery(`select timestamp(cast(121141105.123 as decimal(60, 5)))`)
result.Check(testkit.Rows("2000-01-21 14:11:05.12300"))
result = tk.MustQuery(`select timestamp(1141105)`)
result.Check(testkit.Rows("0114-11-05 00:00:00"))
result = tk.MustQuery(`select timestamp(cast(1141105 as decimal(60, 5)))`)
result.Check(testkit.Rows("0114-11-05 00:00:00.00000"))
result = tk.MustQuery(`select timestamp(41105.11)`)
result.Check(testkit.Rows("2004-11-05 00:00:00.00"))
result = tk.MustQuery(`select timestamp(cast(41105.11 as decimal(60, 5)))`)
result.Check(testkit.Rows("2004-11-05 00:00:00.00000"))
result = tk.MustQuery(`select timestamp(1105.3)`)
result.Check(testkit.Rows("2000-11-05 00:00:00.0"))
result = tk.MustQuery(`select timestamp(cast(1105.3 as decimal(60, 5)))`)
result.Check(testkit.Rows("2000-11-05 00:00:00.00000"))
result = tk.MustQuery(`select timestamp(105)`)
result.Check(testkit.Rows("2000-01-05 00:00:00"))
result = tk.MustQuery(`select timestamp(cast(105 as decimal(60, 5)))`)
result.Check(testkit.Rows("2000-01-05 00:00:00.00000"))
}

func (s *testIntegrationSuite) TestOpBuiltin(c *C) {
Expand Down
27 changes: 22 additions & 5 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,28 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int8, isFloat b
switch len(seps) {
case 1:
l := len(seps[0])
// Values specified as numbers
if isFloat {
numOfTime, err := StrToInt(sc, seps[0], false)
if err != nil {
return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(DateTimeStr, str))
}

dateTime, err := ParseDatetimeFromNum(sc, numOfTime)
if err != nil {
return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(DateTimeStr, str))
}

year, month, day, hour, minute, second =
dateTime.Year(), dateTime.Month(), dateTime.Day(), dateTime.Hour(), dateTime.Minute(), dateTime.Second()
if l >= 9 && l <= 14 {
hhmmss = true
}

break
}

// Values specified as strings
switch l {
case 14: // No delimiter.
// YYYYMMDDHHMMSS
Expand Down Expand Up @@ -1613,11 +1635,6 @@ func parseDateTimeFromNum(sc *stmtctx.StatementContext, num int64) (Time, error)
return getTime(sc, num, t.Type())
}

// Check YYYYMMDD.
if num < 10000101 {
return t, errors.Trace(ErrWrongValue.GenWithStackByArgs(TimeStr, strconv.FormatInt(num, 10)))
}

// Adjust hour/min/second.
if num <= 99991231 {
num = num * 1000000
Expand Down
37 changes: 35 additions & 2 deletions types/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ func (s *testTimeSuite) TestParseTimeFromNum(c *C) {
{2010101011, true, types.ZeroDatetimeStr, true, types.ZeroDatetimeStr, true, types.ZeroDateStr},
{201010101, false, "2000-02-01 01:01:01", false, "2000-02-01 01:01:01", false, "2000-02-01"},
{20101010, false, "2010-10-10 00:00:00", false, "2010-10-10 00:00:00", false, "2010-10-10"},
{2010101, true, types.ZeroDatetimeStr, true, types.ZeroDatetimeStr, true, types.ZeroDateStr},
{2010101, false, "0201-01-01 00:00:00", true, types.ZeroDatetimeStr, false, "0201-01-01"},
{201010, false, "2020-10-10 00:00:00", false, "2020-10-10 00:00:00", false, "2020-10-10"},
{20101, false, "2002-01-01 00:00:00", false, "2002-01-01 00:00:00", false, "2002-01-01"},
{2010, true, types.ZeroDatetimeStr, true, types.ZeroDatetimeStr, true, types.ZeroDateStr},
Expand Down Expand Up @@ -747,6 +747,39 @@ func (s *testTimeSuite) TestToNumber(c *C) {
}
}

func (s *testTimeSuite) TestParseTimeFromFloatString(c *C) {
sc := mock.NewContext().GetSessionVars().StmtCtx
sc.IgnoreZeroInDate = true
defer testleak.AfterTest(c)()
table := []struct {
Input string
Fsp int8
ExpectError bool
Expect string
}{
{"20170118.123", 3, false, "2017-01-18 00:00:00.000"},
{"121231113045.123345", 6, false, "2012-12-31 11:30:45.123345"},
{"20121231113045.123345", 6, false, "2012-12-31 11:30:45.123345"},
{"121231113045.9999999", 6, false, "2012-12-31 11:30:46.000000"},
{"170105084059.575601", 6, false, "2017-01-05 08:40:59.575601"},
{"201705051315111.22", 2, true, "0000-00-00 00:00:00.00"},
{"2011110859.1111", 4, true, "0000-00-00 00:00:00.0000"},
{"2011110859.1111", 4, true, "0000-00-00 00:00:00.0000"},
{"191203081.1111", 4, true, "0000-00-00 00:00:00.0000"},
{"43128.121105", 6, true, "0000-00-00 00:00:00.000000"},
}

for _, test := range table {
t, err := types.ParseTimeFromFloatString(sc, test.Input, mysql.TypeDatetime, test.Fsp)
if test.ExpectError {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
c.Assert(t.String(), Equals, test.Expect)
}
}
}

func (s *testTimeSuite) TestParseFrac(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
Expand Down Expand Up @@ -1027,7 +1060,7 @@ func (s *testTimeSuite) TestParseDateFormat(c *C) {
}
}

func (s *testTimeSuite) TestTamestampDiff(c *C) {
func (s *testTimeSuite) TestTimestampDiff(c *C) {
tests := []struct {
unit string
t1 types.CoreTime
Expand Down