From 29ecd9da1d7e77d852499fec0464a5d32bedc48f Mon Sep 17 00:00:00 2001 From: kanchairen Date: Wed, 10 Jul 2019 19:28:27 +0800 Subject: [PATCH] CONVERT_TZ should return NULL if its arguments are invalid. (#11161) --- expression/builtin_time.go | 19 ++++++++++--------- expression/builtin_time_test.go | 19 ++++++++++++++----- expression/integration_test.go | 13 ++++++++++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/expression/builtin_time.go b/expression/builtin_time.go index 52954e7aeb16f..ee2390e05745a 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -5101,21 +5101,22 @@ func (b *builtinConvertTzSig) Clone() builtinFunc { } // evalTime evals CONVERT_TZ(dt,from_tz,to_tz). +// `CONVERT_TZ` function returns NULL if the arguments are invalid. // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_convert-tz func (b *builtinConvertTzSig) evalTime(row chunk.Row) (types.Time, bool, error) { dt, isNull, err := b.args[0].EvalTime(b.ctx, row) if isNull || err != nil { - return types.Time{}, true, err + return types.Time{}, true, nil } fromTzStr, isNull, err := b.args[1].EvalString(b.ctx, row) - if isNull || err != nil { - return types.Time{}, true, err + if isNull || err != nil || fromTzStr == "" { + return types.Time{}, true, nil } toTzStr, isNull, err := b.args[2].EvalString(b.ctx, row) - if isNull || err != nil { - return types.Time{}, true, err + if isNull || err != nil || toTzStr == "" { + return types.Time{}, true, nil } fromTzMatched := b.timezoneRegex.MatchString(fromTzStr) @@ -5124,17 +5125,17 @@ func (b *builtinConvertTzSig) evalTime(row chunk.Row) (types.Time, bool, error) if !fromTzMatched && !toTzMatched { fromTz, err := time.LoadLocation(fromTzStr) if err != nil { - return types.Time{}, true, err + return types.Time{}, true, nil } toTz, err := time.LoadLocation(toTzStr) if err != nil { - return types.Time{}, true, err + return types.Time{}, true, nil } t, err := dt.Time.GoTime(fromTz) if err != nil { - return types.Time{}, true, err + return types.Time{}, true, nil } return types.Time{ @@ -5146,7 +5147,7 @@ func (b *builtinConvertTzSig) evalTime(row chunk.Row) (types.Time, bool, error) if fromTzMatched && toTzMatched { t, err := dt.Time.GoTime(time.Local) if err != nil { - return types.Time{}, true, err + return types.Time{}, true, nil } return types.Time{ diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index 60dbbf504523b..4c570ffa15c6c 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -2437,8 +2437,8 @@ func (s *testEvaluatorSuite) TestSecToTime(c *C) { func (s *testEvaluatorSuite) TestConvertTz(c *C) { tests := []struct { t interface{} - fromTz string - toTz string + fromTz interface{} + toTz interface{} Success bool expect string }{ @@ -2450,11 +2450,20 @@ func (s *testEvaluatorSuite) TestConvertTz(c *C) { {"2004-01-01 12:00:00", "-00:00", "+13:00", true, "2004-01-02 01:00:00"}, {"2004-01-01 12:00:00", "-00:00", "-13:00", true, ""}, {"2004-01-01 12:00:00", "-00:00", "-12:88", true, ""}, - {"2004-01-01 12:00:00", "+10:82", "GMT", false, ""}, + {"2004-01-01 12:00:00", "+10:82", "GMT", true, ""}, {"2004-01-01 12:00:00", "+00:00", "GMT", true, ""}, {"2004-01-01 12:00:00", "GMT", "+00:00", true, ""}, {20040101, "+00:00", "+10:32", true, "2004-01-01 10:32:00"}, {3.14159, "+00:00", "+10:32", true, ""}, + {"2004-01-01 12:00:00", "", "GMT", true, ""}, + {"2004-01-01 12:00:00", "GMT", "", true, ""}, + {"2004-01-01 12:00:00", "a", "GMT", true, ""}, + {"2004-01-01 12:00:00", "0", "GMT", true, ""}, + {"2004-01-01 12:00:00", "GMT", "a", true, ""}, + {"2004-01-01 12:00:00", "GMT", "0", true, ""}, + {nil, "GMT", "+00:00", true, ""}, + {"2004-01-01 12:00:00", nil, "+00:00", true, ""}, + {"2004-01-01 12:00:00", "GMT", nil, true, ""}, } fc := funcs[ast.ConvertTz] for _, test := range tests { @@ -2462,8 +2471,8 @@ func (s *testEvaluatorSuite) TestConvertTz(c *C) { s.datumsToConstants( []types.Datum{ types.NewDatum(test.t), - types.NewStringDatum(test.fromTz), - types.NewStringDatum(test.toTz)})) + types.NewDatum(test.fromTz), + types.NewDatum(test.toTz)})) c.Assert(err, IsNil) d, err := evalBuiltinFunc(f, chunk.Row{}) if test.Success { diff --git a/expression/integration_test.go b/expression/integration_test.go index 36da17c5e4a2a..da5dc758dd85b 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -1790,9 +1790,16 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) { // for convert_tz result = tk.MustQuery(`select convert_tz("2004-01-01 12:00:00", "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00.01", "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00.01234567", "+00:00", "+10:32");`) result.Check(testkit.Rows("2004-01-01 22:32:00 2004-01-01 22:32:00.01 2004-01-01 22:32:00.012346")) - // TODO: release the following test after fix #4462 - //result = tk.MustQuery(`select convert_tz(20040101, "+00:00", "+10:32"), convert_tz(20040101.01, "+00:00", "+10:32"), convert_tz(20040101.01234567, "+00:00", "+10:32");`) - //result.Check(testkit.Rows("2004-01-01 10:32:00 2004-01-01 10:32:00.00 2004-01-01 10:32:00.000000")) + result = tk.MustQuery(`select convert_tz(20040101, "+00:00", "+10:32"), convert_tz(20040101.01, "+00:00", "+10:32"), convert_tz(20040101.01234567, "+00:00", "+10:32");`) + result.Check(testkit.Rows("2004-01-01 10:32:00 2004-01-01 10:32:00.00 2004-01-01 10:32:00.000000")) + result = tk.MustQuery(`select convert_tz(NULL, "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00", NULL, "+10:32"), convert_tz("2004-01-01 12:00:00", "+00:00", NULL);`) + result.Check(testkit.Rows(" ")) + result = tk.MustQuery(`select convert_tz("a", "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00", "a", "+10:32"), convert_tz("2004-01-01 12:00:00", "+00:00", "a");`) + result.Check(testkit.Rows(" ")) + result = tk.MustQuery(`select convert_tz("", "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00", "", "+10:32"), convert_tz("2004-01-01 12:00:00", "+00:00", "");`) + result.Check(testkit.Rows(" ")) + result = tk.MustQuery(`select convert_tz("0", "+00:00", "+10:32"), convert_tz("2004-01-01 12:00:00", "0", "+10:32"), convert_tz("2004-01-01 12:00:00", "+00:00", "0");`) + result.Check(testkit.Rows(" ")) // for from_unixtime tk.MustExec(`set @@session.time_zone = "+08:00"`)