Skip to content

Commit

Permalink
executor: fix bad null error handling for insert statement when disab…
Browse files Browse the repository at this point in the history
…ling the strict SQL mode (#10161) (#10254)
  • Loading branch information
jackysp authored and zz-jason committed Apr 24, 2019
1 parent a5d9c80 commit 4a13c71
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 6 deletions.
5 changes: 4 additions & 1 deletion executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1290,8 +1290,11 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
sc.Priority = stmt.Priority
case *ast.InsertStmt:
sc.InInsertStmt = true
// For insert statement (not for update statement), disabling the StrictSQLMode
// should make TruncateAsWarning and DividedByZeroAsWarning,
// but should not make DupKeyAsWarning or BadNullAsWarning,
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.BadNullAsWarning = stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
Expand Down
9 changes: 8 additions & 1 deletion executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1764,8 +1764,15 @@ func (s *testSuite) TestSQLMode(c *C) {

tk.MustExec("set sql_mode = ''")
tk.MustExec("insert t values ()")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
_, err = tk.Exec("insert t values (null)")
c.Check(err, NotNil)
tk.MustExec("insert ignore t values (null)")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
tk.MustExec("insert t select null")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
tk.MustExec("insert t values (1000)")
tk.MustQuery("select * from t").Check(testkit.Rows("0", "127"))
tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "127"))

tk.MustExec("insert tdouble values (10.23)")
tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99"))
Expand Down
4 changes: 4 additions & 0 deletions executor/insert_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ func (e *InsertValues) insertRowsFromSelect(ctx context.Context, exec func(rows
rows := make([][]types.Datum, 0, chk.Capacity())

sessVars := e.ctx.GetSessionVars()
if !sessVars.StrictSQLMode {
// If StrictSQLMode is disabled and it is a insert-select statement, it also handle BadNullAsWarning.
sessVars.StmtCtx.BadNullAsWarning = true
}
batchInsert := (sessVars.BatchInsert && !sessVars.InTxn()) || config.GetGlobalConfig().EnableBatchDML

for {
Expand Down
5 changes: 5 additions & 0 deletions executor/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,11 @@ commit;`
tk.MustExec(`INSERT IGNORE t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = null;`)
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'f2' cannot be null"))
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))

tk.MustExec(`SET sql_mode='';`)
_, err = tk.Exec(`INSERT t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = null;`)
c.Assert(err, NotNil)
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))
}

func (s *testSuite) TestInsertIgnoreOnDup(c *C) {
Expand Down
9 changes: 7 additions & 2 deletions table/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,12 +426,17 @@ func getColDefaultValueFromNil(ctx sessionctx.Context, col *model.ColumnInfo) (t
if col.IsGenerated() {
return types.Datum{}, nil
}
sc := ctx.GetSessionVars().StmtCtx
vars := ctx.GetSessionVars()
sc := vars.StmtCtx
if sc.BadNullAsWarning {
sc.AppendWarning(ErrColumnCantNull.GenWithStackByArgs(col.Name))
return GetZeroValue(col), nil
}
return types.Datum{}, ErrNoDefaultValue.GenWithStack("Field '%s' doesn't have a default value", col.Name)
if !vars.StrictSQLMode {
sc.AppendWarning(ErrNoDefaultValue.GenWithStackByArgs(col.Name))
return GetZeroValue(col), nil
}
return types.Datum{}, ErrNoDefaultValue.GenWithStackByArgs(col.Name)
}

// GetZeroValue gets zero value for given column type.
Expand Down
4 changes: 2 additions & 2 deletions table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ var (

// ErrNoDefaultValue is used when insert a row, the column value is not given, and the column has not null flag
// and it doesn't have a default value.
ErrNoDefaultValue = terror.ClassTable.New(codeNoDefaultValue, "field doesn't have a default value")
ErrNoDefaultValue = terror.ClassTable.New(codeNoDefaultValue, mysql.MySQLErrName[mysql.ErrNoDefaultForField])
// ErrIndexOutBound returns for index column offset out of bound.
ErrIndexOutBound = terror.ClassTable.New(codeIndexOutBound, "index column offset out of bound")
// ErrUnsupportedOp returns for unsupported operation.
Expand Down Expand Up @@ -199,7 +199,7 @@ const (
codeColumnCantNull = mysql.ErrBadNull
codeUnknownColumn = 1054
codeDuplicateColumn = 1110
codeNoDefaultValue = 1364
codeNoDefaultValue = mysql.ErrNoDefaultForField
codeTruncateWrongValue = 1366
// MySQL error code, "Trigger creation context of table `%-.64s`.`%-.64s` is invalid".
// It may happen when inserting some data outside of all table partitions.
Expand Down

0 comments on commit 4a13c71

Please sign in to comment.