@ -310,14 +310,41 @@ func (t Time) RoundFrac(fsp int) (Time, error) {
|
||||
return Time{Time: nt, Type: t.Type, Fsp: fsp}, nil
|
||||
}
|
||||
|
||||
func parseDateFormat(format string) []string {
|
||||
format = strings.TrimSpace(format)
|
||||
|
||||
start := 0
|
||||
seps := []string{}
|
||||
for i := 0; i < len(format); i++ {
|
||||
// Date fromat must start and end with number.
|
||||
if i == 0 || i == len(format)-1 {
|
||||
if !unicode.IsNumber(rune(format[i])) {
|
||||
return nil
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Seperator is a single none-number char.
|
||||
if !unicode.IsNumber(rune(format[i])) {
|
||||
if !unicode.IsNumber(rune(format[i-1])) {
|
||||
return nil
|
||||
}
|
||||
|
||||
seps = append(seps, format[start:i])
|
||||
start = i + 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
seps = append(seps, format[start:])
|
||||
return seps
|
||||
}
|
||||
|
||||
func parseDatetime(str string, fsp int) (Time, error) {
|
||||
// Try to split str with delimiter.
|
||||
// TODO: only punctuation can be the delimiter for date parts or time parts.
|
||||
// But only space and T can be the delimiter between the date and time part.
|
||||
seps := strings.FieldsFunc(str, func(c rune) bool {
|
||||
return !unicode.IsNumber(c)
|
||||
})
|
||||
|
||||
var (
|
||||
year int
|
||||
month int
|
||||
@ -330,6 +357,9 @@ func parseDatetime(str string, fsp int) (Time, error) {
|
||||
|
||||
err error
|
||||
)
|
||||
|
||||
seps := parseDateFormat(str)
|
||||
|
||||
switch len(seps) {
|
||||
case 1:
|
||||
// No delimiter.
|
||||
|
||||
@ -671,3 +671,26 @@ func (s *testTimeSuite) TestDurationClock(c *C) {
|
||||
c.Assert(d.MicroSecond(), Equals, t.MicroSecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *testTimeSuite) TestParseDateFormat(c *C) {
|
||||
tbl := []struct {
|
||||
Input string
|
||||
Result []string
|
||||
}{
|
||||
{"2011-11-11 10:10:10.123456", []string{"2011", "11", "11", "10", "10", "10", "123456"}},
|
||||
{" 2011-11-11 10:10:10.123456 ", []string{"2011", "11", "11", "10", "10", "10", "123456"}},
|
||||
{"2011-11-11 10", []string{"2011", "11", "11", "10"}},
|
||||
{"2011-11-11T10:10:10.123456", []string{"2011", "11", "11", "10", "10", "10", "123456"}},
|
||||
{"2011:11:11T10:10:10.123456", []string{"2011", "11", "11", "10", "10", "10", "123456"}},
|
||||
{"xx2011-11-11 10:10:10", nil},
|
||||
{"T10:10:10", nil},
|
||||
{"2011-11-11x", nil},
|
||||
{"2011-11-11 10:10:10", nil},
|
||||
{"xxx 10:10:10", nil},
|
||||
}
|
||||
|
||||
for _, t := range tbl {
|
||||
r := parseDateFormat(t.Input)
|
||||
c.Assert(r, DeepEquals, t.Result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1245,6 +1245,14 @@ func (s *testSessionSuite) TestResultType(c *C) {
|
||||
c.Assert(fs[0].Col.FieldType.Tp, Equals, mysql.TypeString)
|
||||
}
|
||||
|
||||
func (s *testSessionSuite) TestBuiltin(c *C) {
|
||||
store := newStore(c, s.dbName)
|
||||
se := newSession(c, store, s.dbName)
|
||||
|
||||
// Testcase for https://github.com/pingcap/tidb/issues/382
|
||||
mustExecFailed(c, se, `select cast("xxx 10:10:10" as datetime)`)
|
||||
}
|
||||
|
||||
func newSession(c *C, store kv.Storage, dbName string) Session {
|
||||
se, err := CreateSession(store)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
Reference in New Issue
Block a user