From 7d5b936e507786f9252a5a85eddc1de7872f9c93 Mon Sep 17 00:00:00 2001 From: Lonng Date: Tue, 15 Oct 2019 16:58:17 +0800 Subject: [PATCH 1/3] fix the STR_TO_DATE incompitable in MySQL and TiDB Signed-off-by: Lonng --- executor/executor_test.go | 2 ++ expression/builtin_time.go | 10 +++++++--- types/time.go | 5 +++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 5a1ab52dc2d78..8a43813386d5d 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -3997,6 +3997,8 @@ func (s *testSuite4) TearDownTest(c *C) { func (s *testSuiteP1) TestStrToDateBuiltin(c *C) { tk := testkit.NewTestKit(c, s.store) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) tk.MustQuery(`select str_to_date('a18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) tk.MustQuery(`select str_to_date('69/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) diff --git a/expression/builtin_time.go b/expression/builtin_time.go index f12161337035a..75c31fb9c3cfc 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -1788,15 +1788,19 @@ func (c *strToDateFunctionClass) getRetTp(ctx sessionctx.Context, arg Expression if err != nil || isNull { return } + + if strings.Contains(format, "%f") { + tp = mysql.TypeDatetime + fsp = types.MaxFsp + return + } + isDuration, isDate := types.GetFormatType(format) if isDuration && !isDate { tp = mysql.TypeDuration } else if !isDuration && isDate { tp = mysql.TypeDate } - if strings.Contains(format, "%f") { - fsp = types.MaxFsp - } return } diff --git a/types/time.go b/types/time.go index 746e0507fb460..c8ae413382c8c 100644 --- a/types/time.go +++ b/types/time.go @@ -2199,6 +2199,11 @@ func strToDate(t *MysqlTime, date string, format string, ctx map[string]int) boo return true } + if len(date) == 0 { + ctx[token] = 0 + return true + } + dateRemain, succ := matchDateWithToken(t, date, token, ctx) if !succ { return false From cee4509f523012f7efabf60cee97d4929f718039 Mon Sep 17 00:00:00 2001 From: Lonng Date: Tue, 15 Oct 2019 17:01:17 +0800 Subject: [PATCH 2/3] coverage some test Signed-off-by: Lonng --- executor/executor_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/executor/executor_test.go b/executor/executor_test.go index 8a43813386d5d..f999c5cef78cb 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -3997,6 +3997,7 @@ func (s *testSuite4) TearDownTest(c *C) { func (s *testSuiteP1) TestStrToDateBuiltin(c *C) { tk := testkit.NewTestKit(c, s.store) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%!') from dual`).Check(testkit.Rows("2019-01-01")) tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) From ada36c275d531703ddbaa4dc64cba19cca099053 Mon Sep 17 00:00:00 2001 From: Lonng Date: Tue, 15 Oct 2019 17:14:57 +0800 Subject: [PATCH 3/3] fix CI failure Signed-off-by: Lonng --- expression/builtin_time.go | 9 +++------ types/time.go | 13 +++---------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/expression/builtin_time.go b/expression/builtin_time.go index 75c31fb9c3cfc..8d29ec263e4b9 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -1789,18 +1789,15 @@ func (c *strToDateFunctionClass) getRetTp(ctx sessionctx.Context, arg Expression return } - if strings.Contains(format, "%f") { - tp = mysql.TypeDatetime - fsp = types.MaxFsp - return - } - isDuration, isDate := types.GetFormatType(format) if isDuration && !isDate { tp = mysql.TypeDuration } else if !isDuration && isDate { tp = mysql.TypeDate } + if strings.Contains(format, "%f") { + fsp = types.MaxFsp + } return } diff --git a/types/time.go b/types/time.go index c8ae413382c8c..739db5fd2c2d2 100644 --- a/types/time.go +++ b/types/time.go @@ -2321,21 +2321,14 @@ func GetFormatType(format string) (isDuration, isDate bool) { isDuration, isDate = false, false break } - var durationTokens bool - var dateTokens bool if len(token) >= 2 && token[0] == '%' { switch token[1] { - case 'h', 'H', 'i', 'I', 's', 'S', 'k', 'l': - durationTokens = true + case 'h', 'H', 'i', 'I', 's', 'S', 'k', 'l', 'f': + isDuration = true case 'y', 'Y', 'm', 'M', 'c', 'b', 'D', 'd', 'e': - dateTokens = true + isDate = true } } - if durationTokens { - isDuration = true - } else if dateTokens { - isDate = true - } if isDuration && isDate { break }