diff --git a/executor/executor_test.go b/executor/executor_test.go index f5b82c73c98aa..e932958d206d2 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -6647,3 +6647,19 @@ func (s *testSuite) TestIssue22201(c *C) { tk.MustQuery("SELECT HEX(WEIGHT_STRING('ab' AS char(1000000000000000000)));").Check(testkit.Rows("")) tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1301 Result of weight_string() was larger than max_allowed_packet (67108864) - truncated")) } + +func (s *testSuite) TestIssue22231(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_issue_22231") + tk.MustExec("create table t_issue_22231(a datetime)") + tk.MustExec("insert into t_issue_22231 values('2020--05-20 01:22:12')") + tk.MustQuery("select * from t_issue_22231 where a >= '2020-05-13 00:00:00 00:00:00' and a <= '2020-05-28 23:59:59 00:00:00'").Check(testkit.Rows("2020-05-20 01:22:12")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-13 00:00:00 00:00:00'", "Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) + + tk.MustQuery("select cast('2020-10-22 10:31-10:12' as datetime)").Check(testkit.Rows("2020-10-22 10:31:10")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-10-22 10:31-10:12'")) + tk.MustQuery("select cast('2020-05-28 23:59:59 00:00:00' as datetime)").Check(testkit.Rows("2020-05-28 23:59:59")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) + tk.MustExec("drop table if exists t_issue_22231") +} diff --git a/types/time.go b/types/time.go index 842c62daaf5f8..4a88001eda1e2 100644 --- a/types/time.go +++ b/types/time.go @@ -739,8 +739,8 @@ func ParseDateFormat(format string) []string { return nil } - // Date format must start and end with number. - if !isDigit(format[0]) || !isDigit(format[len(format)-1]) { + // Date format must start with number. + if !isDigit(format[0]) { return nil } @@ -786,7 +786,14 @@ func isValidSeparator(c byte, prevParts int) bool { return true } - return prevParts == 2 && (c == ' ' || c == 'T') + if prevParts == 2 && (c == ' ' || c == 'T') { + return true + } + + if prevParts > 4 && !isDigit(c) { + return true + } + return false } var validIdxCombinations = map[int]struct { @@ -995,6 +1002,8 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int8, isFloat b } } switch len(seps) { + case 0: + return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(DateTimeStr, str)) case 1: l := len(seps[0]) // Values specified as numbers @@ -1083,6 +1092,8 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int8, isFloat b sc.AppendWarning(ErrTruncatedWrongVal.GenWithStackByArgs("datetime", str)) err = nil } + case 2: + return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(DateTimeStr, str)) case 3: // YYYY-MM-DD err = scanTimeArgs(seps, &year, &month, &day) @@ -1098,7 +1109,14 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int8, isFloat b err = scanTimeArgs(seps, &year, &month, &day, &hour, &minute, &second) hhmmss = true default: - return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(DateTimeStr, str)) + // For case like `2020-05-28 23:59:59 00:00:00`, the seps should be > 6, the reluctant parts should be truncated. + seps = seps[:6] + // YYYY-MM-DD HH-MM-SS + if sc != nil { + sc.AppendWarning(ErrTruncatedWrongVal.GenWithStackByArgs("datetime", str)) + } + err = scanTimeArgs(seps, &year, &month, &day, &hour, &minute, &second) + hhmmss = true } if err != nil { return ZeroDatetime, errors.Trace(err) diff --git a/types/time_test.go b/types/time_test.go index 0befea3a77f1b..9dc3c4851e486 100644 --- a/types/time_test.go +++ b/types/time_test.go @@ -106,6 +106,15 @@ func (s *testTimeSuite) TestDateTime(c *C) { {"2018.01.01 00:00:00", "2018-01-01 00:00:00"}, {"2018/01/01-00:00:00", "2018-01-01 00:00:00"}, {"4710072", "2047-10-07 02:00:00"}, + {"2016-06-01 00:00:00 00:00:00", "2016-06-01 00:00:00"}, + {"2020-06-01 00:00:00ads!,?*da;dsx", "2020-06-01 00:00:00"}, + + // For issue 22231 + {"2020-05-28 23:59:59 00:00:00", "2020-05-28 23:59:59"}, + {"2020-05-28 23:59:59-00:00:00", "2020-05-28 23:59:59"}, + {"2020-05-28 23:59:59T T00:00:00", "2020-05-28 23:59:59"}, + {"2020-10-22 10:31-10:12", "2020-10-22 10:31:10"}, + {"2018.01.01 01:00:00", "2018-01-01 01:00:00"}, } for _, test := range table { @@ -164,12 +173,12 @@ func (s *testTimeSuite) TestDateTime(c *C) { "170118-12", "1710-10", "1710-1000", - "2020-10-22 10:31-10:12", // YYYY-MM-DD HH:MM-SS:HH (invalid) } for _, test := range errTable { _, err := types.ParseDatetime(sc, test) - c.Assert(err, NotNil) + c.Assert(err != nil || sc.WarningCount() > 0, Equals, true) + sc.SetWarnings(nil) } } @@ -1066,7 +1075,7 @@ func (s *testTimeSuite) TestParseDateFormat(c *C) { {"2011-11-11 10:10:10", []string{"2011", "11", "11", "10", "10", "10"}}, {"xx2011-11-11 10:10:10", nil}, {"T10:10:10", nil}, - {"2011-11-11x", nil}, + {"2011-11-11x", []string{"2011", "11", "11x"}}, {"xxx 10:10:10", nil}, }