From b43bdb74a3ca3f416db75565e19cf26625a10ea3 Mon Sep 17 00:00:00 2001
From: bb7133 <bb7133@gmail.com>
Date: Sat, 6 Jul 2019 12:50:07 +0800
Subject: [PATCH] =?UTF-8?q?executor,=20infoschema:=20fix=20display=20of=20?=
 =?UTF-8?q?default=20CURRENT=5FTIMESTAMP=E2=80=A6=20(#11088)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 executor/show.go          |  5 ++++-
 executor/show_test.go     | 29 +++++++++++++++++++++++++++++
 infoschema/tables_test.go | 36 ++++++++++++++++++++++++++++++++++++
 table/column.go           |  8 ++++++++
 4 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/executor/show.go b/executor/show.go
index 5618f04b20c75..37fad01831aaf 100644
--- a/executor/show.go
+++ b/executor/show.go
@@ -402,7 +402,7 @@ func (e *ShowExec) fetchShowColumns() error {
 			// SHOW COLUMNS result expects string value
 			defaultValStr := fmt.Sprintf("%v", desc.DefaultValue)
 			// If column is timestamp, and default value is not current_timestamp, should convert the default value to the current session time zone.
-			if col.Tp == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr && strings.ToUpper(defaultValStr) != strings.ToUpper(ast.CurrentTimestamp) {
+			if col.Tp == mysql.TypeTimestamp && defaultValStr != types.ZeroDatetimeStr && !strings.HasPrefix(strings.ToUpper(defaultValStr), strings.ToUpper(ast.CurrentTimestamp)) {
 				timeValue, err := table.GetColDefaultValue(e.ctx, col.ToInfo())
 				if err != nil {
 					return errors.Trace(err)
@@ -692,6 +692,9 @@ func (e *ShowExec) fetchShowCreateTable() error {
 					}
 				case "CURRENT_TIMESTAMP":
 					buf.WriteString(" DEFAULT CURRENT_TIMESTAMP")
+					if col.Decimal > 0 {
+						buf.WriteString(fmt.Sprintf("(%d)", col.Decimal))
+					}
 				default:
 					defaultValStr := fmt.Sprintf("%v", defaultValue)
 					// If column is timestamp, and default value is not current_timestamp, should convert the default value to the current session time zone.
diff --git a/executor/show_test.go b/executor/show_test.go
index c34d357c5f825..a1c8afc6548f6 100644
--- a/executor/show_test.go
+++ b/executor/show_test.go
@@ -186,13 +186,18 @@ func (s *testSuite2) TestShow2(c *C) {
 					c_nchar national char(1) charset ascii collate ascii_bin,
 					c_binary binary,
 					c_varchar varchar(1) charset ascii collate ascii_bin,
+					c_varchar_default varchar(20) charset ascii collate ascii_bin default 'cUrrent_tImestamp',
 					c_nvarchar national varchar(1) charset ascii collate ascii_bin,
 					c_varbinary varbinary(1),
 					c_year year,
 					c_date date,
 					c_time time,
 					c_datetime datetime,
+					c_datetime_default datetime default current_timestamp,
+					c_datetime_default_2 datetime(2) default current_timestamp(2),
 					c_timestamp timestamp,
+					c_timestamp_default timestamp default current_timestamp,
+					c_timestamp_default_3 timestamp(3) default current_timestamp(3),
 					c_blob blob,
 					c_tinyblob tinyblob,
 					c_mediumblob mediumblob,
@@ -216,13 +221,18 @@ func (s *testSuite2) TestShow2(c *C) {
 			"[c_nchar char(1) ascii_bin YES  <nil>  select,insert,update,references ]\n" +
 			"[c_binary binary(1) <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_varchar varchar(1) ascii_bin YES  <nil>  select,insert,update,references ]\n" +
+			"[c_varchar_default varchar(20) ascii_bin YES  cUrrent_tImestamp  select,insert,update,references ]\n" +
 			"[c_nvarchar varchar(1) ascii_bin YES  <nil>  select,insert,update,references ]\n" +
 			"[c_varbinary varbinary(1) <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_year year(4) <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_date date <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_time time <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_datetime datetime <nil> YES  <nil>  select,insert,update,references ]\n" +
+			"[c_datetime_default datetime <nil> YES  CURRENT_TIMESTAMP  select,insert,update,references ]\n" +
+			"[c_datetime_default_2 datetime(2) <nil> YES  CURRENT_TIMESTAMP(2)  select,insert,update,references ]\n" +
 			"[c_timestamp timestamp <nil> YES  <nil>  select,insert,update,references ]\n" +
+			"[c_timestamp_default timestamp <nil> YES  CURRENT_TIMESTAMP  select,insert,update,references ]\n" +
+			"[c_timestamp_default_3 timestamp(3) <nil> YES  CURRENT_TIMESTAMP(3)  select,insert,update,references ]\n" +
 			"[c_blob blob <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_tinyblob tinyblob <nil> YES  <nil>  select,insert,update,references ]\n" +
 			"[c_mediumblob mediumblob <nil> YES  <nil>  select,insert,update,references ]\n" +
@@ -451,6 +461,25 @@ func (s *testSuite2) TestShowCreateTable(c *C) {
 			") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
 	))
 
+	tk.MustExec("drop table if exists t")
+	tk.MustExec("create table `t` (\n" +
+		"`a` timestamp not null default current_timestamp,\n" +
+		"`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')")
+	tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
+		""+
+			"t CREATE TABLE `t` (\n"+
+			"  `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n"+
+			"  `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"+
+			") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
+	))
+	tk.MustExec("drop table t")
+
 	tk.MustExec("create table t (a int, b int) shard_row_id_bits = 4 pre_split_regions=3;")
 	tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
 		""+
diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go
index 057ec4082ed25..ce102e67bc1a0 100644
--- a/infoschema/tables_test.go
+++ b/infoschema/tables_test.go
@@ -241,6 +241,42 @@ func (s *testTableSuite) TestCharacterSetCollations(c *C) {
 	tk.MustExec("DROP DATABASE charset_collate_test")
 }
 
+func (s *testTableSuite) TestCurrentTimestampAsDefault(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+
+	tk.MustExec("DROP DATABASE IF EXISTS default_time_test")
+	tk.MustExec("CREATE DATABASE default_time_test; USE default_time_test")
+
+	tk.MustExec(`CREATE TABLE default_time_table(
+					c_datetime datetime,
+					c_datetime_default datetime default current_timestamp,
+					c_datetime_default_2 datetime(2) default current_timestamp(2),
+					c_timestamp timestamp,
+					c_timestamp_default timestamp default current_timestamp,
+					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_with_case varchar(20) default "cUrrent_tImestamp"
+				);`)
+
+	tk.MustQuery(`SELECT column_name, column_default
+					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 <nil>",
+		"c_datetime_default CURRENT_TIMESTAMP",
+		"c_datetime_default_2 CURRENT_TIMESTAMP(2)",
+		"c_timestamp <nil>",
+		"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",
+	))
+	tk.MustExec("DROP DATABASE default_time_test")
+}
+
 type mockSessionManager struct {
 	processInfoMap map[uint64]*util.ProcessInfo
 }
diff --git a/table/column.go b/table/column.go
index ce9fb65454673..08f4884ad5d9c 100644
--- a/table/column.go
+++ b/table/column.go
@@ -19,6 +19,7 @@ package table
 
 import (
 	"context"
+	"fmt"
 	"strings"
 	"time"
 	"unicode/utf8"
@@ -256,6 +257,13 @@ func NewColDesc(col *Column) *ColDesc {
 	var defaultValue interface{}
 	if !mysql.HasNoDefaultValueFlag(col.Flag) {
 		defaultValue = col.GetDefaultValue()
+		if defaultValStr, ok := defaultValue.(string); ok {
+			if (col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime) &&
+				strings.ToUpper(defaultValStr) == strings.ToUpper(ast.CurrentTimestamp) &&
+				col.Decimal > 0 {
+				defaultValue = fmt.Sprintf("%s(%d)", defaultValStr, col.Decimal)
+			}
+		}
 	}
 
 	extra := ""