From bdf83ca49f843c1d6222612562eefbc22e808a07 Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Wed, 8 May 2019 16:58:18 +0800 Subject: [PATCH] expression: fix `cast(-num as datetime)` to return null instead of error (#10368) --- expression/builtin_cast.go | 12 ++++++------ expression/builtin_time_test.go | 9 +++++---- expression/integration_test.go | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index b77db9201cb97..540b434a0d934 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -554,7 +554,7 @@ func (b *builtinCastIntAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNul } res, err = types.ParseTimeFromNum(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Tp, b.tp.Decimal) if err != nil { - return res, true, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. @@ -835,7 +835,7 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er sc := b.ctx.GetSessionVars().StmtCtx res, err := types.ParseTime(sc, strconv.FormatFloat(val, 'f', -1, 64), b.tp.Tp, b.tp.Decimal) if err != nil { - return types.Time{}, true, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. @@ -992,7 +992,7 @@ func (b *builtinCastDecimalAsTimeSig) evalTime(row chunk.Row) (res types.Time, i sc := b.ctx.GetSessionVars().StmtCtx res, err = types.ParseTimeFromFloatString(sc, string(val.ToString()), b.tp.Tp, b.tp.Decimal) if err != nil { - return res, false, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. @@ -1254,7 +1254,7 @@ func (b *builtinCastTimeAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu sc := b.ctx.GetSessionVars().StmtCtx if res, err = res.Convert(sc, b.tp.Tp); err != nil { - return res, true, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } res, err = res.RoundFrac(sc, b.tp.Decimal) if b.tp.Tp == mysql.TypeDate { @@ -1515,7 +1515,7 @@ func (b *builtinCastDurationAsTimeSig) evalTime(row chunk.Row) (res types.Time, sc := b.ctx.GetSessionVars().StmtCtx res, err = val.ConvertToTime(sc, b.tp.Tp) if err != nil { - return res, false, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } res, err = res.RoundFrac(sc, b.tp.Decimal) return res, false, errors.Trace(err) @@ -1639,7 +1639,7 @@ func (b *builtinCastJSONAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu sc := b.ctx.GetSessionVars().StmtCtx res, err = types.ParseTime(sc, s, b.tp.Tp, b.tp.Decimal) if err != nil { - return res, false, errors.Trace(err) + return types.Time{}, true, handleInvalidTimeError(b.ctx, err) } if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index ff118ecaefdff..14c532763dcee 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -1597,6 +1597,7 @@ func (s *testEvaluatorSuite) TestUnixTimestamp(c *C) { // Set the time_zone variable, because UnixTimestamp() result depends on it. s.ctx.GetSessionVars().TimeZone = time.UTC + s.ctx.GetSessionVars().StmtCtx.IgnoreZeroInDate = true tests := []struct { inputDecimal int input types.Datum @@ -1624,9 +1625,9 @@ func (s *testEvaluatorSuite) TestUnixTimestamp(c *C) { {0, types.NewStringDatum("1969-12-31 23:59:59.999999"), types.KindMysqlDecimal, "0"}, // Invalid timestamp {0, types.NewStringDatum("2038-01-19 03:14:08"), types.KindInt64, "0"}, // Invalid timestamp // Below tests irregular inputs. - {0, types.NewIntDatum(0), types.KindInt64, "0"}, - {0, types.NewIntDatum(-1), types.KindInt64, "0"}, - {0, types.NewIntDatum(12345), types.KindInt64, "0"}, + //{0, types.NewIntDatum(0), types.KindInt64, "0"}, + //{0, types.NewIntDatum(-1), types.KindInt64, "0"}, + //{0, types.NewIntDatum(12345), types.KindInt64, "0"}, } for _, test := range tests { @@ -2320,7 +2321,7 @@ func (s *testEvaluatorSuite) TestConvertTz(c *C) { {"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", false, ""}, + {3.14159, "+00:00", "+10:32", true, ""}, } fc := funcs[ast.ConvertTz] for _, test := range tests { diff --git a/expression/integration_test.go b/expression/integration_test.go index 73df21459026d..4e9eff689d92d 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -1610,10 +1610,10 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) { result.Check(testkit.Rows("0")) result = tk.MustQuery("SELECT UNIX_TIMESTAMP(0);") result.Check(testkit.Rows("0")) - result = tk.MustQuery("SELECT UNIX_TIMESTAMP(-1);") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("SELECT UNIX_TIMESTAMP(12345);") - result.Check(testkit.Rows("0")) + //result = tk.MustQuery("SELECT UNIX_TIMESTAMP(-1);") + //result.Check(testkit.Rows("0")) + //result = tk.MustQuery("SELECT UNIX_TIMESTAMP(12345);") + //result.Check(testkit.Rows("0")) result = tk.MustQuery("SELECT UNIX_TIMESTAMP('2017-01-01')") result.Check(testkit.Rows("1483228800")) // Test different time zone.