Skip to content

Commit

Permalink
ddl: fix potential wrong column definition when setting default value (
Browse files Browse the repository at this point in the history
  • Loading branch information
wjhuang2016 authored Jun 30, 2022
1 parent 4887126 commit 1c259da
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
13 changes: 12 additions & 1 deletion ddl/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
57 changes: 57 additions & 0 deletions ddl/db_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()")
}

0 comments on commit 1c259da

Please sign in to comment.