Skip to content

Commit ee67770

Browse files
authored
*: disable insert null to not-null column for single-row insertion in non-strict mode | tidb-test=pr/2445 (#55477) (#58044)
close #55457, close #56381, close #57435
1 parent b598f6e commit ee67770

File tree

14 files changed

+58
-10
lines changed

14 files changed

+58
-10
lines changed

br/pkg/lightning/backend/kv/session.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ func NewSession(options *encode.SessionOptions, logger log.Logger) *Session {
287287
vars.StmtCtx.InInsertStmt = true
288288
vars.StmtCtx.BatchCheck = true
289289
vars.StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode()
290+
vars.StmtCtx.NoDefaultAsWarning = !sqlMode.HasStrictMode()
290291
vars.StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode()
291292
vars.StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode()
292293
vars.StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode()

br/pkg/lightning/errormanager/errormanager.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ const (
8888
create_time datetime(6) NOT NULL DEFAULT now(6),
8989
table_name varchar(261) NOT NULL,
9090
index_name varchar(128) NOT NULL,
91-
key_data text NOT NULL COMMENT 'decoded from raw_key, human readable only, not for machine use',
92-
row_data text NOT NULL COMMENT 'decoded from raw_row, human readable only, not for machine use',
91+
key_data text COMMENT 'decoded from raw_key, human readable only, not for machine use',
92+
row_data text COMMENT 'decoded from raw_row, human readable only, not for machine use',
9393
raw_key mediumblob NOT NULL COMMENT 'the conflicted key',
9494
raw_value mediumblob NOT NULL COMMENT 'the value of the conflicted key',
9595
raw_handle mediumblob NOT NULL COMMENT 'the data handle derived from the conflicted key or value',

pkg/ddl/backfilling_scheduler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ func initSessCtx(
168168
return errors.Trace(err)
169169
}
170170
sessCtx.GetSessionVars().StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode()
171+
sessCtx.GetSessionVars().StmtCtx.NoDefaultAsWarning = !sqlMode.HasStrictMode()
171172
sessCtx.GetSessionVars().StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode()
172173
sessCtx.GetSessionVars().StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode()
173174
sessCtx.GetSessionVars().StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode()
@@ -194,6 +195,7 @@ func restoreSessCtx(sessCtx sessionctx.Context) func(sessCtx sessionctx.Context)
194195
timezone = &tz
195196
}
196197
badNullAsWarn := sv.StmtCtx.BadNullAsWarning
198+
noDefaultAsWarn := sv.StmtCtx.NoDefaultAsWarning
197199
overflowAsWarn := sv.StmtCtx.OverflowAsWarning
198200
dividedZeroAsWarn := sv.StmtCtx.DividedByZeroAsWarning
199201
ignoreZeroInDate := sv.StmtCtx.IgnoreZeroInDate
@@ -205,6 +207,7 @@ func restoreSessCtx(sessCtx sessionctx.Context) func(sessCtx sessionctx.Context)
205207
uv.SQLMode = sqlMode
206208
uv.TimeZone = timezone
207209
uv.StmtCtx.BadNullAsWarning = badNullAsWarn
210+
uv.StmtCtx.NoDefaultAsWarning = noDefaultAsWarn
208211
uv.StmtCtx.OverflowAsWarning = overflowAsWarn
209212
uv.StmtCtx.DividedByZeroAsWarning = dividedZeroAsWarn
210213
uv.StmtCtx.IgnoreZeroInDate = ignoreZeroInDate

pkg/executor/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ go_test(
420420
"//pkg/store/helper",
421421
"//pkg/store/mockstore",
422422
"//pkg/store/mockstore/unistore",
423+
"//pkg/table",
423424
"//pkg/table/tables",
424425
"//pkg/tablecodec",
425426
"//pkg/testkit",

pkg/executor/executor.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,11 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
21042104
// should make TruncateAsWarning and DividedByZeroAsWarning,
21052105
// but should not make DupKeyAsWarning.
21062106
sc.DupKeyAsWarning = stmt.IgnoreErr
2107-
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
2107+
// For single-row INSERT statements, ignore non-strict mode
2108+
// See https://dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html
2109+
isSingleInsert := len(stmt.Lists) == 1
2110+
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
2111+
sc.BadNullAsWarning = (!vars.StrictSQLMode && !isSingleInsert) || stmt.IgnoreErr
21082112
// see https://dev.mysql.com/doc/refman/8.0/en/out-of-range-and-overflow.html
21092113
sc.OverflowAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
21102114
sc.IgnoreNoPartition = stmt.IgnoreErr
@@ -2226,6 +2230,7 @@ func ResetUpdateStmtCtx(sc *stmtctx.StatementContext, stmt *ast.UpdateStmt, vars
22262230
sc.InUpdateStmt = true
22272231
sc.DupKeyAsWarning = stmt.IgnoreErr
22282232
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
2233+
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22292234
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22302235
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22312236
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
@@ -2239,6 +2244,7 @@ func ResetDeleteStmtCtx(sc *stmtctx.StatementContext, stmt *ast.DeleteStmt, vars
22392244
sc.InDeleteStmt = true
22402245
sc.DupKeyAsWarning = stmt.IgnoreErr
22412246
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
2247+
sc.NoDefaultAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22422248
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22432249
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
22442250
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()

pkg/executor/insert_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/pingcap/tidb/pkg/executor"
2828
"github.com/pingcap/tidb/pkg/meta/autoid"
2929
"github.com/pingcap/tidb/pkg/sessionctx/variable"
30+
"github.com/pingcap/tidb/pkg/table"
3031
"github.com/pingcap/tidb/pkg/testkit"
3132
"github.com/pingcap/tidb/pkg/util"
3233
"github.com/pingcap/tidb/pkg/util/execdetails"
@@ -1693,3 +1694,32 @@ func TestMySQLInsertID(t *testing.T) {
16931694
tk.MustExec("insert into tb(a, b) values(1,2) on duplicate key update b = 2;")
16941695
require.Equal(t, tk.Session().LastInsertID(), uint64(0))
16951696
}
1697+
1698+
func TestInsertNullInNonStrictMode(t *testing.T) {
1699+
store := testkit.CreateMockStore(t)
1700+
tk := testkit.NewTestKit(t, store)
1701+
tk.MustExec("use test")
1702+
tk.MustExec("create table t1 (id int primary key, col1 varchar(10) not null default '')")
1703+
tk.MustExec("create table t2 (id int primary key, col1 varchar(10))")
1704+
tk.MustExec("insert into t2 values (1, null)")
1705+
tk.MustExec("insert ignore into t1 values(5, null)")
1706+
1707+
tk.MustExec("set session sql_mode = ''")
1708+
1709+
err := tk.ExecToErr("insert into t1 values(1, null)")
1710+
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())
1711+
1712+
err = tk.ExecToErr("insert into t1 set id = 1, col1 = null")
1713+
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())
1714+
1715+
err = tk.ExecToErr("insert t1 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = null")
1716+
require.EqualError(t, err, table.ErrColumnCantNull.GenWithStackByArgs("col1").Error())
1717+
1718+
tk.MustExec("insert t1 VALUES (5, 5), (6, null) ON DUPLICATE KEY UPDATE col1 = null")
1719+
1720+
tk.MustExec("insert into t1 select * from t2")
1721+
tk.MustExec("insert into t1 values(2, null), (3, 3), (4, 4)")
1722+
tk.MustExec("update t1 set col1 = null where id = 3")
1723+
tk.MustExec("insert ignore t1 VALUES (4, 4) ON DUPLICATE KEY UPDATE col1 = null")
1724+
tk.MustQuery("select * from t1").Check(testkit.RowsWithSep("|", "1|", "2|", "3|", "4|", "5|", "6|"))
1725+
}

pkg/executor/load_data.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func setNonRestrictiveFlags(stmtCtx *stmtctx.StatementContext) {
101101
stmtCtx.DupKeyAsWarning = true
102102
stmtCtx.TruncateAsWarning = true
103103
stmtCtx.BadNullAsWarning = true
104+
stmtCtx.NoDefaultAsWarning = true
104105
}
105106

106107
// NewLoadDataWorker creates a new LoadDataWorker that is ready to work.

pkg/executor/test/executor/executor_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,14 +3083,13 @@ func TestSQLMode(t *testing.T) {
30833083
tk.MustExec("set sql_mode = ''")
30843084
tk.MustExec("insert t values ()")
30853085
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
3086-
tk.MustExec("insert t values (null)")
3087-
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
3086+
tk.ExecToErr("insert t values (null)")
30883087
tk.MustExec("insert ignore t values (null)")
30893088
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
30903089
tk.MustExec("insert t select null")
30913090
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null"))
30923091
tk.MustExec("insert t values (1000)")
3093-
tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "0", "127"))
3092+
tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "127"))
30943093

30953094
tk.MustExec("insert tdouble values (10.23)")
30963095
tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99"))

pkg/executor/test/writetest/write_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,8 +757,7 @@ commit;`
757757
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))
758758

759759
tk.MustExec(`SET sql_mode='';`)
760-
tk.MustExec(`INSERT t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = null;`)
761-
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'f2' cannot be null"))
760+
tk.ExecToErr(`INSERT t1 VALUES (1, 1) ON DUPLICATE KEY UPDATE f2 = null;`)
762761
tk.MustQuery(`SELECT * FROM t1 order by f1;`).Check(testkit.Rows("1 0", "2 2"))
763762
}
764763

@@ -1314,6 +1313,7 @@ func TestIssue18681(t *testing.T) {
13141313
selectSQL := "select bin(a), bin(b), bin(c), bin(d), bin(e), bin(f) from load_data_test;"
13151314
ctx.GetSessionVars().StmtCtx.DupKeyAsWarning = true
13161315
ctx.GetSessionVars().StmtCtx.BadNullAsWarning = true
1316+
ctx.GetSessionVars().StmtCtx.NoDefaultAsWarning = true
13171317

13181318
sc := ctx.GetSessionVars().StmtCtx
13191319
originIgnoreTruncate := sc.IgnoreTruncate.Load()

pkg/expression/builtin_miscellaneous_vec_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func TestSleepVectorized(t *testing.T) {
152152

153153
// non-strict model
154154
sessVars.StmtCtx.BadNullAsWarning = true
155+
sessVars.StmtCtx.NoDefaultAsWarning = true
155156
input.AppendFloat64(0, 1)
156157
err = f.vecEvalInt(input, result)
157158
require.NoError(t, err)
@@ -185,6 +186,7 @@ func TestSleepVectorized(t *testing.T) {
185186

186187
// for error case under the strict model
187188
sessVars.StmtCtx.BadNullAsWarning = false
189+
sessVars.StmtCtx.NoDefaultAsWarning = false
188190
input.Reset()
189191
input.AppendNull(0)
190192
err = f.vecEvalInt(input, result)

0 commit comments

Comments
 (0)