Skip to content

Commit

Permalink
ddl: fix and test for alter table stmt
Browse files Browse the repository at this point in the history
Signed-off-by: unconsolable <[email protected]>
  • Loading branch information
unconsolable committed Jan 26, 2022
1 parent 4be1bd6 commit 7754e12
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 15 deletions.
23 changes: 23 additions & 0 deletions ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7772,3 +7772,26 @@ func (s *testSerialDBSuite) TestAddGeneratedColumnAndInsert(c *C) {
tk.MustQuery("select * from t1 order by a").Check(testkit.Rows("4 5", "10 11"))
c.Assert(checkErr, IsNil)
}

// for issue #30328
func (s *testDBSuite5) TestTooBigFieldLengthAutoConvert(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)

err := tk.ExecToErr("create table i30328_1(a varbinary(70000), b varchar(70000000))")
c.Assert(types.ErrTooBigFieldLength.Equal(err), IsTrue)

// save previous sql_mode and change
r := tk.MustQuery("select @@sql_mode")
defer func(sqlMode string) {
tk.MustExec("set @@sql_mode= '" + sqlMode + "'")
tk.MustExec("drop table if exists i30328_1")
tk.MustExec("drop table if exists i30328_2")
}(r.Rows()[0][0].(string))
tk.MustExec("set @@sql_mode='NO_ENGINE_SUBSTITUTION'")

tk.MustExec("create table i30328_1(a varbinary(70000), b varchar(70000000))")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1246 Converting column 'a' from VARBINARY to BLOB", "Warning 1246 Converting column 'b' from VARCHAR to TEXT"))
tk.MustExec("create table i30328_2(a varchar(200))")
tk.MustExec("alter table i30328_2 modify a varchar(70000000);")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1246 Converting column 'a' from VARCHAR to TEXT"))
}
43 changes: 28 additions & 15 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,24 +566,12 @@ func buildColumnAndConstraint(
if err != nil {
return nil, nil, errors.Trace(err)
}

if err := setCharsetCollationFlenDecimal(colDef.Tp, chs, coll); err != nil {
return nil, nil, errors.Trace(err)
}
// Some column checks are performed before convert, so varchar auto convert is checked here, see issue #30328
sessVars := ctx.GetSessionVars()
if sessVars != nil && !sessVars.SQLMode.HasStrictMode() && colDef.Tp.Tp == mysql.TypeVarchar {
err := IsTooBigFieldLength(colDef.Tp.Flen, colDef.Name.Name.O, colDef.Tp.Charset)
if err != nil && terror.ErrorEqual(types.ErrTooBigFieldLength, err) {
colDef.Tp.Tp = mysql.TypeBlob
if err = adjustBlobTypesFlen(colDef.Tp, colDef.Tp.Charset); err != nil {
return nil, nil, err
}
if colDef.Tp.Charset == charset.CharsetBin {
sessVars.StmtCtx.AppendWarning(ErrAutoConvert.GenWithStackByArgs(colDef.Name.Name.O, "VARBINARY", "BLOB"))
} else {
sessVars.StmtCtx.AppendWarning(ErrAutoConvert.GenWithStackByArgs(colDef.Name.Name.O, "VARCHAR", "TEXT"))
}
}
if err = checkTooBigFieldLengthAndTryAutoConvert(colDef.Tp, colDef.Name.Name.O, ctx.GetSessionVars()); err != nil {
return nil, nil, errors.Trace(err)
}
col, cts, err := columnDefToCol(ctx, offset, colDef, outPriKeyConstraint)
if err != nil {
Expand Down Expand Up @@ -4284,6 +4272,10 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex
return nil, errors.Trace(err)
}

if err = checkTooBigFieldLengthAndTryAutoConvert(&newCol.FieldType, newCol.Name.O, sctx.GetSessionVars()); err != nil {
return nil, errors.Trace(err)
}

// Check the column with foreign key, waiting for the default flen and decimal.
if fkInfo := getColumnForeignKeyInfo(originalColName.L, t.Meta().ForeignKeys); fkInfo != nil {
// For now we strongly ban the all column type change for column with foreign key.
Expand Down Expand Up @@ -6883,3 +6875,24 @@ func (d *ddl) AlterTableNoCache(ctx sessionctx.Context, ti ast.Ident) (err error
err = d.doDDLJob(ctx, job)
return d.callHookOnChanged(err)
}

// checkTooBigFieldLengthAndTryAutoConvert will check whether the field length is too big
// in non-strict mode and varchar column. If it is, will try to adjust to blob or text, see issue #30328
func checkTooBigFieldLengthAndTryAutoConvert(tp *types.FieldType, colName string, sessVars *variable.SessionVars) error {
if sessVars != nil && !sessVars.SQLMode.HasStrictMode() && tp.Tp == mysql.TypeVarchar {
err := IsTooBigFieldLength(tp.Flen, colName, tp.Charset)
if err != nil && terror.ErrorEqual(types.ErrTooBigFieldLength, err) {
tp.Tp = mysql.TypeBlob
if err = adjustBlobTypesFlen(tp, tp.Charset); err != nil {
return err
}
if tp.Charset == charset.CharsetBin {
sessVars.StmtCtx.AppendWarning(ErrAutoConvert.GenWithStackByArgs(colName, "VARBINARY", "BLOB"))
} else {
sessVars.StmtCtx.AppendWarning(ErrAutoConvert.GenWithStackByArgs(colName, "VARCHAR", "TEXT"))
}
}
return nil
}
return nil
}

0 comments on commit 7754e12

Please sign in to comment.