diff --git a/ddl/column.go b/ddl/column.go index 218f30d9480b0..047d27105e7c9 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -1788,7 +1788,18 @@ func updateColumnDefaultValue(d *ddlCtx, t *meta.Meta, job *model.Job, newCol *m // 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.SetFlag(newCol.GetFlag()) + oldCol.DefaultIsExpr = newCol.DefaultIsExpr + if mysql.HasNoDefaultValueFlag(newCol.GetFlag()) { + oldCol.AddFlag(mysql.NoDefaultValueFlag) + } else { + oldCol.DelFlag(mysql.NoDefaultValueFlag) + sctx := newContext(d.store) + err = checkDefaultValue(sctx, table.ToColumn(oldCol), true) + if err != nil { + job.State = model.JobStateCancelled + return ver, err + } + } ver, err = updateVersionAndTableInfo(d, t, job, tblInfo, true) if err != nil { diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 2863aa2685f5a..5efbd6dc3b688 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -2092,3 +2092,60 @@ func TestParallelRenameTable(t *testing.T) { require.True(t, strings.Contains(checkErr.Error(), "Table 'test.t' doesn't exist"), checkErr.Error()) tk.MustExec("rename table tt to t") } + +func TestConcurrentSetDefaultValue(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a YEAR NULL DEFAULT '2029')") + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + + setdefaultSQL := []string{ + "alter table t alter a SET DEFAULT '2098'", + "alter table t alter a SET DEFAULT '1'", + } + setdefaultSQLOffset := 0 + + var wg sync.WaitGroup + d := dom.DDL() + originalCallback := d.GetHook() + defer d.SetHook(originalCallback) + callback := &ddl.TestDDLCallback{Do: dom} + skip := false + callback.OnJobRunBeforeExported = func(job *model.Job) { + switch job.SchemaState { + case model.StateDeleteOnly: + if skip { + break + } + skip = true + wg.Add(1) + go func() { + _, err := tk1.Exec(setdefaultSQL[setdefaultSQLOffset]) + if setdefaultSQLOffset == 0 { + require.Nil(t, err) + } + wg.Done() + }() + } + } + + d.SetHook(callback) + tk.MustExec("alter table t modify column a MEDIUMINT NULL DEFAULT '-8145111'") + + wg.Wait() + tk.MustQuery("select column_type from information_schema.columns where table_name = 't' and table_schema = 'test';").Check(testkit.Rows("mediumint(9)")) + + tk.MustExec("drop table t") + tk.MustExec("create table t(a int default 2)") + skip = false + setdefaultSQLOffset = 1 + tk.MustExec("alter table t modify column a TIMESTAMP NULL DEFAULT '2017-08-06 10:47:11'") + wg.Wait() + tk.MustExec("show create table t") + tk.MustExec("insert into t value()") +}