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

executor: refineArgs() bug fix when compare int with very small decimal (#23694) #23705

Merged
merged 8 commits into from
May 10, 2021
15 changes: 11 additions & 4 deletions expression/builtin_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -1344,8 +1344,13 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express
// int non-constant [cmp] non-int constant
if arg0IsInt && !arg0IsCon && !arg1IsInt && arg1IsCon {
arg1, isExceptional = RefineComparedConstant(ctx, *arg0Type, arg1, c.op)
finalArg1 = arg1
if isExceptional && arg1.GetType().EvalType() == types.ETInt {
// Why check not null flag
// eg: int_col > const_val(which is less than min_int32)
// If int_col got null, compare result cannot be true
if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg0Type.Flag)) {
finalArg1 = arg1
}
if isExceptional && arg1.GetType().EvalType() == types.ETInt && mysql.HasNotNullFlag(arg0Type.Flag) {
// Judge it is inf or -inf
// For int:
// inf: 01111111 & 1 == 1
Expand All @@ -1363,8 +1368,10 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express
// non-int constant [cmp] int non-constant
if arg1IsInt && !arg1IsCon && !arg0IsInt && arg0IsCon {
arg0, isExceptional = RefineComparedConstant(ctx, *arg1Type, arg0, symmetricOp[c.op])
finalArg0 = arg0
if isExceptional && arg0.GetType().EvalType() == types.ETInt {
if !isExceptional || (isExceptional && mysql.HasNotNullFlag(arg1Type.Flag)) {
finalArg0 = arg0
}
if isExceptional && arg0.GetType().EvalType() == types.ETInt && mysql.HasNotNullFlag(arg1Type.Flag) {
if arg0.Value.GetInt64()&1 == 1 {
isNegativeInfinite = true
} else {
Expand Down
2 changes: 1 addition & 1 deletion expression/builtin_compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
)

func (s *testEvaluatorSuite) TestCompareFunctionWithRefine(c *C) {
tblInfo := newTestTableBuilder("").add("a", mysql.TypeLong).build()
tblInfo := newTestTableBuilder("").add("a", mysql.TypeLong, mysql.NotNullFlag).build()
tests := []struct {
exprStr string
result string
Expand Down
7 changes: 5 additions & 2 deletions expression/expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *testEvaluatorSuite) TestNewValuesFunc(c *C) {
}

func (s *testEvaluatorSuite) TestEvaluateExprWithNull(c *C) {
tblInfo := newTestTableBuilder("").add("col0", mysql.TypeLonglong).add("col1", mysql.TypeLonglong).build()
tblInfo := newTestTableBuilder("").add("col0", mysql.TypeLonglong, 0).add("col1", mysql.TypeLonglong, 0).build()
schema := tableInfoToSchemaForTest(tblInfo)
col0 := schema.Columns[0]
col1 := schema.Columns[1]
Expand Down Expand Up @@ -142,15 +142,17 @@ type testTableBuilder struct {
tableName string
columnNames []string
tps []byte
flags []uint
}

func newTestTableBuilder(tableName string) *testTableBuilder {
return &testTableBuilder{tableName: tableName}
}

func (builder *testTableBuilder) add(name string, tp byte) *testTableBuilder {
func (builder *testTableBuilder) add(name string, tp byte, flag uint) *testTableBuilder {
builder.columnNames = append(builder.columnNames, name)
builder.tps = append(builder.tps, tp)
builder.flags = append(builder.flags, flag)
return builder
}

Expand All @@ -165,6 +167,7 @@ func (builder *testTableBuilder) build() *model.TableInfo {
fieldType := types.NewFieldType(tp)
fieldType.Flen, fieldType.Decimal = mysql.GetDefaultFieldLengthAndDecimal(tp)
fieldType.Charset, fieldType.Collate = types.DefaultCharsetForType(tp)
fieldType.Flag = builder.flags[i]
ti.Columns = append(ti.Columns, &model.ColumnInfo{
ID: int64(i + 1),
Name: model.NewCIStr(colName),
Expand Down
9 changes: 9 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8121,6 +8121,15 @@ func (s *testIntegrationSuite) TestIssue23889(c *C) {
testkit.Rows("<nil>", "0"))
}

func (s *testIntegrationSuite) TestIssue23623(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 int);")
tk.MustExec("insert into t1 values(-2147483648), (-2147483648), (null);")
tk.MustQuery("select count(*) from t1 where c1 > (select sum(c1) from t1);").Check(testkit.Rows("2"))
}

func (s *testIntegrationSerialSuite) TestCollationForBinaryLiteral(c *C) {
tk := testkit.NewTestKit(c, s.store)
collate.SetNewCollationEnabledForTest(true)
Expand Down
2 changes: 1 addition & 1 deletion planner/core/cbo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func (s *testAnalyzeSuite) TestPreparedNullParam(c *C) {
testKit := testkit.NewTestKit(c, store)
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t")
testKit.MustExec("create table t (id int, KEY id (id))")
testKit.MustExec("create table t (id int not null, KEY id (id))")
testKit.MustExec("insert into t values (1), (2), (3)")

sql := "select * from t where id = ?"
Expand Down