From d5163d224e2127813b1d370fe679628e745b98d9 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 29 Jul 2019 00:29:38 +0800 Subject: [PATCH 1/7] executor, infoschema: fix display of on update CURRENT_TIMESTAMP with decimal --- ddl/ddl_api.go | 4 ++-- executor/show.go | 1 + executor/show_test.go | 10 ++++++++-- expression/helper.go | 21 ++++++++++++++++----- expression/helper_test.go | 15 ++++++++++++--- table/column.go | 13 ++++++++++++- 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 627ee59eaf2c8..6f0b6f82bde95 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -523,7 +523,7 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o case ast.ColumnOptionOnUpdate: // TODO: Support other time functions. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { - if !expression.IsCurrentTimestampExpr(v.Expr) { + if !expression.IsValidCurrentTimestampExpr(v.Expr, colDef.Tp) { return nil, nil, ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { @@ -2447,7 +2447,7 @@ func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []* case ast.ColumnOptionOnUpdate: // TODO: Support other time functions. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { - if !expression.IsCurrentTimestampExpr(opt.Expr) { + if !expression.IsValidCurrentTimestampExpr(opt.Expr, &col.FieldType) { return ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { diff --git a/executor/show.go b/executor/show.go index f2b4cf0470978..ed0864cb22f2f 100644 --- a/executor/show.go +++ b/executor/show.go @@ -721,6 +721,7 @@ func (e *ShowExec) fetchShowCreateTable() error { } if mysql.HasOnUpdateNowFlag(col.Flag) { buf.WriteString(" ON UPDATE CURRENT_TIMESTAMP") + buf.WriteString(table.OptionalFsp(&col.FieldType)) } } if len(col.Comment) > 0 { diff --git a/executor/show_test.go b/executor/show_test.go index c7306f63cd44d..6d0eefe75e991 100644 --- a/executor/show_test.go +++ b/executor/show_test.go @@ -198,6 +198,7 @@ func (s *testSuite2) TestShow2(c *C) { c_timestamp timestamp, c_timestamp_default timestamp default current_timestamp, c_timestamp_default_3 timestamp(3) default current_timestamp(3), + c_timestamp_default_4 timestamp(3) default current_timestamp(3) on update current_timestamp(3), c_blob blob, c_tinyblob tinyblob, c_mediumblob mediumblob, @@ -233,6 +234,7 @@ func (s *testSuite2) TestShow2(c *C) { "[c_timestamp timestamp YES select,insert,update,references ]\n" + "[c_timestamp_default timestamp YES CURRENT_TIMESTAMP select,insert,update,references ]\n" + "[c_timestamp_default_3 timestamp(3) YES CURRENT_TIMESTAMP(3) select,insert,update,references ]\n" + + "[c_timestamp_default_4 timestamp(3) YES CURRENT_TIMESTAMP(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3) select,insert,update,references ]\n" + "[c_blob blob YES select,insert,update,references ]\n" + "[c_tinyblob tinyblob YES select,insert,update,references ]\n" + "[c_mediumblob mediumblob YES select,insert,update,references ]\n" + @@ -488,7 +490,9 @@ func (s *testSuite2) TestShowCreateTable(c *C) { "`b` timestamp(3) default current_timestamp(3),\n" + "`c` datetime default current_timestamp,\n" + "`d` datetime(4) default current_timestamp(4),\n" + - "`e` varchar(20) default 'cUrrent_tImestamp')") + "`e` varchar(20) default 'cUrrent_tImestamp',\n" + + "`f` datetime(2) default current_timestamp(2) on update current_timestamp(2),\n" + + "`g` timestamp(2) default current_timestamp(2) on update current_timestamp(2))") tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ @@ -496,7 +500,9 @@ func (s *testSuite2) TestShowCreateTable(c *C) { " `b` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3),\n"+ " `c` datetime DEFAULT CURRENT_TIMESTAMP,\n"+ " `d` datetime(4) DEFAULT CURRENT_TIMESTAMP(4),\n"+ - " `e` varchar(20) DEFAULT 'cUrrent_tImestamp'\n"+ + " `e` varchar(20) DEFAULT 'cUrrent_tImestamp',\n"+ + " `f` datetime(2) DEFAULT CURRENT_TIMESTAMP(2) ON UPDATE CURRENT_TIMESTAMP(2),\n"+ + " `g` timestamp(2) DEFAULT CURRENT_TIMESTAMP(2) ON UPDATE CURRENT_TIMESTAMP(2)\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", )) tk.MustExec("drop table t") diff --git a/expression/helper.go b/expression/helper.go index cd150fcb6cc84..dac97b82b8ff6 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -34,12 +34,23 @@ func boolToInt64(v bool) int64 { return 0 } -// IsCurrentTimestampExpr returns whether e is CurrentTimestamp expression. -func IsCurrentTimestampExpr(e ast.ExprNode) bool { - if fn, ok := e.(*ast.FuncCallExpr); ok && fn.FnName.L == ast.CurrentTimestamp { - return true +// IsValidCurrentTimestampExpr returns whether e is a valid CurrentTimestamp expression. +// Here `valid` means it is consistent with the given fieldType's Decimal. +func IsValidCurrentTimestampExpr(exprNode ast.ExprNode, fieldType *types.FieldType) bool { + fn, isFuncCall := exprNode.(*ast.FuncCallExpr) + if !isFuncCall || fn.FnName.L != ast.CurrentTimestamp { + return false } - return false + + containsArg := len(fn.Args) > 0 + containsFsp := fieldType != nil && fieldType.Decimal > 0 // Fsp represents fractional seconds precision. + var isConsistent bool + if containsArg { + v, ok := fn.Args[0].(*driver.ValueExpr) + isConsistent = ok && fieldType != nil && v.Datum.GetInt64() == int64(fieldType.Decimal) + } + + return (containsArg && isConsistent) || (!containsArg && !containsFsp) } // GetTimeValue gets the time value with type tp. diff --git a/expression/helper_test.go b/expression/helper_test.go index e0acecfdf817b..da9a92a1971c3 100644 --- a/expression/helper_test.go +++ b/expression/helper_test.go @@ -108,11 +108,20 @@ func (s *testExpressionSuite) TestGetTimeValue(c *C) { func (s *testExpressionSuite) TestIsCurrentTimestampExpr(c *C) { defer testleak.AfterTest(c)() - v := IsCurrentTimestampExpr(ast.NewValueExpr("abc")) + v := IsValidCurrentTimestampExpr(ast.NewValueExpr("abc"), nil) c.Assert(v, IsFalse) - - v = IsCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}, nil) + c.Assert(v, IsTrue) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(3)")}, &types.FieldType{Decimal: 3}) c.Assert(v, IsTrue) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(1)")}, &types.FieldType{Decimal: 3}) + c.Assert(v, IsFalse) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}, &types.FieldType{Decimal: 3}) + c.Assert(v, IsFalse) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(2)")}, &types.FieldType{Decimal: 0}) + c.Assert(v, IsFalse) + v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(2)")}, nil) + c.Assert(v, IsFalse) } func (s *testExpressionSuite) TestCurrentTimestampTimeZone(c *C) { diff --git a/table/column.go b/table/column.go index 08f4884ad5d9c..f11debce30efa 100644 --- a/table/column.go +++ b/table/column.go @@ -20,6 +20,7 @@ package table import ( "context" "fmt" + "strconv" "strings" "time" "unicode/utf8" @@ -272,7 +273,7 @@ func NewColDesc(col *Column) *ColDesc { } else if mysql.HasOnUpdateNowFlag(col.Flag) { //in order to match the rules of mysql 8.0.16 version //see https://github.com/pingcap/tidb/issues/10337 - extra = "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + extra = "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + OptionalFsp(&col.FieldType) } else if col.IsGenerated() { if col.GeneratedStored { extra = "STORED GENERATED" @@ -494,3 +495,13 @@ func GetZeroValue(col *model.ColumnInfo) types.Datum { } return d } + +// OptionalFsp convert a FieldType.Decimal to string. +func OptionalFsp(fieldType *types.FieldType) string { + fsp := fieldType.Decimal + if fsp == 0 { + return "" + } else { + return "(" + strconv.Itoa(fsp) + ")" + } +} From 2fe812193357e2198aa50a2b732c68f0a348ae96 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 29 Jul 2019 10:04:56 +0800 Subject: [PATCH 2/7] fix isValidTimestampExpr test --- expression/helper_test.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/expression/helper_test.go b/expression/helper_test.go index da9a92a1971c3..21db9667f1063 100644 --- a/expression/helper_test.go +++ b/expression/helper_test.go @@ -14,6 +14,7 @@ package expression import ( + driver "github.com/pingcap/tidb/types/parser_driver" "strings" "time" @@ -108,19 +109,27 @@ func (s *testExpressionSuite) TestGetTimeValue(c *C) { func (s *testExpressionSuite) TestIsCurrentTimestampExpr(c *C) { defer testleak.AfterTest(c)() + buildTimestampFuncCallExpr := func(i int64) *ast.FuncCallExpr { + var args []ast.ExprNode + if i != 0 { + args = []ast.ExprNode{&driver.ValueExpr{Datum: types.NewIntDatum(i)}} + } + return &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: args} + } + v := IsValidCurrentTimestampExpr(ast.NewValueExpr("abc"), nil) c.Assert(v, IsFalse) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}, nil) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(0), nil) c.Assert(v, IsTrue) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(3)")}, &types.FieldType{Decimal: 3}) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(3), &types.FieldType{Decimal: 3}) c.Assert(v, IsTrue) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(1)")}, &types.FieldType{Decimal: 3}) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(1), &types.FieldType{Decimal: 3}) c.Assert(v, IsFalse) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}, &types.FieldType{Decimal: 3}) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(0), &types.FieldType{Decimal: 3}) c.Assert(v, IsFalse) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(2)")}, &types.FieldType{Decimal: 0}) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(2), &types.FieldType{Decimal: 0}) c.Assert(v, IsFalse) - v = IsValidCurrentTimestampExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP(2)")}, nil) + v = IsValidCurrentTimestampExpr(buildTimestampFuncCallExpr(2), nil) c.Assert(v, IsFalse) } From 038840ec7ab4c20a68d6c08df62e98ceece32ef3 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 29 Jul 2019 10:21:24 +0800 Subject: [PATCH 3/7] fix linter --- table/column.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/table/column.go b/table/column.go index f11debce30efa..0db5313aa21ce 100644 --- a/table/column.go +++ b/table/column.go @@ -501,7 +501,6 @@ func OptionalFsp(fieldType *types.FieldType) string { fsp := fieldType.Decimal if fsp == 0 { return "" - } else { - return "(" + strconv.Itoa(fsp) + ")" } + return "(" + strconv.Itoa(fsp) + ")" } From 8b61780ba407b6289c2cf1522409adf9f3b1e061 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 29 Jul 2019 11:09:32 +0800 Subject: [PATCH 4/7] add tests for invalid case --- ddl/db_integration_test.go | 8 ++++++++ expression/helper.go | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 5d9574271d37e..00cd3f08ff8a3 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -428,6 +428,14 @@ func (s *testIntegrationSuite5) TestMySQLErrorCode(c *C) { assertErrorCode(c, tk, sql, tmysql.ErrPrimaryCantHaveNull) sql = "create table t2 (id int auto_increment);" assertErrorCode(c, tk, sql, tmysql.ErrWrongAutoKey) + sql = "create table t2 (a datetime(2) default current_timestamp(3))" + assertErrorCode(c, tk, sql, tmysql.ErrInvalidDefault) + sql = "create table t2 (a datetime(2) default current_timestamp(2) on update current_timestamp)" + assertErrorCode(c, tk, sql, tmysql.ErrInvalidOnUpdate) + sql = "create table t2 (a datetime default current_timestamp on update current_timestamp(2))" + assertErrorCode(c, tk, sql, tmysql.ErrInvalidOnUpdate) + sql = "create table t2 (a datetime(2) default current_timestamp(2) on update current_timestamp(3))" + assertErrorCode(c, tk, sql, tmysql.ErrInvalidOnUpdate) sql = "create table t2 (id int primary key , age int);" tk.MustExec(sql) diff --git a/expression/helper.go b/expression/helper.go index dac97b82b8ff6..0c3cedc2275c0 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -43,7 +43,8 @@ func IsValidCurrentTimestampExpr(exprNode ast.ExprNode, fieldType *types.FieldTy } containsArg := len(fn.Args) > 0 - containsFsp := fieldType != nil && fieldType.Decimal > 0 // Fsp represents fractional seconds precision. + // Fsp represents fractional seconds precision. + containsFsp := fieldType != nil && fieldType.Decimal > 0 var isConsistent bool if containsArg { v, ok := fn.Args[0].(*driver.ValueExpr) From 60eee297accd83b974c6746274fc8d412e4515f9 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 29 Jul 2019 12:59:12 +0800 Subject: [PATCH 5/7] address comment --- expression/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/expression/helper.go b/expression/helper.go index 0c3cedc2275c0..307c2aba9cad3 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -34,7 +34,7 @@ func boolToInt64(v bool) int64 { return 0 } -// IsValidCurrentTimestampExpr returns whether e is a valid CurrentTimestamp expression. +// IsValidCurrentTimestampExpr returns true if exprNode is a valid CurrentTimestamp expression. // Here `valid` means it is consistent with the given fieldType's Decimal. func IsValidCurrentTimestampExpr(exprNode ast.ExprNode, fieldType *types.FieldType) bool { fn, isFuncCall := exprNode.(*ast.FuncCallExpr) From e82c672b8618cea6ea67fb81dcc4abd707755ed6 Mon Sep 17 00:00:00 2001 From: tangenta Date: Wed, 31 Jul 2019 16:10:54 +0800 Subject: [PATCH 6/7] add more tests --- ddl/db_integration_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 00cd3f08ff8a3..91106701e5133 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1856,3 +1856,21 @@ func (s *testIntegrationSuite4) TestDropAutoIncrementIndex(c *C) { dropIndexSQL = "alter table t1 drop index a" assertErrorCode(c, tk, dropIndexSQL, mysql.ErrWrongAutoKey) } + +func (s *testIntegrationSuite4) TestOnUpdateCurrentTimestamp(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("drop database if exists test_on_update_timestamp") + tk.MustExec("create database test_on_update_timestamp") + tk.MustExec("use test_on_update_timestamp") + tk.MustExec("create table timestamp_table (a datetime not null default current_timestamp on update current_timestamp, " + + "b datetime(3) not null default current_timestamp(3) on update current_timestamp(3))") + tk.MustQuery("show full columns from timestamp_table").Check(testkit.Rows( + "a datetime NO CURRENT_TIMESTAMP DEFAULT_GENERATED on update CURRENT_TIMESTAMP select,insert,update,references ", + "b datetime(3) NO CURRENT_TIMESTAMP(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3) select,insert,update,references ")) + tk.MustQuery("select * from information_schema.columns where table_name = 'timestamp_table' and column_name='a'").Check(testkit.Rows( + "def test_on_update_timestamp timestamp_table a 1 CURRENT_TIMESTAMP NO datetime 0 " + + " datetime DEFAULT_GENERATED on update CURRENT_TIMESTAMP select,insert,update,references ")) + tk.MustQuery("select * from information_schema.columns where table_name = 'timestamp_table' and column_name='b'").Check(testkit.Rows( + "def test_on_update_timestamp timestamp_table b 2 CURRENT_TIMESTAMP(3) NO datetime 3 " + + " datetime(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3) select,insert,update,references ")) +} From 0f3f4eab57762f7a5165a38ef33e393d743134f8 Mon Sep 17 00:00:00 2001 From: tangenta Date: Fri, 2 Aug 2019 16:24:29 +0800 Subject: [PATCH 7/7] move tests from db_integration to infoschema/tables_test --- ddl/db_integration_test.go | 18 ------------------ infoschema/tables_test.go | 24 ++++++++++++++---------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 91106701e5133..00cd3f08ff8a3 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1856,21 +1856,3 @@ func (s *testIntegrationSuite4) TestDropAutoIncrementIndex(c *C) { dropIndexSQL = "alter table t1 drop index a" assertErrorCode(c, tk, dropIndexSQL, mysql.ErrWrongAutoKey) } - -func (s *testIntegrationSuite4) TestOnUpdateCurrentTimestamp(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_on_update_timestamp") - tk.MustExec("create database test_on_update_timestamp") - tk.MustExec("use test_on_update_timestamp") - tk.MustExec("create table timestamp_table (a datetime not null default current_timestamp on update current_timestamp, " + - "b datetime(3) not null default current_timestamp(3) on update current_timestamp(3))") - tk.MustQuery("show full columns from timestamp_table").Check(testkit.Rows( - "a datetime NO CURRENT_TIMESTAMP DEFAULT_GENERATED on update CURRENT_TIMESTAMP select,insert,update,references ", - "b datetime(3) NO CURRENT_TIMESTAMP(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3) select,insert,update,references ")) - tk.MustQuery("select * from information_schema.columns where table_name = 'timestamp_table' and column_name='a'").Check(testkit.Rows( - "def test_on_update_timestamp timestamp_table a 1 CURRENT_TIMESTAMP NO datetime 0 " + - " datetime DEFAULT_GENERATED on update CURRENT_TIMESTAMP select,insert,update,references ")) - tk.MustQuery("select * from information_schema.columns where table_name = 'timestamp_table' and column_name='b'").Check(testkit.Rows( - "def test_on_update_timestamp timestamp_table b 2 CURRENT_TIMESTAMP(3) NO datetime 3 " + - " datetime(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3) select,insert,update,references ")) -} diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index 31334384ccaec..8d8fbc7f8b7a0 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -270,23 +270,27 @@ func (s *testTableSuite) TestCurrentTimestampAsDefault(c *C) { c_timestamp_default_3 timestamp(3) default current_timestamp(3), c_varchar_default varchar(20) default "current_timestamp", c_varchar_default_3 varchar(20) default "current_timestamp(3)", + c_varchar_default_on_update datetime default current_timestamp on update current_timestamp, + c_varchar_default_on_update_fsp datetime(3) default current_timestamp(3) on update current_timestamp(3), c_varchar_default_with_case varchar(20) default "cUrrent_tImestamp" );`) - tk.MustQuery(`SELECT column_name, column_default + tk.MustQuery(`SELECT column_name, column_default, extra FROM information_schema.COLUMNS WHERE table_schema = "default_time_test" AND table_name = "default_time_table" ORDER BY column_name`, ).Check(testkit.Rows( - "c_datetime ", - "c_datetime_default CURRENT_TIMESTAMP", - "c_datetime_default_2 CURRENT_TIMESTAMP(2)", - "c_timestamp ", - "c_timestamp_default CURRENT_TIMESTAMP", - "c_timestamp_default_3 CURRENT_TIMESTAMP(3)", - "c_varchar_default current_timestamp", - "c_varchar_default_3 current_timestamp(3)", - "c_varchar_default_with_case cUrrent_tImestamp", + "c_datetime ", + "c_datetime_default CURRENT_TIMESTAMP ", + "c_datetime_default_2 CURRENT_TIMESTAMP(2) ", + "c_timestamp ", + "c_timestamp_default CURRENT_TIMESTAMP ", + "c_timestamp_default_3 CURRENT_TIMESTAMP(3) ", + "c_varchar_default current_timestamp ", + "c_varchar_default_3 current_timestamp(3) ", + "c_varchar_default_on_update CURRENT_TIMESTAMP DEFAULT_GENERATED on update CURRENT_TIMESTAMP", + "c_varchar_default_on_update_fsp CURRENT_TIMESTAMP(3) DEFAULT_GENERATED on update CURRENT_TIMESTAMP(3)", + "c_varchar_default_with_case cUrrent_tImestamp ", )) tk.MustExec("DROP DATABASE default_time_test") }