diff --git a/executor/ddl_test.go b/executor/ddl_test.go index fa803bd2b7dbd..f6aa471fdf11a 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -518,3 +518,11 @@ func (s *testSuite) TestSetDDLReorgBatchSize(c *C) { // If do not LoadDDLReorgVars, the local variable will be the last loaded value. c.Assert(variable.GetDDLReorgBatchSize(), Equals, int32(100)) } + +func (s *testSuite) TestTimestampMinDefaultValue(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists tdv;") + tk.MustExec("create table tdv(a int);") + tk.MustExec("ALTER TABLE tdv ADD COLUMN ts timestamp DEFAULT '1970-01-01 08:00:01';") +} diff --git a/table/column.go b/table/column.go index 9bb8cee76dbab..161acc570bd3a 100644 --- a/table/column.go +++ b/table/column.go @@ -360,27 +360,36 @@ func getColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo, defaultVa } return value, nil } + // Check and get timestamp/datetime default value. - value, err := expression.GetTimeValue(ctx, defaultVal, col.Tp, col.Decimal) - if err != nil { - return types.Datum{}, errGetDefaultFailed.GenWithStack("Field '%s' get default value fail - %s", - col.Name, errors.Trace(err)) - } - // If column is timestamp, and default value is not current_timestamp, should convert the default value to the current session time zone. + sc := ctx.GetSessionVars().StmtCtx + var needChangeTimeZone bool + // If the column's default value is not ZeroDatetimeStr nor CurrentTimestamp, should use the time zone of the default value itself. if col.Tp == mysql.TypeTimestamp { if vv, ok := defaultVal.(string); ok && vv != types.ZeroDatetimeStr && strings.ToUpper(vv) != strings.ToUpper(ast.CurrentTimestamp) { - t := value.GetMysqlTime() + needChangeTimeZone = true + originalTZ := sc.TimeZone // For col.Version = 0, the timezone information of default value is already lost, so use the system timezone as the default value timezone. - defaultTimeZone := timeutil.SystemLocation() + sc.TimeZone = timeutil.SystemLocation() if col.Version >= model.ColumnInfoVersion1 { - defaultTimeZone = time.UTC - } - err = t.ConvertTimeZone(defaultTimeZone, ctx.GetSessionVars().Location()) - if err != nil { - return value, errors.Trace(err) + sc.TimeZone = time.UTC } - value.SetMysqlTime(t) + defer func() { sc.TimeZone = originalTZ }() + } + } + value, err := expression.GetTimeValue(ctx, defaultVal, col.Tp, col.Decimal) + if err != nil { + return types.Datum{}, errGetDefaultFailed.GenWithStack("Field '%s' get default value fail - %s", + col.Name, errors.Trace(err)) + } + // If the column's default value is not ZeroDatetimeStr nor CurrentTimestamp, should convert the default value to the current session time zone. + if needChangeTimeZone { + t := value.GetMysqlTime() + err = t.ConvertTimeZone(sc.TimeZone, ctx.GetSessionVars().Location()) + if err != nil { + return value, errors.Trace(err) } + value.SetMysqlTime(t) } return value, nil }