From f1400e9feb8fdf851324483b93f4258c27963f10 Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 13:37:46 +0800 Subject: [PATCH 1/7] expression: make current_timestamp follow fsp rule. --- expression/helper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/expression/helper.go b/expression/helper.go index a7bc83fcb7770..b419a31d13ffb 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -16,6 +16,7 @@ package expression import ( "strings" "time" + "math" "github.com/juju/errors" "github.com/pingcap/tidb/ast" @@ -57,7 +58,7 @@ func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d ty case string: upperX := strings.ToUpper(x) if upperX == strings.ToUpper(ast.CurrentTimestamp) { - value.Time = types.FromGoTime(defaultTime) + value.Time = types.FromGoTime(defaultTime.Truncate(time.Duration(math.Pow10(9-fsp)) * time.Nanosecond)) if tp == mysql.TypeTimestamp { err = value.ConvertTimeZone(time.Local, ctx.GetSessionVars().Location()) if err != nil { From df8a80207872067859c0cdaba57ba3cc701f1578 Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 16:49:38 +0800 Subject: [PATCH 2/7] ddl,parser: add check current_timestamp(x) args. --- ddl/ddl_api.go | 30 ++++++++++++++++++++++++++---- expression/helper.go | 2 +- parser/parser.y | 4 ++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index fe163c5f16007..67ddea382f6ea 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -600,7 +600,7 @@ func checkTooManyColumns(colDefs []*ast.ColumnDef) error { // checkColumnsAttributes checks attributes for multiple columns. func checkColumnsAttributes(colDefs []*ast.ColumnDef) error { for _, colDef := range colDefs { - if err := checkColumnAttributes(colDef.Name.OrigColName(), colDef.Tp); err != nil { + if err := checkColumnAttributes(colDef.Name.OrigColName(), colDef.Tp, colDef.Options); err != nil { return errors.Trace(err) } } @@ -608,7 +608,7 @@ func checkColumnsAttributes(colDefs []*ast.ColumnDef) error { } // checkColumnAttributes check attributes for single column. -func checkColumnAttributes(colName string, tp *types.FieldType) error { +func checkColumnAttributes(colName string, tp *types.FieldType, options []*ast.ColumnOption) error { switch tp.Tp { case mysql.TypeNewDecimal, mysql.TypeDouble, mysql.TypeFloat: if tp.Flen < tp.Decimal { @@ -618,6 +618,28 @@ func checkColumnAttributes(colName string, tp *types.FieldType) error { if tp.Decimal != types.UnspecifiedFsp && (tp.Decimal < types.MinFsp || tp.Decimal > types.MaxFsp) { return types.ErrTooBigPrecision.GenByArgs(tp.Decimal, colName, types.MaxFsp) } + if tp.Tp == mysql.TypeTimestamp { + columnFsp := uint64(tp.Decimal) + if tp.Decimal < 0 { + columnFsp = 0 + } + for _, option := range options { + if !expression.IsCurrentTimestampExpr(option.Expr) { + continue + } + fc, ok := option.Expr.(*ast.FuncCallExpr) + if !ok { + continue + } + funcFsp := uint64(0) + if fc.Args != nil && len(fc.Args) > 0 { + funcFsp = fc.Args[0].GetValue().(uint64) + } + if funcFsp != columnFsp { + return types.ErrInvalidDefault.GenByArgs(colName) + } + } + } } return nil } @@ -1197,7 +1219,7 @@ func (d *ddl) AddColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTab } colName := specNewColumn.Name.Name.O - if err = checkColumnAttributes(colName, specNewColumn.Tp); err != nil { + if err = checkColumnAttributes(colName, specNewColumn.Tp, specNewColumn.Options); err != nil { return errors.Trace(err) } @@ -1573,7 +1595,7 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or return nil, errors.Trace(errUnsupportedModifyColumn) } - if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp); err != nil { + if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp, specNewColumn.Options); err != nil { return nil, errors.Trace(err) } diff --git a/expression/helper.go b/expression/helper.go index b419a31d13ffb..813f45e903c85 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -14,9 +14,9 @@ package expression import ( + "math" "strings" "time" - "math" "github.com/juju/errors" "github.com/pingcap/tidb/ast" diff --git a/parser/parser.y b/parser/parser.y index 80b283c5a9a53..f7f56eb493de9 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -1376,7 +1376,7 @@ ColumnOption: } | "ON" "UPDATE" NowSymOptionFraction { - nowFunc := &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + nowFunc := $3 $$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} } | "COMMENT" stringLit @@ -1600,7 +1600,7 @@ NowSymOptionFraction: } | NowSymFunc '(' NUM ')' { - $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} } /* From 2adb29b9fa042918bc0a807075c4e92bc079e20a Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 17:22:31 +0800 Subject: [PATCH 3/7] ddl: on update function limit & add testcase for ddl --- ddl/db_test.go | 17 ++++++++++++++++- parser/parser.y | 19 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/ddl/db_test.go b/ddl/db_test.go index 69921cb423071..4cac7689f5234 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -1760,7 +1760,22 @@ func (s *testDBSuite) TestTableDDLWithTimeType(c *C) { s.testErrorCode(c, "alter table t change column a aa time(7)", tmysql.ErrTooBigPrecision) s.testErrorCode(c, "alter table t change column a aa datetime(7)", tmysql.ErrTooBigPrecision) s.testErrorCode(c, "alter table t change column a aa timestamp(7)", tmysql.ErrTooBigPrecision) - s.mustExec(c, "alter table t change column a aa timestamp(0)") + s.mustExec(c, "alter table t change column a aa datetime(0)") + s.mustExec(c, "drop table t") + + s.testErrorCode(c, "create table t (a timestamp null default current_timestamp(3))", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp(2) null default current_timestamp(3))", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp(0) null default current_timestamp(3))", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp(0) null default now(3))", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp null default current_timestamp(3))", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp)", tmysql.ErrInvalidDefault) + s.testErrorCode(c, "create table t (a timestamp(3) null default localtimestamp(3) on update localtimestamp)", tmysql.ErrInvalidDefault) + _, err = s.tk.Exec("create table t (a timestamp(3) null default localtimestamp(3) on update now(3))") + c.Assert(err, NotNil) + _, err = s.tk.Exec("create table t (a timestamp(3) null default localtimestamp(3) on update localtime(3))") + c.Assert(err, NotNil) + s.mustExec(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp(3))") + s.mustExec(c, "create table t2 (a timestamp null default current_timestamp() on update current_timestamp)") s.mustExec(c, "drop table t") } diff --git a/parser/parser.y b/parser/parser.y index f7f56eb493de9..47481733882e8 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -519,6 +519,7 @@ import ( SignedLiteral "Literal or NumLiteral with sign" DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)" NowSymOptionFraction "NowSym with optional fraction part" + OnUpdateNowSymOptionFraction "NowSync with optional fraction part in on update" %type AdminStmt "Check table statement or show ddl statement" @@ -1374,7 +1375,7 @@ ColumnOption: { $$ = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: $2} } -| "ON" "UPDATE" NowSymOptionFraction +| "ON" "UPDATE" OnUpdateNowSymOptionFraction { nowFunc := $3 $$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} @@ -1603,6 +1604,20 @@ NowSymOptionFraction: $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} } +OnUpdateNowSymOptionFraction: + OnUpdateNowSym + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } +| OnUpdateNowSym '(' ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } +| OnUpdateNowSym '(' NUM ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} + } + /* * See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_localtime * TODO: Process other three keywords @@ -1611,6 +1626,8 @@ NowSymFunc: "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" | builtinNow NowSym: "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" +OnUpdateNowSym: + "CURRENT_TIMESTAMP" | "LOCALTIMESTAMP" SignedLiteral: From 11d53d1af520aa5342de42c65e102249cde679c7 Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 18:43:55 +0800 Subject: [PATCH 4/7] test: add testcase for current_timestamp insert/selection --- executor/executor_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/executor/executor_test.go b/executor/executor_test.go index e2e53470e550e..ae0156ea61570 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -3088,3 +3088,37 @@ func (s *testSuite) TestMaxOneRow(c *C) { err = rs.Close() c.Assert(err, IsNil) } + +func (s *testSuite) TestCurrentTimestampValueSelection(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t,t1") + + tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))") + tk.MustExec("insert into t (id) values (1)") + rs := tk.MustQuery("select t0, t1, t2 from t where id = 1") + t0 := rs.Rows()[0][0].(string) + t1 := rs.Rows()[0][1].(string) + t2 := rs.Rows()[0][2].(string) + c.Assert(len(strings.Split(t0, ".")), Equals, 1) + c.Assert(len(strings.Split(t1, ".")[1]), Equals, 1) + c.Assert(len(strings.Split(t2, ".")[1]), Equals, 2) + tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1")) + time.Sleep(time.Second / 2) + tk.MustExec("update t set t0 = now() where id = 1") + rs = tk.MustQuery("select t2 from t where id = 1") + newT2 := rs.Rows()[0][0].(string) + c.Assert(newT2 != t2, IsTrue) + + tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))") + tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))") + rs = tk.MustQuery("select a, b, c from t1 where id = 1") + a := rs.Rows()[0][0].(string) + b := rs.Rows()[0][1].(string) + d := rs.Rows()[0][2].(string) + c.Assert(len(strings.Split(a, ".")), Equals, 1) + c.Assert(strings.Split(b, ".")[1], Equals, "00") + c.Assert(len(strings.Split(d, ".")[1]), Equals, 3) +} From a7f6bc54ecfd8108d66eed96a4b716f247ece9f6 Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 19:59:22 +0800 Subject: [PATCH 5/7] revert: old logic is right. --- ddl/db_test.go | 4 ---- parser/parser.y | 19 +------------------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/ddl/db_test.go b/ddl/db_test.go index 4cac7689f5234..255a778afae3f 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -1770,10 +1770,6 @@ func (s *testDBSuite) TestTableDDLWithTimeType(c *C) { s.testErrorCode(c, "create table t (a timestamp null default current_timestamp(3))", tmysql.ErrInvalidDefault) s.testErrorCode(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp)", tmysql.ErrInvalidDefault) s.testErrorCode(c, "create table t (a timestamp(3) null default localtimestamp(3) on update localtimestamp)", tmysql.ErrInvalidDefault) - _, err = s.tk.Exec("create table t (a timestamp(3) null default localtimestamp(3) on update now(3))") - c.Assert(err, NotNil) - _, err = s.tk.Exec("create table t (a timestamp(3) null default localtimestamp(3) on update localtime(3))") - c.Assert(err, NotNil) s.mustExec(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp(3))") s.mustExec(c, "create table t2 (a timestamp null default current_timestamp() on update current_timestamp)") s.mustExec(c, "drop table t") diff --git a/parser/parser.y b/parser/parser.y index 47481733882e8..f7f56eb493de9 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -519,7 +519,6 @@ import ( SignedLiteral "Literal or NumLiteral with sign" DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)" NowSymOptionFraction "NowSym with optional fraction part" - OnUpdateNowSymOptionFraction "NowSync with optional fraction part in on update" %type AdminStmt "Check table statement or show ddl statement" @@ -1375,7 +1374,7 @@ ColumnOption: { $$ = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: $2} } -| "ON" "UPDATE" OnUpdateNowSymOptionFraction +| "ON" "UPDATE" NowSymOptionFraction { nowFunc := $3 $$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} @@ -1604,20 +1603,6 @@ NowSymOptionFraction: $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} } -OnUpdateNowSymOptionFraction: - OnUpdateNowSym - { - $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} - } -| OnUpdateNowSym '(' ')' - { - $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} - } -| OnUpdateNowSym '(' NUM ')' - { - $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} - } - /* * See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_localtime * TODO: Process other three keywords @@ -1626,8 +1611,6 @@ NowSymFunc: "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" | builtinNow NowSym: "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" -OnUpdateNowSym: - "CURRENT_TIMESTAMP" | "LOCALTIMESTAMP" SignedLiteral: From 1577ef3e3de06aae9c7f5249f021c4a3076ac1cc Mon Sep 17 00:00:00 2001 From: robi Date: Fri, 10 Aug 2018 20:09:37 +0800 Subject: [PATCH 6/7] revert: fix explain's wrong use. --- cmd/explaintest/r/topn_push_down.result | 20 ++++++++++---------- cmd/explaintest/t/topn_push_down.test | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cmd/explaintest/r/topn_push_down.result b/cmd/explaintest/r/topn_push_down.result index 65992f23cfadd..e332cbc4c4a84 100644 --- a/cmd/explaintest/r/topn_push_down.result +++ b/cmd/explaintest/r/topn_push_down.result @@ -4,7 +4,7 @@ CREATE TABLE `tr` ( `domain_type` tinyint(4) NOT NULL, `business_type` tinyint(4) NOT NULL, `trade_type` tinyint(4) NOT NULL DEFAULT '1', -`trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `trade_status` tinyint(4) NOT NULL DEFAULT '0', `trade_pay_status` tinyint(4) NOT NULL DEFAULT '0', `delivery_type` tinyint(4) NOT NULL DEFAULT '0', @@ -24,10 +24,10 @@ CREATE TABLE `tr` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -66,10 +66,10 @@ CREATE TABLE `p` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL DEFAULT '1', -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -117,10 +117,10 @@ CREATE TABLE `te` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, diff --git a/cmd/explaintest/t/topn_push_down.test b/cmd/explaintest/t/topn_push_down.test index 5ae400aa49227..bc45575ba7f68 100644 --- a/cmd/explaintest/t/topn_push_down.test +++ b/cmd/explaintest/t/topn_push_down.test @@ -4,7 +4,7 @@ CREATE TABLE `tr` ( `domain_type` tinyint(4) NOT NULL, `business_type` tinyint(4) NOT NULL, `trade_type` tinyint(4) NOT NULL DEFAULT '1', - `trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `trade_status` tinyint(4) NOT NULL DEFAULT '0', `trade_pay_status` tinyint(4) NOT NULL DEFAULT '0', `delivery_type` tinyint(4) NOT NULL DEFAULT '0', @@ -24,10 +24,10 @@ CREATE TABLE `tr` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -68,10 +68,10 @@ CREATE TABLE `p` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL DEFAULT '1', - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -121,10 +121,10 @@ CREATE TABLE `te` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, From cddffd865bc200585c2b3ee26df6aaf7716698c1 Mon Sep 17 00:00:00 2001 From: robi Date: Mon, 13 Aug 2018 14:12:08 +0800 Subject: [PATCH 7/7] address comment, doesn't break backward compatible --- cmd/explaintest/r/topn_push_down.result | 20 ++++++++--------- cmd/explaintest/t/topn_push_down.test | 20 ++++++++--------- ddl/db_test.go | 11 --------- ddl/ddl_api.go | 30 ++++--------------------- parser/parser.y | 4 ++-- 5 files changed, 26 insertions(+), 59 deletions(-) diff --git a/cmd/explaintest/r/topn_push_down.result b/cmd/explaintest/r/topn_push_down.result index e332cbc4c4a84..65992f23cfadd 100644 --- a/cmd/explaintest/r/topn_push_down.result +++ b/cmd/explaintest/r/topn_push_down.result @@ -4,7 +4,7 @@ CREATE TABLE `tr` ( `domain_type` tinyint(4) NOT NULL, `business_type` tinyint(4) NOT NULL, `trade_type` tinyint(4) NOT NULL DEFAULT '1', -`trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `trade_status` tinyint(4) NOT NULL DEFAULT '0', `trade_pay_status` tinyint(4) NOT NULL DEFAULT '0', `delivery_type` tinyint(4) NOT NULL DEFAULT '0', @@ -24,10 +24,10 @@ CREATE TABLE `tr` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -66,10 +66,10 @@ CREATE TABLE `p` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL DEFAULT '1', -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -117,10 +117,10 @@ CREATE TABLE `te` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, -`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +`client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, -`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), -`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), +`server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +`server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, diff --git a/cmd/explaintest/t/topn_push_down.test b/cmd/explaintest/t/topn_push_down.test index bc45575ba7f68..5ae400aa49227 100644 --- a/cmd/explaintest/t/topn_push_down.test +++ b/cmd/explaintest/t/topn_push_down.test @@ -4,7 +4,7 @@ CREATE TABLE `tr` ( `domain_type` tinyint(4) NOT NULL, `business_type` tinyint(4) NOT NULL, `trade_type` tinyint(4) NOT NULL DEFAULT '1', - `trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `trade_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `trade_status` tinyint(4) NOT NULL DEFAULT '0', `trade_pay_status` tinyint(4) NOT NULL DEFAULT '0', `delivery_type` tinyint(4) NOT NULL DEFAULT '0', @@ -24,10 +24,10 @@ CREATE TABLE `tr` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -68,10 +68,10 @@ CREATE TABLE `p` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL DEFAULT '1', - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, @@ -121,10 +121,10 @@ CREATE TABLE `te` ( `device_identy` varchar(36) NOT NULL, `uuid` varchar(32) NOT NULL, `status_flag` tinyint(4) NOT NULL, - `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `client_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, `client_update_time` timestamp(3) NULL DEFAULT NULL, - `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + `server_create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `server_update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `creator_id` bigint(20) DEFAULT NULL, `creator_name` varchar(32) DEFAULT NULL, `updator_id` bigint(20) DEFAULT NULL, diff --git a/ddl/db_test.go b/ddl/db_test.go index 255a778afae3f..e134ddadbc615 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -1762,17 +1762,6 @@ func (s *testDBSuite) TestTableDDLWithTimeType(c *C) { s.testErrorCode(c, "alter table t change column a aa timestamp(7)", tmysql.ErrTooBigPrecision) s.mustExec(c, "alter table t change column a aa datetime(0)") s.mustExec(c, "drop table t") - - s.testErrorCode(c, "create table t (a timestamp null default current_timestamp(3))", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp(2) null default current_timestamp(3))", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp(0) null default current_timestamp(3))", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp(0) null default now(3))", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp null default current_timestamp(3))", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp)", tmysql.ErrInvalidDefault) - s.testErrorCode(c, "create table t (a timestamp(3) null default localtimestamp(3) on update localtimestamp)", tmysql.ErrInvalidDefault) - s.mustExec(c, "create table t (a timestamp(3) null default current_timestamp(3) on update current_timestamp(3))") - s.mustExec(c, "create table t2 (a timestamp null default current_timestamp() on update current_timestamp)") - s.mustExec(c, "drop table t") } func (s *testDBSuite) TestTruncateTable(c *C) { diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 67ddea382f6ea..fe163c5f16007 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -600,7 +600,7 @@ func checkTooManyColumns(colDefs []*ast.ColumnDef) error { // checkColumnsAttributes checks attributes for multiple columns. func checkColumnsAttributes(colDefs []*ast.ColumnDef) error { for _, colDef := range colDefs { - if err := checkColumnAttributes(colDef.Name.OrigColName(), colDef.Tp, colDef.Options); err != nil { + if err := checkColumnAttributes(colDef.Name.OrigColName(), colDef.Tp); err != nil { return errors.Trace(err) } } @@ -608,7 +608,7 @@ func checkColumnsAttributes(colDefs []*ast.ColumnDef) error { } // checkColumnAttributes check attributes for single column. -func checkColumnAttributes(colName string, tp *types.FieldType, options []*ast.ColumnOption) error { +func checkColumnAttributes(colName string, tp *types.FieldType) error { switch tp.Tp { case mysql.TypeNewDecimal, mysql.TypeDouble, mysql.TypeFloat: if tp.Flen < tp.Decimal { @@ -618,28 +618,6 @@ func checkColumnAttributes(colName string, tp *types.FieldType, options []*ast.C if tp.Decimal != types.UnspecifiedFsp && (tp.Decimal < types.MinFsp || tp.Decimal > types.MaxFsp) { return types.ErrTooBigPrecision.GenByArgs(tp.Decimal, colName, types.MaxFsp) } - if tp.Tp == mysql.TypeTimestamp { - columnFsp := uint64(tp.Decimal) - if tp.Decimal < 0 { - columnFsp = 0 - } - for _, option := range options { - if !expression.IsCurrentTimestampExpr(option.Expr) { - continue - } - fc, ok := option.Expr.(*ast.FuncCallExpr) - if !ok { - continue - } - funcFsp := uint64(0) - if fc.Args != nil && len(fc.Args) > 0 { - funcFsp = fc.Args[0].GetValue().(uint64) - } - if funcFsp != columnFsp { - return types.ErrInvalidDefault.GenByArgs(colName) - } - } - } } return nil } @@ -1219,7 +1197,7 @@ func (d *ddl) AddColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTab } colName := specNewColumn.Name.Name.O - if err = checkColumnAttributes(colName, specNewColumn.Tp, specNewColumn.Options); err != nil { + if err = checkColumnAttributes(colName, specNewColumn.Tp); err != nil { return errors.Trace(err) } @@ -1595,7 +1573,7 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or return nil, errors.Trace(errUnsupportedModifyColumn) } - if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp, specNewColumn.Options); err != nil { + if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp); err != nil { return nil, errors.Trace(err) } diff --git a/parser/parser.y b/parser/parser.y index f7f56eb493de9..80b283c5a9a53 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -1376,7 +1376,7 @@ ColumnOption: } | "ON" "UPDATE" NowSymOptionFraction { - nowFunc := $3 + nowFunc := &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} $$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} } | "COMMENT" stringLit @@ -1600,7 +1600,7 @@ NowSymOptionFraction: } | NowSymFunc '(' NUM ')' { - $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(getUint64FromNUM($3))}} + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} } /*