Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types: fix incorrect time fraction parsing method #9933

Merged
merged 9 commits into from
Apr 1, 2019
41 changes: 37 additions & 4 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,13 @@ func (t Time) RoundFrac(sc *stmtctx.StatementContext, fsp int) (Time, error) {

// GetFsp gets the fsp of a string.
func GetFsp(s string) (fsp int) {
fsp = len(s) - strings.LastIndex(s, ".") - 1
index := getFracIndex(s)
if index < 0 {
fsp = 0
} else {
fsp = len(s) - getFracIndex(s) - 1
WangXiangUSTC marked this conversation as resolved.
Show resolved Hide resolved
}

if fsp == len(s) {
fsp = 0
} else if fsp > 6 {
Expand All @@ -408,6 +414,23 @@ func GetFsp(s string) (fsp int) {
return
}

// find the last '.' for get fracStr, index = -1 means fracStr not found.
// for format like '2019.01.01 00:00:00', the fracStr should be empty
func getFracIndex(s string) (index int) {
zz-jason marked this conversation as resolved.
Show resolved Hide resolved
WangXiangUSTC marked this conversation as resolved.
Show resolved Hide resolved
index = -1
for i := len(s) - 1; i >= 0; i-- {
if unicode.IsPunct(rune(s[i])) {
if s[i] == '.' {
index = i
}

WangXiangUSTC marked this conversation as resolved.
Show resolved Hide resolved
break
}
}

return index
}

// RoundFrac rounds fractional seconds precision with new fsp and returns a new one.
// We will use the “round half up” rule, e.g, >= 0.5 -> 1, < 0.5 -> 0,
// so 2011:11:11 10:10:10.888888 round 0 -> 2011:11:11 10:10:11
Expand Down Expand Up @@ -600,9 +623,10 @@ func ParseDateFormat(format string) []string {
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html.
// The only delimiter recognized between a date and time part and a fractional seconds part is the decimal point.
func splitDateTime(format string) (seps []string, fracStr string) {
if i := strings.LastIndex(format, "."); i > 0 {
fracStr = strings.TrimSpace(format[i+1:])
format = format[:i]
index := getFracIndex(format)
if index > 0 {
fracStr = format[index+1:]
format = format[:index]
}

seps = ParseDateFormat(format)
Expand Down Expand Up @@ -687,6 +711,15 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bo
sc.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs("datetime", str))
err = nil
}
case 2:
// YYYY-MM is not valid
if len(fracStr) == 0 {
return ZeroDatetime, errors.Trace(ErrIncorrectDatetimeValue.GenWithStackByArgs(str))
}

// YYYY-MM.DD, DD is treat as fracStr
err = scanTimeArgs(append(seps, fracStr), &year, &month, &day)
fracStr = ""
case 3:
// YYYY-MM-DD
err = scanTimeArgs(seps, &year, &month, &day)
Expand Down
11 changes: 11 additions & 0 deletions types/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ func (s *testTimeSuite) TestDateTime(c *C) {
{"170102037.11", "2017-01-02 03:07:11.00"},
{"2018-01-01 18", "2018-01-01 18:00:00"},
{"18-01-01 18", "2018-01-01 18:00:00"},
{"2018.01.01", "2018-01-01 00:00:00.00"},
{"2018.01.01 00:00:00", "2018-01-01 00:00:00"},
{"2018/01/01-00:00:00", "2018-01-01 00:00:00"},
}

for _, test := range table {
Expand All @@ -85,6 +88,9 @@ func (s *testTimeSuite) TestDateTime(c *C) {
{"2017-01-05 23:59:59.575601", 0, "2017-01-06 00:00:00"},
{"2017-01-31 23:59:59.575601", 0, "2017-02-01 00:00:00"},
{"2017-00-05 23:59:58.575601", 3, "2017-00-05 23:59:58.576"},
{"2017.00.05 23:59:58.575601", 3, "2017-00-05 23:59:58.576"},
{"2017/00/05 23:59:58.575601", 3, "2017-00-05 23:59:58.576"},
{"2017/00/05-23:59:58.575601", 3, "2017-00-05 23:59:58.576"},
}

for _, test := range fspTbl {
Expand All @@ -105,6 +111,8 @@ func (s *testTimeSuite) TestDateTime(c *C) {
"1000-09-31 00:00:00",
"1001-02-29 00:00:00",
"20170118.999",
"2018-01",
"2018.01",
}

for _, test := range errTable {
Expand Down Expand Up @@ -154,6 +162,8 @@ func (s *testTimeSuite) TestDate(c *C) {
{"2015-06-01 12:12:12", "2015-06-01"},
{"0001-01-01 00:00:00", "0001-01-01"},
{"0001-01-01", "0001-01-01"},
{"2019.01.01", "2019-01-01"},
{"2019/01/01", "2019-01-01"},
}

for _, test := range table {
Expand All @@ -164,6 +174,7 @@ func (s *testTimeSuite) TestDate(c *C) {

errTable := []string{
"0121231",
"2019.01",
}

for _, test := range errTable {
Expand Down