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

expression: fix unix_timestamp function which is not compatible with Mysql #9751

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -3516,10 +3516,10 @@ func (c *unixTimestampFunctionClass) getFunction(ctx sessionctx.Context, args []
argType := args[0].GetType()
argEvaltp := argType.EvalType()
if argEvaltp == types.ETString {
// Treat types.ETString as unspecified decimal.
retDecimal = types.UnspecifiedLength
if cnst, ok := args[0].(*Constant); ok {
tmpStr, _, err := cnst.EvalString(ctx, chunk.Row{})
if _, ok := args[0].(*Column); ok {
retDecimal = types.UnspecifiedLength
} else {
tmpStr, _, err := args[0].EvalString(ctx, chunk.Row{})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider this case: args[0] is a scalar function, but it refers to other columns. Directly calling args[0].EvalString() would cause a nil pointer deference panic because the input Row is empty in this case.

A simple SQL can be:

select unix_timestamp(concat(a+b)) from t;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I think that some scalar functions would panic. And the test passing surprises we.
Can we eval it here for scalar function like concat?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For general scalar function, I think we can not. We can specially handle the GetVar function in the non-prepare statements. However, it's better to check how mysql handle this scenario in their codebase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For general scalar function, I think we can not. We can specially handle the GetVar function in the non-prepare statements. However, it's better to check how mysql handle this scenario in their codebase.

Agree with you, we have better check the code in MySQL. And I think GetVar is not the only function we need to handle.

Copy link
Contributor

@eurekaka eurekaka Apr 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An off-topic finding: concat seems to have bug currently

mysql> select concat(a+b) from t;
ERROR 1054 (42S22): Unknown column 'b' in 'field list'
mysql> select concat(a, b) from t;
ERROR 1054 (42S22): Unknown column 'b' in 'field list'
mysql> select unix_timestamp(concat(a+b)) from t;
ERROR 1054 (42S22): Unknown column 'b' in 'field list'

it reports error in parser.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eurekaka
Do you forget the column b when create table t?

mysql> create table t(a int, b int);
Query OK, 0 rows affected (0.04 sec)

mysql> select concat(a+b) from t;
Empty set (0.00 sec)

mysql> select concat(a, b) from t;
Empty set (0.01 sec)

mysql> select unix_timestamp(concat(a+b)) from t;
Empty set (0.01 sec)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭 My fault.

if err != nil {
return nil, err
}
Expand Down
16 changes: 16 additions & 0 deletions expression/builtin_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,22 @@ func (s *testEvaluatorSuite) TestUnixTimestamp(c *C) {
c.Assert(err, IsNil)
c.Assert(d.IsNull(), Equals, true)

// https://github.com/pingcap/tidb/issues/9729
// Test UNIX_TIMESTAMP(@a).
resetStmtContext(s.ctx)
s.ctx.GetSessionVars().Users["a"] = "1970-01-01 08:00:01"
args = []types.Datum{types.NewStringDatum("a")}
getVarFunc, err := newFunctionForTest(s.ctx, ast.GetVar, s.datumsToConstants(args)...)
c.Assert(err, IsNil)
funcArgs := make([]Expression, 0, 1)
funcArgs = append(funcArgs, getVarFunc)
f, err = fc.getFunction(s.ctx, funcArgs)
c.Assert(err, IsNil)
d, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(d.Kind(), Equals, types.KindInt64)
c.Assert(d.GetInt64(), Equals, int64(28801))

// Set the time_zone variable, because UnixTimestamp() result depends on it.
s.ctx.GetSessionVars().TimeZone = time.UTC
tests := []struct {
Expand Down