Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: disable insert null to not-null column for single-row insertion in non-strict mode | tidb-test=pr/2445 (#55477) #58044

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions br/pkg/lightning/backend/kv/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ func NewSession(options *encode.SessionOptions, logger log.Logger) *Session {
vars.StmtCtx.InInsertStmt = true
vars.StmtCtx.BatchCheck = true
vars.StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode()
vars.StmtCtx.NoDefaultAsWarning = !sqlMode.HasStrictMode()
vars.StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode()
vars.StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode()
vars.StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode()
Expand Down
4 changes: 2 additions & 2 deletions br/pkg/lightning/errormanager/errormanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ const (
create_time datetime(6) NOT NULL DEFAULT now(6),
table_name varchar(261) NOT NULL,
index_name varchar(128) NOT NULL,
key_data text NOT NULL COMMENT 'decoded from raw_key, human readable only, not for machine use',
row_data text NOT NULL COMMENT 'decoded from raw_row, human readable only, not for machine use',
key_data text COMMENT 'decoded from raw_key, human readable only, not for machine use',
row_data text COMMENT 'decoded from raw_row, human readable only, not for machine use',
raw_key mediumblob NOT NULL COMMENT 'the conflicted key',
raw_value mediumblob NOT NULL COMMENT 'the value of the conflicted key',
raw_handle mediumblob NOT NULL COMMENT 'the data handle derived from the conflicted key or value',
Expand Down
3 changes: 3 additions & 0 deletions pkg/ddl/backfilling_scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func initSessCtx(
return errors.Trace(err)
}
sessCtx.GetSessionVars().StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode()
sessCtx.GetSessionVars().StmtCtx.NoDefaultAsWarning = !sqlMode.HasStrictMode()
sessCtx.GetSessionVars().StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode()
sessCtx.GetSessionVars().StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode()
sessCtx.GetSessionVars().StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode()
Expand All @@ -191,6 +192,7 @@ func restoreSessCtx(sessCtx sessionctx.Context) func(sessCtx sessionctx.Context)
timezone = &tz
}
badNullAsWarn := sv.StmtCtx.BadNullAsWarning
noDefaultAsWarn := sv.StmtCtx.NoDefaultAsWarning
overflowAsWarn := sv.StmtCtx.OverflowAsWarning
dividedZeroAsWarn := sv.StmtCtx.DividedByZeroAsWarning
ignoreZeroInDate := sv.StmtCtx.IgnoreZeroInDate
Expand All @@ -202,6 +204,7 @@ func restoreSessCtx(sessCtx sessionctx.Context) func(sessCtx sessionctx.Context)
uv.SQLMode = sqlMode
uv.TimeZone = timezone
uv.StmtCtx.BadNullAsWarning = badNullAsWarn
uv.StmtCtx.NoDefaultAsWarning = noDefaultAsWarn
uv.StmtCtx.OverflowAsWarning = overflowAsWarn
uv.StmtCtx.DividedByZeroAsWarning = dividedZeroAsWarn
uv.StmtCtx.IgnoreZeroInDate = ignoreZeroInDate
Expand Down
1 change: 1 addition & 0 deletions pkg/executor/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ go_test(
"//pkg/store/helper",
"//pkg/store/mockstore",
"//pkg/store/mockstore/unistore",
"//pkg/table",
"//pkg/table/tables",
"//pkg/tablecodec",
"//pkg/testkit",
Expand Down
8 changes: 7 additions & 1 deletion pkg/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2104,7 +2104,11 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
// should make TruncateAsWarning and DividedByZeroAsWarning,
// but should not make DupKeyAsWarning.
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
// For single-row INSERT statements, ignore non-strict mode
// See https://dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html
isSingleInsert := len(stmt.Lists) == 1
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.BadNullAsWarning = (!vars.StrictSQLMode && !isSingleInsert) || stmt.IgnoreErr
// see https://dev.mysql.com/doc/refman/8.0/en/out-of-range-and-overflow.html
sc.OverflowAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.IgnoreNoPartition = stmt.IgnoreErr
Expand Down Expand Up @@ -2226,6 +2230,7 @@ func ResetUpdateStmtCtx(sc *stmtctx.StatementContext, stmt *ast.UpdateStmt, vars
sc.InUpdateStmt = true
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
Expand All @@ -2239,6 +2244,7 @@ func ResetDeleteStmtCtx(sc *stmtctx.StatementContext, stmt *ast.DeleteStmt, vars
sc.InDeleteStmt = true
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
Expand Down
30 changes: 30 additions & 0 deletions pkg/executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/pingcap/tidb/pkg/executor"
"github.com/pingcap/tidb/pkg/meta/autoid"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
"github.com/pingcap/tidb/pkg/table"
"github.com/pingcap/tidb/pkg/testkit"
"github.com/pingcap/tidb/pkg/util"
"github.com/pingcap/tidb/pkg/util/execdetails"
Expand Down Expand Up @@ -1628,3 +1629,32 @@ func TestUnsignedDecimalFloatInsertNegative(t *testing.T) {
tk.MustExec("insert into tf values('-100')")
tk.MustQuery("select * from tf").Check(testkit.Rows("0"))
}

func TestInsertNullInNonStrictMode(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t1 (id int primary key, col1 varchar(10) not null default '')")
tk.MustExec("create table t2 (id int primary key, col1 varchar(10))")
tk.MustExec("insert into t2 values (1, null)")
tk.MustExec("insert ignore into t1 values(5, null)")

tk.MustExec("set session sql_mode = ''")

err := tk.ExecToErr("insert into t1 values(1, null)")
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())

err = tk.ExecToErr("insert into t1 set id = 1, col1 = null")
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())

err = tk.ExecToErr("insert t1 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = null")
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())

tk.MustExec("insert t1 VALUES (5, 5), (6, null) ON DUPLICATE KEY UPDATE col1 = null")

tk.MustExec("insert into t1 select * from t2")
tk.MustExec("insert into t1 values(2, null), (3, 3), (4, 4)")
tk.MustExec("update t1 set col1 = null where id = 3")
tk.MustExec("insert ignore t1 VALUES (4, 4) ON DUPLICATE KEY UPDATE col1 = null")
tk.MustQuery("select * from t1").Check(testkit.RowsWithSep("|", "1|", "2|", "3|", "4|", "5|", "6|"))
}
1 change: 1 addition & 0 deletions pkg/executor/load_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func setNonRestrictiveFlags(stmtCtx *stmtctx.StatementContext) {
stmtCtx.DupKeyAsWarning = true
stmtCtx.TruncateAsWarning = true
stmtCtx.BadNullAsWarning = true
stmtCtx.NoDefaultAsWarning = true
}

// NewLoadDataWorker creates a new LoadDataWorker that is ready to work.
Expand Down
5 changes: 2 additions & 3 deletions pkg/executor/test/executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3083,14 +3083,13 @@ func TestSQLMode(t *testing.T) {
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"))
tk.MustExec("insert t values (null)")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
tk.ExecToErr("insert t values (null)")
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 order by a").Check(testkit.Rows("0", "0", "0", "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: 2 additions & 2 deletions pkg/executor/test/writetest/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,8 +757,7 @@ commit;`
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))

tk.MustExec(`SET sql_mode='';`)
tk.MustExec(`INSERT 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.ExecToErr(`INSERT t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = null;`)
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))
}

Expand Down Expand Up @@ -1314,6 +1313,7 @@ func TestIssue18681(t *testing.T) {
selectSQL := "select bin(a), bin(b), bin(c), bin(d) from load_data_test;"
ctx.GetSessionVars().StmtCtx.DupKeyAsWarning = true
ctx.GetSessionVars().StmtCtx.BadNullAsWarning = true
ctx.GetSessionVars().StmtCtx.NoDefaultAsWarning = true

sc := ctx.GetSessionVars().StmtCtx
originIgnoreTruncate := sc.IgnoreTruncate.Load()
Expand Down
2 changes: 2 additions & 0 deletions pkg/expression/builtin_miscellaneous_vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func TestSleepVectorized(t *testing.T) {

// non-strict model
sessVars.StmtCtx.BadNullAsWarning = true
sessVars.StmtCtx.NoDefaultAsWarning = true
input.AppendFloat64(0, 1)
err = f.vecEvalInt(input, result)
require.NoError(t, err)
Expand Down Expand Up @@ -185,6 +186,7 @@ func TestSleepVectorized(t *testing.T) {

// for error case under the strict model
sessVars.StmtCtx.BadNullAsWarning = false
sessVars.StmtCtx.NoDefaultAsWarning = false
input.Reset()
input.AppendNull(0)
err = f.vecEvalInt(input, result)
Expand Down
2 changes: 2 additions & 0 deletions pkg/expression/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func TestSleep(t *testing.T) {
fc := funcs[ast.Sleep]
// non-strict model
sessVars.StmtCtx.BadNullAsWarning = true
sessVars.StmtCtx.NoDefaultAsWarning = true
d := make([]types.Datum, 1)
f, err := fc.getFunction(ctx, datumsToConstants(d))
require.NoError(t, err)
Expand All @@ -122,6 +123,7 @@ func TestSleep(t *testing.T) {

// for error case under the strict model
sessVars.StmtCtx.BadNullAsWarning = false
sessVars.StmtCtx.NoDefaultAsWarning = false
d[0].SetNull()
_, err = fc.getFunction(ctx, datumsToConstants(d))
require.NoError(t, err)
Expand Down
1 change: 1 addition & 0 deletions pkg/sessionctx/stmtctx/stmtctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ type StatementContext struct {
NoZeroDate bool
DupKeyAsWarning bool
BadNullAsWarning bool
NoDefaultAsWarning bool
DividedByZeroAsWarning bool
TruncateAsWarning bool
OverflowAsWarning bool
Expand Down
4 changes: 2 additions & 2 deletions pkg/table/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ func GetColOriginDefaultValueWithoutStrictSQLMode(ctx sessionctx.Context, col *m
// But CheckNoDefaultValueForInsert logic should only check before insert.
func CheckNoDefaultValueForInsert(sc *stmtctx.StatementContext, col *model.ColumnInfo) error {
if mysql.HasNoDefaultValueFlag(col.GetFlag()) && !col.DefaultIsExpr && col.GetDefaultValue() == nil && col.GetType() != mysql.TypeEnum {
if !sc.BadNullAsWarning {
if !sc.NoDefaultAsWarning {
return ErrNoDefaultValue.GenWithStackByArgs(col.Name)
}
if !mysql.HasNotNullFlag(col.GetFlag()) {
Expand Down Expand Up @@ -661,7 +661,7 @@ func getColDefaultValueFromNil(ctx sessionctx.Context, col *model.ColumnInfo, ar
sc.AppendWarning(ErrNoDefaultValue.FastGenByArgs(col.Name))
return GetZeroValue(col), nil
}
if sc.BadNullAsWarning {
if sc.NoDefaultAsWarning {
var err error
if mysql.HasNoDefaultValueFlag(col.GetFlag()) {
err = ErrNoDefaultValue.FastGenByArgs(col.Name)
Expand Down
2 changes: 2 additions & 0 deletions pkg/table/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ func TestGetDefaultValue(t *testing.T) {

for _, tt := range tests {
ctx.GetSessionVars().StmtCtx.BadNullAsWarning = !tt.strict
ctx.GetSessionVars().StmtCtx.NoDefaultAsWarning = !tt.strict
val, err := GetColDefaultValue(ctx, tt.colInfo)
if err != nil {
require.Errorf(t, tt.err, "%v", err)
Expand All @@ -479,6 +480,7 @@ func TestGetDefaultValue(t *testing.T) {

for _, tt := range tests {
ctx.GetSessionVars().StmtCtx.BadNullAsWarning = !tt.strict
ctx.GetSessionVars().StmtCtx.NoDefaultAsWarning = !tt.strict
val, err := GetColOriginDefaultValue(ctx, tt.colInfo)
if err != nil {
require.Errorf(t, tt.err, "%v", err)
Expand Down
Loading