From a38fb749a99dd09a560e60da9d6e508b7fa78635 Mon Sep 17 00:00:00 2001 From: AndrewDi Date: Fri, 26 Jul 2019 22:23:47 +0800 Subject: [PATCH 1/2] fix date_add/date_sub function issue --- expression/builtin_time.go | 8 ++++++++ expression/builtin_time_test.go | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/expression/builtin_time.go b/expression/builtin_time.go index c0ea24fcb7541..32626985eb255 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -2744,6 +2744,10 @@ func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, int date.Fsp = 6 } + if goTime.Year() < 0 || goTime.Year() > (1<<16-1) { + return types.Time{}, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) + } + date.Time = types.FromGoTime(goTime) overflow, err := types.DateTimeIsOverflow(ctx.GetSessionVars().StmtCtx, date) if err := handleInvalidTimeError(ctx, err); err != nil { @@ -2779,6 +2783,10 @@ func (du *baseDateArithmitical) sub(ctx sessionctx.Context, date types.Time, int return types.Time{}, true, err } + if goTime.Year() < 0 || goTime.Year() > (1<<16-1) { + return types.Time{}, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) + } + duration := time.Duration(nano) goTime = goTime.Add(duration) goTime = types.AddDate(year, month, day, goTime) diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index 23e2858feef15..97c96ec2049f1 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -1762,6 +1762,25 @@ func (s *testEvaluatorSuite) TestDateArithFuncs(c *C) { c.Assert(err, IsNil) c.Assert(v.GetMysqlTime().String(), Equals, test.expected) } + + testOverflowYears := []struct { + input string + year int + }{ + {"2008-11-23", -1465647104}, + {"2008-11-23", 1465647104}, + } + + for _, test := range testOverflowYears { + args = types.MakeDatums(test.input, test.year, "YEAR") + f, err = fcAdd.getFunction(s.ctx, s.datumsToConstants(args)) + c.Assert(err, IsNil) + c.Assert(f, NotNil) + v, err = evalBuiltinFunc(f, chunk.Row{}) + c.Assert(err, IsNil) + c.Assert(v.IsNull(), IsTrue) + } + testDurations := []struct { dur string fsp int From b324a2727ac221179ad2db9c76a61810e8959154 Mon Sep 17 00:00:00 2001 From: AndrewDi Date: Sat, 27 Jul 2019 16:57:11 +0800 Subject: [PATCH 2/2] add integration test --- expression/builtin_time.go | 8 ++++---- expression/builtin_time_test.go | 10 ++++++++++ expression/integration_test.go | 6 ++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/expression/builtin_time.go b/expression/builtin_time.go index 32626985eb255..65ac3cf311cbf 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -2783,10 +2783,6 @@ func (du *baseDateArithmitical) sub(ctx sessionctx.Context, date types.Time, int return types.Time{}, true, err } - if goTime.Year() < 0 || goTime.Year() > (1<<16-1) { - return types.Time{}, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) - } - duration := time.Duration(nano) goTime = goTime.Add(duration) goTime = types.AddDate(year, month, day, goTime) @@ -2797,6 +2793,10 @@ func (du *baseDateArithmitical) sub(ctx sessionctx.Context, date types.Time, int date.Fsp = 6 } + if goTime.Year() < 0 || goTime.Year() > (1<<16-1) { + return types.Time{}, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) + } + date.Time = types.FromGoTime(goTime) overflow, err := types.DateTimeIsOverflow(ctx.GetSessionVars().StmtCtx, date) if err := handleInvalidTimeError(ctx, err); err != nil { diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index 97c96ec2049f1..aa4064c6a5797 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -1781,6 +1781,16 @@ func (s *testEvaluatorSuite) TestDateArithFuncs(c *C) { c.Assert(v.IsNull(), IsTrue) } + for _, test := range testOverflowYears { + args = types.MakeDatums(test.input, test.year, "YEAR") + f, err = fcSub.getFunction(s.ctx, s.datumsToConstants(args)) + c.Assert(err, IsNil) + c.Assert(f, NotNil) + v, err = evalBuiltinFunc(f, chunk.Row{}) + c.Assert(err, IsNil) + c.Assert(v.IsNull(), IsTrue) + } + testDurations := []struct { dur string fsp int diff --git a/expression/integration_test.go b/expression/integration_test.go index 2be144299678b..f1d88eeaa0a49 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -1966,6 +1966,12 @@ func (s *testIntegrationSuite) TestDatetimeOverflow(c *C) { rows = append(rows, "") } tk.MustQuery("select * from t1").Check(testkit.Rows(rows...)) + + //Fix ISSUE 11256 + tk.MustQuery(`select DATE_ADD('2000-04-13 07:17:02',INTERVAL -1465647104 YEAR);`).Check(testkit.Rows("")) + tk.MustQuery(`select DATE_ADD('2008-11-23 22:47:31',INTERVAL 266076160 QUARTER);`).Check(testkit.Rows("")) + tk.MustQuery(`select DATE_SUB('2000-04-13 07:17:02',INTERVAL 1465647104 YEAR);`).Check(testkit.Rows("")) + tk.MustQuery(`select DATE_SUB('2008-11-23 22:47:31',INTERVAL -266076160 QUARTER);`).Check(testkit.Rows("")) } func (s *testIntegrationSuite) TestBuiltin(c *C) {