Skip to content

Commit

Permalink
CONVERT_TZ should return NULL if its arguments are invalid. (#… (#11357)
Browse files Browse the repository at this point in the history
  • Loading branch information
SunRunAway authored and zz-jason committed Jul 23, 2019
1 parent b978528 commit 0f0d8b4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 17 deletions.
19 changes: 10 additions & 9 deletions expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -4837,21 +4837,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, errors.Trace(err)
return types.Time{}, true, nil
}

fromTzStr, isNull, err := b.args[1].EvalString(b.ctx, row)
if isNull || err != nil {
return types.Time{}, true, errors.Trace(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, errors.Trace(err)
if isNull || err != nil || toTzStr == "" {
return types.Time{}, true, nil
}

fromTzMatched := b.timezoneRegex.MatchString(fromTzStr)
Expand All @@ -4860,17 +4861,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, errors.Trace(err)
return types.Time{}, true, nil
}

toTz, err := time.LoadLocation(toTzStr)
if err != nil {
return types.Time{}, true, errors.Trace(err)
return types.Time{}, true, nil
}

t, err := dt.Time.GoTime(fromTz)
if err != nil {
return types.Time{}, true, errors.Trace(err)
return types.Time{}, true, nil
}

return types.Time{
Expand All @@ -4882,7 +4883,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, errors.Trace(err)
return types.Time{}, true, nil
}

return types.Time{
Expand Down
19 changes: 14 additions & 5 deletions expression/builtin_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2331,8 +2331,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
}{
Expand All @@ -2344,20 +2344,29 @@ 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 {
f, err := fc.getFunction(s.ctx,
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 {
Expand Down
13 changes: 10 additions & 3 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1739,9 +1739,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("<nil> <nil> <nil>"))
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("<nil> <nil> <nil>"))
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("<nil> <nil> <nil>"))
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("<nil> <nil> <nil>"))

// for from_unixtime
tk.MustExec(`set @@session.time_zone = "+08:00"`)
Expand Down

0 comments on commit 0f0d8b4

Please sign in to comment.