ddl: set default value to zero value when add a not null column. (#1443)
This commit is contained in:
@ -21,6 +21,7 @@ import (
|
||||
"github.com/pingcap/tidb/kv"
|
||||
"github.com/pingcap/tidb/meta"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/mysql"
|
||||
"github.com/pingcap/tidb/table"
|
||||
"github.com/pingcap/tidb/tablecodec"
|
||||
"github.com/pingcap/tidb/terror"
|
||||
@ -165,7 +166,7 @@ func (d *ddl) onAddColumn(t *meta.Meta, job *model.Job) error {
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if columnInfo.DefaultValue != nil {
|
||||
if columnInfo.DefaultValue != nil || mysql.HasNotNullFlag(columnInfo.Flag) {
|
||||
err = d.runReorgJob(func() error {
|
||||
return d.backfillColumn(tbl, columnInfo, reorgInfo)
|
||||
})
|
||||
@ -321,9 +322,17 @@ func (d *ddl) backfillColumn(t table.Table, columnInfo *model.ColumnInfo, reorgI
|
||||
}
|
||||
|
||||
func (d *ddl) backfillColumnData(t table.Table, columnInfo *model.ColumnInfo, handles []int64, reorgInfo *reorgInfo) error {
|
||||
defaultVal, _, err := table.GetColDefaultValue(nil, columnInfo)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
var (
|
||||
defaultVal types.Datum
|
||||
err error
|
||||
)
|
||||
if columnInfo.DefaultValue != nil {
|
||||
defaultVal, _, err = table.GetColDefaultValue(nil, columnInfo)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
} else if mysql.HasNotNullFlag(columnInfo.Flag) {
|
||||
defaultVal = table.GetZeroValue(columnInfo)
|
||||
}
|
||||
colMap := make(map[int64]*types.FieldType)
|
||||
for _, col := range t.Meta().Columns {
|
||||
|
||||
@ -141,3 +141,18 @@ func (s *testSuite) TestAlterTable(c *C) {
|
||||
tk.MustExec("create table if not exists alter_test (c1 int)")
|
||||
tk.MustExec("alter table alter_test add column c2 int")
|
||||
}
|
||||
|
||||
func (s *testSuite) TestAddNotNullColumnNoDefault(c *C) {
|
||||
defer testleak.AfterTest(c)()
|
||||
tk := testkit.NewTestKit(c, s.store)
|
||||
tk.MustExec("use test")
|
||||
tk.MustExec("create table nn (c1 int)")
|
||||
tk.MustExec("insert nn values (1), (2)")
|
||||
tk.MustExec("alter table nn add column c2 int not null")
|
||||
tk.MustQuery("select * from nn").Check(testkit.Rows("1 0", "2 0"))
|
||||
_, err := tk.Exec("insert nn (c1) values (3)")
|
||||
c.Check(err, NotNil)
|
||||
tk.MustExec("set sql_mode=''")
|
||||
tk.MustExec("insert nn (c1) values (3)")
|
||||
tk.MustQuery("select * from nn").Check(testkit.Rows("1 0", "2 0", "3 0"))
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ func GetColDefaultValue(ctx context.Context, col *model.ColumnInfo) (types.Datum
|
||||
sessVars := variable.GetSessionVars(ctx)
|
||||
if !sessVars.StrictSQLMode {
|
||||
// TODO: add warning.
|
||||
return getZeroValue(col), true, nil
|
||||
return GetZeroValue(col), true, nil
|
||||
}
|
||||
}
|
||||
return types.Datum{}, false, errors.Trace(err)
|
||||
@ -269,7 +269,8 @@ func GetColDefaultValue(ctx context.Context, col *model.ColumnInfo) (types.Datum
|
||||
return value, true, nil
|
||||
}
|
||||
|
||||
func getZeroValue(col *model.ColumnInfo) types.Datum {
|
||||
// GetZeroValue gets zero value for given column type.
|
||||
func GetZeroValue(col *model.ColumnInfo) types.Datum {
|
||||
var d types.Datum
|
||||
switch col.Tp {
|
||||
case mysql.TypeTiny, mysql.TypeInt24, mysql.TypeShort, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeYear:
|
||||
|
||||
@ -175,7 +175,7 @@ func (s *testColumnSuite) TestGetZeroValue(c *C) {
|
||||
}
|
||||
for _, ca := range cases {
|
||||
colInfo := &model.ColumnInfo{FieldType: *ca.ft}
|
||||
zv := getZeroValue(colInfo)
|
||||
zv := GetZeroValue(colInfo)
|
||||
c.Assert(zv.Kind(), Equals, ca.value.Kind())
|
||||
cmp, err := zv.CompareDatum(ca.value)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
Reference in New Issue
Block a user