Skip to content

Commit

Permalink
table: handling the boundary value of the timestamp type's default va…
Browse files Browse the repository at this point in the history
…lue (#9578)
  • Loading branch information
zimulala authored and zz-jason committed Apr 1, 2019
1 parent 2ee8f42 commit 08346b7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 14 deletions.
8 changes: 8 additions & 0 deletions executor/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,3 +770,11 @@ func (s *testSuite3) TestCheckDefaultFsp(c *C) {
_, err = tk.Exec("alter table t change column tt tttt timestamp(1) default now();")
c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tttt'")
}

func (s *testSuite3) 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';")
}
37 changes: 23 additions & 14 deletions table/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,27 +363,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
}
Expand Down

0 comments on commit 08346b7

Please sign in to comment.