diff --git a/ddl/column.go b/ddl/column.go index c467d3d85eb90..bed81ac0d4a66 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -324,7 +324,7 @@ func onSetDefaultValue(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } - return updateColumn(t, job, newCol, &newCol.Name) + return updateColumnDefaultValue(t, job, newCol, &newCol.Name) } func (w *worker) onModifyColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { @@ -481,7 +481,7 @@ func checkForNullValue(ctx sessionctx.Context, isDataTruncated bool, schema, tab return nil } -func updateColumn(t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldColName *model.CIStr) (ver int64, _ error) { +func updateColumnDefaultValue(t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldColName *model.CIStr) (ver int64, _ error) { tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) @@ -491,7 +491,10 @@ func updateColumn(t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldCol job.State = model.JobStateCancelled return ver, infoschema.ErrColumnNotExists.GenWithStackByArgs(newCol.Name, tblInfo.Name) } - *oldCol = *newCol + // The newCol's offset may be the value of the old schema version, so we can't use newCol directly. + oldCol.DefaultValue = newCol.DefaultValue + oldCol.DefaultValueBit = newCol.DefaultValueBit + oldCol.Flag = newCol.Flag ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) if err != nil { diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 33539ea5e1c75..451dcf69b8089 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -682,6 +682,30 @@ func (s *testStateChangeSuite) TestParallelAlterModifyColumn(c *C) { // s.testControlParallelExecSQL(c, sql1, sql2, f) // } +func (s *testStateChangeSuite) TestParallelAddColumAndSetDefaultValue(c *C) { + _, err := s.se.Execute(context.Background(), "use test_db_state") + c.Assert(err, IsNil) + _, err = s.se.Execute(context.Background(), `create table tx ( + c1 varchar(64), + c2 enum('N','Y') not null default 'N', + primary key idx2 (c2, c1))`) + c.Assert(err, IsNil) + _, err = s.se.Execute(context.Background(), "insert into tx values('a', 'N')") + c.Assert(err, IsNil) + defer s.se.Execute(context.Background(), "drop table tx") + + sql1 := "alter table tx add column cx int after c1" + sql2 := "alter table tx alter c2 set default 'N'" + + f := func(c *C, err1, err2 error) { + c.Assert(err1, IsNil) + c.Assert(err2, IsNil) + _, err := s.se.Execute(context.Background(), "delete from tx where c1='a'") + c.Assert(err, IsNil) + } + s.testControlParallelExecSQL(c, sql1, sql2, f) +} + func (s *testStateChangeSuite) TestParallelChangeColumnName(c *C) { sql1 := "ALTER TABLE t CHANGE a aa int;" sql2 := "ALTER TABLE t CHANGE b aa int;"