Skip to content

Commit

Permalink
expression: fix TIMESTAMP func get wrong result with decimal (pingcap…
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-srebot authored Nov 11, 2020
1 parent d47252a commit b157b89
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 8 deletions.
2 changes: 1 addition & 1 deletion expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -4397,7 +4397,7 @@ func (c *timestampFunctionClass) getFunction(ctx sessionctx.Context, args []Expr
}
isFloat := false
switch args[0].GetType().Tp {
case mysql.TypeFloat, mysql.TypeDouble, mysql.TypeDecimal:
case mysql.TypeFloat, mysql.TypeDouble, mysql.TypeNewDecimal, mysql.TypeLonglong:
isFloat = true
}
bf := newBaseBuiltinFuncWithTp(ctx, 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 @@ -2065,6 +2065,44 @@ func (s *testIntegrationSuite) 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
28 changes: 23 additions & 5 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,29 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bo
switch len(seps) {
case 1:
l := len(seps[0])
// Values specified as numbers
if isFloat {
numOfTime, err := StrToInt(sc, seps[0])
if err != nil {
return ZeroDatetime, errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(str))
}

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

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

break
}

// Values specified as strings
switch l {
case 14: // No delimiter.
// YYYYMMDDHHMMSS
Expand Down Expand Up @@ -1322,11 +1345,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(ErrInvalidTimeFormat.GenWithStackByArgs(num))
}

// 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 @@ -609,7 +609,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 @@ -739,6 +739,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, (int)(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 @@ -1015,7 +1048,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.MysqlTime
Expand Down

0 comments on commit b157b89

Please sign in to comment.