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
expression: add builtinAddTimeSig #3290
expression: add builtinAddTimeSig #3290
Conversation
@hawkingrei Thanks for your PR! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add unit test and modify plan/typeinferer.go.
expression/builtin_time.go
Outdated
return d, errFunctionNotExists.GenByArgs("ADDTIME") | ||
args, err := b.evalArgs(row) | ||
if err != nil { | ||
return types.Datum{}, errors.Trace(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return d, errors.Trace(err)
any test cases? |
I will complete the test case. |
@hanfei1991 PTAL |
expression/builtin_time.go
Outdated
return d, errors.Trace(err) | ||
} | ||
|
||
duration := args[1].GetMysqlDuration() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should convert it to duration
Grean all Have some problem. ADDTIME(expr1,expr2) |
…dd_builtinAddTimeSig
…rei/tidb into expression/add_builtinAddTimeSig
Is it the same behaviour with MySQL?
You can check MySQL's return type by using mysqlworkbench.
You can restrict the type of expr1.
|
expression/builtin_time.go
Outdated
@@ -1785,8 +1785,36 @@ type builtinAddTimeSig struct { | |||
|
|||
// eval evals a builtinAddTimeSig. | |||
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime | |||
// ADDTIME(expr1,expr2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove line 1788,1789
it's useless which has been described in the URL.
and expr1 is a time or datetime expression, but expr2 is a time expression.
mysql> select addtime("12:00:01", 1);
+------------------------+
| addtime("12:00:01", 1) |
+------------------------+
| 12:00:02 |
+------------------------+
expression/typeinferer.go
Outdated
case mysql.TypeDatetime,mysql.TypeDate,mysql.TypeTimestamp: | ||
tp = types.NewFieldType(mysql.TypeDatetime) | ||
case mysql.TypeTime: | ||
tp = types.NewFieldType(mysql.TypeVarString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be mysql.TypeDuration
expression/typeinferer.go
Outdated
case ast.AddTime: | ||
t := x.Args[0].GetType().Tp | ||
switch t { | ||
case mysql.TypeDatetime,mysql.TypeDate,mysql.TypeTimestamp: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
args[0].Tp == mysql.TypeDate
should be contained in default
and the chs
should be setted to 'utf8' in the default
case.
expression/builtin_time_test.go
Outdated
for _, t := range tbl { | ||
tmpInput := types.NewStringDatum(t.Input) | ||
tmpInputDuration := types.NewStringDatum(t.InputDuration) | ||
//tmpResult := types.NewStringDatum(t.result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line if it's useless.
expression/typeinferer.go
Outdated
@@ -367,6 +367,18 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) { | |||
tp.Charset, tp.Collate = types.DefaultCharsetForType(tp.Tp) | |||
} | |||
// number related |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this line to line 381
expression/typeinferer_test.go
Outdated
@@ -177,6 +177,8 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) { | |||
{"weekday('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag}, | |||
{"weekofyear('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag}, | |||
{"yearweek('2009-12-31 23:59:59.000010')", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag}, | |||
{"addtime('2007-12-31 23:59:59.999999', '1 1:1:1.000002')", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'2009-12-31 23:59:59.000010' is a string but not a datetime,
you can use c_datetime (which can be found in line51).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx,i will complete this function as soon as possible
expression/builtin_time_test.go
Outdated
InputDuration string | ||
expect string | ||
}{ | ||
//{"2007-12-31 23:59:59.999999", "1 1:1:1.000002", "2008-01-02 01:01:01.000001"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which will TiDB get of these 4 cases?
expression/builtin_time.go
Outdated
if err != nil { | ||
return d, errors.Trace(err) | ||
} | ||
arg1, err := types.ParseDuration(s, getFsp(s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the fsp of the result will always be types.MaxFsp
if getFsp(s) >0;
and be types.MinFsp if getFsp(s) == 0
…rei/tidb into expression/add_builtinAddTimeSig
@XuHuaiyu Sorry. I forget to push some fixed code. add some invalid cases for “aa: bb: cc” |
expression/builtin_time.go
Outdated
@@ -1770,6 +1770,72 @@ func getTimeZone(ctx context.Context) *time.Location { | |||
return ret | |||
} | |||
|
|||
// isDuration returns a boolean indicating whether the str is the format of duration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- s/is the format/matches the format
- add comment for the format that str should match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@XuHuaiyu Use regular expression install of the old way.
expression/builtin_time_test.go
Outdated
c.Assert(result, Equals, t.expect) | ||
} | ||
|
||
result := isDuration("aa:bb:cc") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need the comparison of these two cases here.
PTAL |
…rei/tidb into expression/add_builtinAddTimeSig
expression/builtin_time.go
Outdated
@@ -1770,6 +1770,52 @@ func getTimeZone(ctx context.Context) *time.Location { | |||
return ret | |||
} | |||
|
|||
// isDuration returns a boolean indicating whether the str is the format of duration. | |||
func isDuration(str string) bool { | |||
const durationArgReg = `^(|[-]?)(|\d{1,2}\s)(\d{2,3}:\d{2}:\d{2}|\d{1,2}:\d{2}|\d{1,6})(|\.\d*)$` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can pre-compile the regexp and store it as a global variable, rather than compile it every time.
Or maybe it's a non-frequency function and you can just leave as it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And add comment for it, better with a example: "xx:xx:xx", otherwise, nobody can understand this regexp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tiancaiamao Fix
expression/builtin_time.go
Outdated
return r.MatchString(str) | ||
} | ||
|
||
// strDatetimeAddDuration adds duration to datetime string, returns a dutam value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/dutam/datum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tiancaiamao Fix
return result, errors.Trace(err) | ||
} | ||
if getFsp(d) != 0 { | ||
tmpDuration.Fsp = types.MaxFsp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this MySQL's behavior ?
By the way, you can fsp := getFsp(d)
to avoid call getFsp
again and again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tiancaiamao
Yes
mysql> select addtime("1:23","1.98");
+------------------------+
| addtime("1:23","1.98") |
+------------------------+
| 01:23:01.980000 |
+------------------------+
1 row in set (0.00 sec)
mysql> select addtime("123","1:23.98");
+--------------------------+
| addtime("123","1:23.98") |
+--------------------------+
| 01:24:23.980000 |
+--------------------------+
1 row in set (0.00 sec)
if err != nil { | ||
return d, errors.Trace(err) | ||
} | ||
if args[0].IsNull() || args[1].IsNull() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to check len(args) == 2
, or is it already done in type infer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tiancaiamao it is already done in buildin.go
LGTM @XuHuaiyu |
expression/typeinferer.go
Outdated
@@ -367,6 +367,18 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) { | |||
tp.Charset, tp.Collate = types.DefaultCharsetForType(tp.Tp) | |||
} | |||
// number related |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment should be in line 381. @hawkingrei
…rei/tidb into expression/add_builtinAddTimeSig
@XuHuaiyu Fix it |
LGTM |
No description provided.