Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#40157
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <[email protected]>
  • Loading branch information
jiyfhust authored and ti-chi-bot committed Apr 19, 2023
1 parent 2adad09 commit 371dca8
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 1 deletion.
31 changes: 30 additions & 1 deletion executor/insert_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,16 +655,45 @@ func (e *InsertValues) fillRow(ctx context.Context, row []types.Datum, hasValue
}
}
}
<<<<<<< HEAD
=======
tbl := e.Table.Meta()
// Handle exchange partition
if tbl.ExchangePartitionInfo != nil && tbl.ExchangePartitionInfo.ExchangePartitionFlag {
is := e.ctx.GetDomainInfoSchema().(infoschema.InfoSchema)
pt, tableFound := is.TableByID(tbl.ExchangePartitionInfo.ExchangePartitionID)
if !tableFound {
return nil, errors.Errorf("exchange partition process table by id failed")
}
p, ok := pt.(table.PartitionedTable)
if !ok {
return nil, errors.Errorf("exchange partition process assert table partition failed")
}
err := p.CheckForExchangePartition(e.ctx, pt.Meta().Partition, row, tbl.ExchangePartitionInfo.ExchangePartitionDefID)
if err != nil {
return nil, err
}
}
sc := e.ctx.GetSessionVars().StmtCtx
warnCnt := int(sc.WarningCount())
>>>>>>> 875e34d28a1 (executor: fix uint type overflow on generated column not compatible with mysql (#40157))
for i, gCol := range gCols {
colIdx := gCol.ColumnInfo.Offset
val, err := e.GenExprs[i].Eval(chunk.MutRowFromDatums(row).ToRow())
if e.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) != nil {
return nil, err
}
row[colIdx], err = table.CastValue(e.ctx, val, gCol.ToInfo(), false, false)
if err != nil {
if err = e.handleErr(gCol, &val, rowIdx, err); err != nil {
return nil, err
}
if newWarnings := sc.TruncateWarnings(warnCnt); len(newWarnings) > 0 {
for k := range newWarnings {
newWarnings[k].Err = completeInsertErr(gCol.ColumnInfo, &val, rowIdx, newWarnings[k].Err)
}
sc.AppendWarnings(newWarnings)
warnCnt += len(newWarnings)
}
// Handle the bad null error.
if err = gCol.HandleBadNull(&row[colIdx], e.ctx.GetSessionVars().StmtCtx); err != nil {
return nil, err
Expand Down
73 changes: 73 additions & 0 deletions executor/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4237,3 +4237,76 @@ func TestIssueInsertPrefixIndexForNonUTF8Collation(t *testing.T) {
tk.MustExec("insert into t3 select 'abc '")
tk.MustGetErrCode("insert into t3 select 'abc d'", 1062)
}
<<<<<<< HEAD:executor/write_test.go
=======

func TestIssue40066(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database test_40066")
defer tk.MustExec("drop database test_40066")
tk.MustExec("use test_40066")
tk.MustExec("set @orig_sql_mode = @@sql_mode;")
defer tk.MustExec("set @@sql_mode = @orig_sql_mode;")

tk.MustExec(`create table t_int(column1 int, column2 int unsigned generated always as(column1-100));`)
tk.MustExec("set @@sql_mode = DEFAULT;")
tk.MustGetErrMsg("insert into t_int(column1) values (99);", "[types:1264]Out of range value for column 'column2' at row 1")
tk.MustExec("set @@sql_mode = '';")
tk.MustExec("insert into t_int(column1) values (99);")
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1264 Out of range value for column 'column2' at row 1"))
tk.MustQuery("select * from t_int;").Check(testkit.Rows("99 0"))

tk.MustExec(`create table t_float(column1 float, column2 int unsigned generated always as(column1-100));`)
tk.MustExec("set @@sql_mode = DEFAULT;")
tk.MustGetErrMsg("insert into t_float(column1) values (12.95);", "[types:1264]Out of range value for column 'column2' at row 1")
tk.MustExec("set @@sql_mode = '';")
tk.MustExec("insert into t_float(column1) values (12.95);")
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1264 Out of range value for column 'column2' at row 1"))
tk.MustQuery("select * from t_float;").Check(testkit.Rows("12.95 0"))

tk.MustExec(`create table t_decimal(column1 decimal(20,10), column2 int unsigned generated always as(column1-100));`)
tk.MustExec("set @@sql_mode = DEFAULT;")
tk.MustGetErrMsg("insert into t_decimal(column1) values (123.456e-2);", "[types:1264]Out of range value for column 'column2' at row 1")
tk.MustExec("set @@sql_mode = '';")
tk.MustExec("insert into t_decimal(column1) values (123.456e-2);")
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1264 Out of range value for column 'column2' at row 1"))
tk.MustQuery("select * from t_decimal;").Check(testkit.Rows("1.2345600000 0"))

tk.MustExec(`create table t_varchar(column1 varchar(10), column2 int unsigned generated always as(column1-100));`)
tk.MustExec("set @@sql_mode = DEFAULT;")
tk.MustGetErrMsg("insert into t_varchar(column1) values ('87.12');", "[types:1264]Out of range value for column 'column2' at row 1")
tk.MustExec("set @@sql_mode = '';")
tk.MustExec("insert into t_varchar(column1) values ('87.12');")
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1264 Out of range value for column 'column2' at row 1"))
tk.MustQuery("select * from t_varchar;").Check(testkit.Rows("87.12 0"))

tk.MustExec(`create table t_union(column1 float, column2 int unsigned generated always as(column1-100), column3 float unsigned generated always as(column1-100));`)
tk.MustExec("set @@sql_mode = DEFAULT;")
tk.MustGetErrMsg("insert into t_union(column1) values (12.95);", "[types:1264]Out of range value for column 'column2' at row 1")
tk.MustExec("set @@sql_mode = '';")
tk.MustExec("insert into t_union(column1) values (12.95);")
tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1264 Out of range value for column 'column2' at row 1", "Warning 1264 Out of range value for column 'column3' at row 1"))
tk.MustQuery("select * from t_union;").Check(testkit.Rows("12.95 0 0"))
}

func TestMutipleReplaceAndInsertInOneSession(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t_securities(id bigint not null auto_increment primary key, security_id varchar(8), market_id smallint, security_type int, unique key uu(security_id, market_id))")
tk.MustExec(`insert into t_securities (security_id, market_id, security_type) values ("1", 2, 7), ("7", 1, 7) ON DUPLICATE KEY UPDATE security_type = VALUES(security_type)`)
tk.MustExec(`replace into t_securities (security_id, market_id, security_type) select security_id+1, 1, security_type from t_securities where security_id="7";`)
tk.MustExec(`INSERT INTO t_securities (security_id, market_id, security_type) values ("1", 2, 7), ("7", 1, 7) ON DUPLICATE KEY UPDATE security_type = VALUES(security_type)`)

tk.MustQuery("select * from t_securities").Sort().Check(testkit.Rows("1 1 2 7", "2 7 1 7", "3 8 1 7"))

tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use test")
tk2.MustExec(`insert into t_securities (security_id, market_id, security_type) values ("1", 2, 7), ("7", 1, 7) ON DUPLICATE KEY UPDATE security_type = VALUES(security_type)`)
tk2.MustExec(`insert into t_securities (security_id, market_id, security_type) select security_id+2, 1, security_type from t_securities where security_id="7";`)
tk2.MustExec(`INSERT INTO t_securities (security_id, market_id, security_type) values ("1", 2, 7), ("7", 1, 7) ON DUPLICATE KEY UPDATE security_type = VALUES(security_type)`)

tk2.MustQuery("select * from t_securities").Sort().Check(testkit.Rows("1 1 2 7", "2 7 1 7", "3 8 1 7", "8 9 1 7"))
}
>>>>>>> 875e34d28a1 (executor: fix uint type overflow on generated column not compatible with mysql (#40157)):executor/writetest/write_test.go
55 changes: 55 additions & 0 deletions table/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,58 @@ func OptionalFsp(fieldType *types.FieldType) string {
}
return "(" + strconv.Itoa(fsp) + ")"
}
<<<<<<< HEAD
=======

// FillVirtualColumnValue will calculate the virtual column value by evaluating generated
// expression using rows from a chunk, and then fill this value into the chunk.
func FillVirtualColumnValue(virtualRetTypes []*types.FieldType, virtualColumnIndex []int,
expCols []*expression.Column, colInfos []*model.ColumnInfo, sctx sessionctx.Context, req *chunk.Chunk) error {
if len(virtualColumnIndex) == 0 {
return nil
}

virCols := chunk.NewChunkWithCapacity(virtualRetTypes, req.Capacity())
iter := chunk.NewIterator4Chunk(req)
for i, idx := range virtualColumnIndex {
for row := iter.Begin(); row != iter.End(); row = iter.Next() {
datum, err := expCols[idx].EvalVirtualColumn(row)
if err != nil {
return err
}
// Because the expression might return different type from
// the generated column, we should wrap a CAST on the result.
castDatum, err := CastValue(sctx, datum, colInfos[idx], false, true)
if err != nil {
return err
}

// Clip to zero if get negative value after cast to unsigned.
if mysql.HasUnsignedFlag(colInfos[idx].FieldType.GetFlag()) && !castDatum.IsNull() && !sctx.GetSessionVars().StmtCtx.ShouldClipToZero() {
switch datum.Kind() {
case types.KindInt64:
if datum.GetInt64() < 0 {
castDatum = GetZeroValue(colInfos[idx])
}
case types.KindFloat32, types.KindFloat64:
if types.RoundFloat(datum.GetFloat64()) < 0 {
castDatum = GetZeroValue(colInfos[idx])
}
case types.KindMysqlDecimal:
if datum.GetMysqlDecimal().IsNegative() {
castDatum = GetZeroValue(colInfos[idx])
}
}
}

// Handle the bad null error.
if (mysql.HasNotNullFlag(colInfos[idx].GetFlag()) || mysql.HasPreventNullInsertFlag(colInfos[idx].GetFlag())) && castDatum.IsNull() {
castDatum = GetZeroValue(colInfos[idx])
}
virCols.AppendDatum(i, &castDatum)
}
req.SetCol(idx, virCols.Column(i))
}
return nil
}
>>>>>>> 875e34d28a1 (executor: fix uint type overflow on generated column not compatible with mysql (#40157))

0 comments on commit 371dca8

Please sign in to comment.