Skip to content

Commit

Permalink
types: fix datetime lower part overflow check (#19822)
Browse files Browse the repository at this point in the history
  • Loading branch information
9547 authored Sep 22, 2020
1 parent 151ef84 commit 462927b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 35 deletions.
41 changes: 11 additions & 30 deletions expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -2852,7 +2852,10 @@ func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, int
if err := handleInvalidTimeError(ctx, err); err != nil {
return types.ZeroTime, true, err
}
return du.addDate(ctx, date, year, month, day, nano)
}

func (du *baseDateArithmitical) addDate(ctx sessionctx.Context, date types.Time, year, month, day, nano int64) (types.Time, bool, error) {
goTime, err := date.GoTime(time.Local)
if err := handleInvalidTimeError(ctx, err); err != nil {
return types.ZeroTime, true, err
Expand All @@ -2867,6 +2870,13 @@ func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, int
date.SetFsp(6)
}

// fix https://github.com/pingcap/tidb/issues/11329
if goTime.Year() == 0 {
hour, minute, second := goTime.Clock()
date.SetCoreTime(types.FromDate(0, 0, 0, hour, minute, second, goTime.Nanosecond()/1000))
return date, false, nil
}

if goTime.Year() < 0 || goTime.Year() > 9999 {
return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime"))
}
Expand Down Expand Up @@ -2911,36 +2921,7 @@ func (du *baseDateArithmitical) sub(ctx sessionctx.Context, date types.Time, int
if err := handleInvalidTimeError(ctx, err); err != nil {
return types.ZeroTime, true, err
}
year, month, day, nano = -year, -month, -day, -nano

goTime, err := date.GoTime(time.Local)
if err := handleInvalidTimeError(ctx, err); err != nil {
return types.ZeroTime, true, err
}

duration := time.Duration(nano)
goTime = goTime.Add(duration)
goTime = types.AddDate(year, month, day, goTime)

if goTime.Nanosecond() == 0 {
date.SetFsp(0)
} else {
date.SetFsp(6)
}

if goTime.Year() < 0 || goTime.Year() > 9999 {
return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime"))
}

date.SetCoreTime(types.FromGoTime(goTime))
overflow, err := types.DateTimeIsOverflow(ctx.GetSessionVars().StmtCtx, date)
if err := handleInvalidTimeError(ctx, err); err != nil {
return types.ZeroTime, true, err
}
if overflow {
return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime"))
}
return date, false, nil
return du.addDate(ctx, date, -year, -month, -day, -nano)
}

func (du *baseDateArithmitical) vecGetDateFromInt(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.Column) error {
Expand Down
18 changes: 15 additions & 3 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2220,10 +2220,7 @@ func (s *testIntegrationSuite) TestDatetimeOverflow(c *C) {
"insert into t1 (d) select date_add('2000-01-01',interval 8000 year)",
"insert into t1 (d) select date_sub('2000-01-01', INTERVAL 2001 YEAR)",
"insert into t1 (d) select date_add('9999-12-31',interval 1 year)",
"insert into t1 (d) select date_sub('1000-01-01', INTERVAL 1 YEAR)",
"insert into t1 (d) select date_add('9999-12-31',interval 1 day)",
"insert into t1 (d) select date_sub('1000-01-01', INTERVAL 1 day)",
"insert into t1 (d) select date_sub('1000-01-01', INTERVAL 1 second)",
}

for _, sql := range overflowSQLs {
Expand Down Expand Up @@ -7366,3 +7363,18 @@ func (s *testIntegrationSuite) TestIssue17476(c *C) {
tk.MustQuery(`SELECT count(*) FROM (table_float JOIN table_int_float_varchar AS tmp3 ON (tmp3.col_varchar_6 AND NULL) IS NULL);`).Check(testkit.Rows("154"))
tk.MustQuery(`SELECT * FROM (table_int_float_varchar AS tmp3) WHERE (col_varchar_6 AND NULL) IS NULL AND col_int_6=0;`).Check(testkit.Rows("13 0 -0.1 <nil>"))
}

func (s *testIntegrationSuite) TestIssue11645(c *C) {
defer s.cleanEnv(c)
tk := testkit.NewTestKit(c, s.store)
tk.MustQuery(`SELECT DATE_ADD('1000-01-01 00:00:00', INTERVAL -2 HOUR);`).Check(testkit.Rows("0999-12-31 22:00:00"))
tk.MustQuery(`SELECT DATE_ADD('1000-01-01 00:00:00', INTERVAL -200 HOUR);`).Check(testkit.Rows("0999-12-23 16:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-01 00:00:00', INTERVAL -2 HOUR);`).Check(testkit.Rows("0000-00-00 22:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-01 00:00:00', INTERVAL -25 HOUR);`).Check(testkit.Rows("0000-00-00 23:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-01 00:00:00', INTERVAL -8784 HOUR);`).Check(testkit.Rows("0000-00-00 00:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-01 00:00:00', INTERVAL -8785 HOUR);`).Check(testkit.Rows("<nil>"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-02 00:00:00', INTERVAL -2 HOUR);`).Check(testkit.Rows("0001-01-01 22:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-02 00:00:00', INTERVAL -24 HOUR);`).Check(testkit.Rows("0001-01-01 00:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-02 00:00:00', INTERVAL -25 HOUR);`).Check(testkit.Rows("0000-00-00 23:00:00"))
tk.MustQuery(`SELECT DATE_ADD('0001-01-02 00:00:00', INTERVAL -8785 HOUR);`).Check(testkit.Rows("0000-00-00 23:00:00"))
}
4 changes: 2 additions & 2 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ var (
)

var (
// MinDatetime is the minimum for mysql datetime type.
MinDatetime = FromDate(1000, 1, 1, 0, 0, 0, 0)
// MinDatetime is the minimum for Golang Time type.
MinDatetime = FromDate(1, 1, 1, 0, 0, 0, 0)
// MaxDatetime is the maximum for mysql datetime type.
MaxDatetime = FromDate(9999, 12, 31, 23, 59, 59, 999999)

Expand Down
5 changes: 5 additions & 0 deletions types/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,11 @@ func (s *testTimeSuite) TestTimeOverflow(c *C) {
{"2018.01.01", false},
{"2018.01.01 00:00:00", false},
{"2018/01/01-00:00:00", false},
{"0999-12-31 22:00:00", false},
{"9999-12-31 23:59:59", false},
{"0001-01-01 00:00:00", false},
{"0001-01-01 23:59:59", false},
{"0000-01-01 00:00:00", true},
}

for _, test := range table {
Expand Down

0 comments on commit 462927b

Please sign in to comment.