diff --git a/expression/bench_test.go b/expression/bench_test.go index 1d926fd6cb1e6..8f721297d0214 100644 --- a/expression/bench_test.go +++ b/expression/bench_test.go @@ -711,7 +711,7 @@ func (g *randHexStrGener) gen() interface{} { return string(buf) } -// dateTimeGener is used to generate a dataTime +// dateTimeGener is used to generate a dateTime type dateTimeGener struct { Fsp int Year int @@ -740,7 +740,7 @@ func (g *dateTimeGener) gen() interface{} { return t } -// dateTimeStrGener is used to generate strings which are dataTime format +// dateTimeStrGener is used to generate strings which are dateTime format type dateTimeStrGener struct { Fsp int Year int @@ -762,14 +762,14 @@ func (g *dateTimeStrGener) gen() interface{} { hour := g.randGen.Intn(12) minute := g.randGen.Intn(60) second := g.randGen.Intn(60) - dataTimeStr := fmt.Sprintf("%d-%d-%d %d:%d:%d", + dateTimeStr := fmt.Sprintf("%d-%d-%d %d:%d:%d", g.Year, g.Month, g.Day, hour, minute, second) if g.Fsp > 0 && g.Fsp <= 6 { microFmt := fmt.Sprintf(".%%0%dd", g.Fsp) - return dataTimeStr + fmt.Sprintf(microFmt, g.randGen.Int()%(10^g.Fsp)) + return dateTimeStr + fmt.Sprintf(microFmt, g.randGen.Int()%(10^g.Fsp)) } - return dataTimeStr + return dateTimeStr } // dateStrGener is used to generate strings which are date format diff --git a/expression/builtin_time.go b/expression/builtin_time.go index ee36fc7d6a8e6..6faad8387add4 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -5559,6 +5559,9 @@ func (b *builtinAddStringAndStringSig) evalString(row chunk.Row) (result string, if isNull || err != nil { return "", isNull, err } + if !isDuration(arg1Str) { + return "", true, nil + } sc := b.ctx.GetSessionVars().StmtCtx arg1, err = types.ParseDuration(sc, arg1Str, getFsp4TimeAddSub(arg1Str)) if err != nil { diff --git a/expression/builtin_time_vec_generated.go b/expression/builtin_time_vec_generated.go index 535c54b9138b6..633d7ef8558d8 100644 --- a/expression/builtin_time_vec_generated.go +++ b/expression/builtin_time_vec_generated.go @@ -404,6 +404,10 @@ func (b *builtinAddStringAndStringSig) vecEvalString(input *chunk.Chunk, result // calculate + if !isDuration(arg1) { + result.AppendNull() // fixed: false + continue + } sc := b.ctx.GetSessionVars().StmtCtx arg1Duration, err := types.ParseDuration(sc, arg1, getFsp4TimeAddSub(arg1)) if err != nil { diff --git a/expression/generator/time_vec.go b/expression/generator/time_vec.go index bb6b4c5fd2be4..a415d94685364 100644 --- a/expression/generator/time_vec.go +++ b/expression/generator/time_vec.go @@ -54,7 +54,7 @@ import ( {{ end }} {{ define "SetNull" }}{{if .Output.Fixed}}result.SetNull(i, true){{else}}result.AppendNull(){{end}} // fixed: {{.Output.Fixed }}{{ end }} {{ define "ConvertStringToDuration" }} - {{ if and (ne .SigName "builtinAddStringAndStringSig") (ne .SigName "builtinSubStringAndStringSig") }} + {{ if (ne .SigName "builtinSubStringAndStringSig") }} if !isDuration(arg1) { {{ template "SetNull" . }} continue @@ -852,7 +852,7 @@ var timeDiffSigsTmpl = []sig{ {SigName: "builtinTimeTimeTimeDiffSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeDuration}, } -var addDataSigsTmpl = []sig{ +var addDateSigsTmpl = []sig{ {SigName: "builtinAddDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime}, {SigName: "builtinAddDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime}, {SigName: "builtinAddDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime}, @@ -871,7 +871,7 @@ var addDataSigsTmpl = []sig{ {SigName: "builtinAddDateDurationDecimalSig", TypeA: TypeDuration, TypeB: TypeDecimal, Output: TypeDuration}, } -var subDataSigsTmpl = []sig{ +var subDateSigsTmpl = []sig{ {SigName: "builtinSubDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime}, {SigName: "builtinSubDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime}, {SigName: "builtinSubDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime}, @@ -912,8 +912,8 @@ var tmplVal = struct { {FuncName: "AddTime", Sigs: addTimeSigsTmpl}, {FuncName: "SubTime", Sigs: subTimeSigsTmpl}, {FuncName: "TimeDiff", Sigs: timeDiffSigsTmpl}, - {FuncName: "AddDate", Sigs: addDataSigsTmpl}, - {FuncName: "SubDate", Sigs: subDataSigsTmpl}, + {FuncName: "AddDate", Sigs: addDateSigsTmpl}, + {FuncName: "SubDate", Sigs: subDateSigsTmpl}, }, } @@ -931,11 +931,11 @@ func generateDotGo(fileName string) error { if err != nil { return err } - err = addOrSubDate.Execute(w, function{FuncName: "AddDate", Sigs: addDataSigsTmpl}) + err = addOrSubDate.Execute(w, function{FuncName: "AddDate", Sigs: addDateSigsTmpl}) if err != nil { return err } - err = addOrSubDate.Execute(w, function{FuncName: "SubDate", Sigs: subDataSigsTmpl}) + err = addOrSubDate.Execute(w, function{FuncName: "SubDate", Sigs: subDateSigsTmpl}) if err != nil { return err } diff --git a/expression/integration_test.go b/expression/integration_test.go index 6ebf5e35d1b52..9b1f143d95bd0 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -1668,6 +1668,8 @@ func (s *testIntegrationSuite2) TestTimeBuiltin(c *C) { tk.MustQuery(`select addtime(cast(1 as time), cast(1 as time))`).Check(testkit.Rows("00:00:02")) tk.MustQuery(`select addtime(cast(null as time), cast(1 as time))`).Check(testkit.Rows("")) tk.MustQuery(`select addtime(cast(1 as time), cast(null as time))`).Check(testkit.Rows("")) + tk.MustQuery(`select addtime("2020-05-13 14:01:24", "2020-04-29 05:11:19")`).Check(testkit.Rows("")) + tk.MustQuery(`select addtime("2020-05-13 14:01:24", "-2020-04-29 05:11:19")`).Check(testkit.Rows("")) // for SUBTIME result = tk.MustQuery("select subtime('01:01:11', '00:00:01.013'), subtime('01:01:11.00', '00:00:01'), subtime" +