From c1be8c0f137c707e9fe9844eac36285f3cacdedf Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Thu, 18 Feb 2021 17:23:04 +0800 Subject: [PATCH 1/2] executor: add new format specifier(%# %@ %.) for str_to_date expression(#22530) --- expression/builtin_time_test.go | 7 ++++++ types/time.go | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index 77fe3ae06ea74..a588e170ee832 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -1411,6 +1411,13 @@ func (s *testEvaluatorSuite) TestStrToDate(c *C) { {"15-01-2001 1:9:8.999", "%d-%m-%Y %H:%i:%S.%f", true, time.Date(2001, 1, 15, 1, 9, 8, 999000000, time.Local)}, {"2003-01-02 10:11:12 PM", "%Y-%m-%d %H:%i:%S %p", false, time.Time{}}, {"10:20:10AM", "%H:%i:%S%p", false, time.Time{}}, + // test %@(skip alpha), %#(skip number), %.(skip punct) + {"2020-10-10ABCD", "%Y-%m-%d%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"2020-10-101234", "%Y-%m-%d%#", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"2020-10-10....", "%Y-%m-%d%.", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"2020-10-10.1", "%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"abcd2020-10-10.1", "%@%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"abcd-2020-10-10.1", "%@-%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, } fc := funcs[ast.StrToDate] diff --git a/types/time.go b/types/time.go index 1358d1b47ef1b..8e525affb9ed6 100644 --- a/types/time.go +++ b/types/time.go @@ -2896,6 +2896,9 @@ var dateFormatParserTable = map[string]dateFormatParser{ "%S": secondsNumeric, // Seconds (00..59) "%T": time24Hour, // Time, 24-hour (hh:mm:ss) "%Y": yearNumericFourDigits, // Year, numeric, four digits + "%#": skipAllNums, // skip all numbers + "%.": skipAllPunct, // skip all punctation characters + "%@": skipAllAlpha, // skip all alpha characters // Deprecated since MySQL 5.7.5 "%y": yearNumericTwoDigits, // Year, numeric (two digits) // TODO: Add the following... @@ -3276,3 +3279,39 @@ func DateTimeIsOverflow(sc *stmtctx.StatementContext, date Time) (bool, error) { inRange := (t.After(b) || t.Equal(b)) && (t.Before(e) || t.Equal(e)) return !inRange, nil } + +func skipAllNums(t *CoreTime, input string, ctx map[string]int) (string, bool) { + retIdx := 0 + for i, ch := range input { + if unicode.IsNumber(ch) { + retIdx = i + 1 + } else { + break + } + } + return input[retIdx:], true +} + +func skipAllPunct(t *CoreTime, input string, ctx map[string]int) (string, bool) { + retIdx := 0 + for i, ch := range input { + if unicode.IsPunct(ch) { + retIdx = i + 1 + } else { + break + } + } + return input[retIdx:], true +} + +func skipAllAlpha(t *CoreTime, input string, ctx map[string]int) (string, bool) { + retIdx := 0 + for i, ch := range input { + if unicode.IsLetter(ch) { + retIdx = i + 1 + } else { + break + } + } + return input[retIdx:], true +} From 542ced20b9eb7297f46c457c2f850b3be745d394 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Thu, 18 Feb 2021 17:40:23 +0800 Subject: [PATCH 2/2] executor: add new format specifier(%# %@ %.) for str_to_date expression(#22530) --- expression/builtin_time_test.go | 2 ++ types/time.go | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index a588e170ee832..0d5feb1340d58 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -1418,6 +1418,8 @@ func (s *testEvaluatorSuite) TestStrToDate(c *C) { {"2020-10-10.1", "%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, {"abcd2020-10-10.1", "%@%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, {"abcd-2020-10-10.1", "%@-%Y-%m-%d%.%#%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"2020-10-10", "%Y-%m-%d%@", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, + {"2020-10-10abcde123abcdef", "%Y-%m-%d%@%#", true, time.Date(2020, 10, 10, 0, 0, 0, 0, time.Local)}, } fc := funcs[ast.StrToDate] diff --git a/types/time.go b/types/time.go index 8e525affb9ed6..615bb86ed6437 100644 --- a/types/time.go +++ b/types/time.go @@ -2896,9 +2896,9 @@ var dateFormatParserTable = map[string]dateFormatParser{ "%S": secondsNumeric, // Seconds (00..59) "%T": time24Hour, // Time, 24-hour (hh:mm:ss) "%Y": yearNumericFourDigits, // Year, numeric, four digits - "%#": skipAllNums, // skip all numbers - "%.": skipAllPunct, // skip all punctation characters - "%@": skipAllAlpha, // skip all alpha characters + "%#": skipAllNums, // Skip all numbers + "%.": skipAllPunct, // Skip all punctation characters + "%@": skipAllAlpha, // Skip all alpha characters // Deprecated since MySQL 5.7.5 "%y": yearNumericTwoDigits, // Year, numeric (two digits) // TODO: Add the following...