diff --git a/pkg/bindinfo/global_handle_test.go b/pkg/bindinfo/global_handle_test.go index 8eb4113ba0b5ea..3325e9be378981 100644 --- a/pkg/bindinfo/global_handle_test.go +++ b/pkg/bindinfo/global_handle_test.go @@ -550,11 +550,10 @@ func TestSetVarFixControlWithBinding(t *testing.T) { tk.MustExec(`create table t(id int, a varchar(100), b int, c int, index idx_ab(a, b))`) tk.MustQuery(`explain select * from t where c = 10 and (a = 'xx' or (a = 'kk' and b = 1))`).Check( testkit.Rows( - `IndexLookUp_12 0.01 root `, - `├─Selection_10(Build) 0.02 cop[tikv] or(eq(test.t.a, "xx"), and(eq(test.t.a, "kk"), eq(test.t.b, 1)))`, - `│ └─IndexRangeScan_8 20.00 cop[tikv] table:t, index:idx_ab(a, b) range:["kk","kk"], ["xx","xx"], keep order:false, stats:pseudo`, - `└─Selection_11(Probe) 0.01 cop[tikv] eq(test.t.c, 10)`, - ` └─TableRowIDScan_9 0.02 cop[tikv] table:t keep order:false, stats:pseudo`)) + `IndexLookUp_11 0.01 root `, + `├─IndexRangeScan_8(Build) 10.10 cop[tikv] table:t, index:idx_ab(a, b) range:["kk" 1,"kk" 1], ["xx","xx"], keep order:false, stats:pseudo`, + `└─Selection_10(Probe) 0.01 cop[tikv] eq(test.t.c, 10)`, + ` └─TableRowIDScan_9 10.10 cop[tikv] table:t keep order:false, stats:pseudo`)) tk.MustExec(`create global binding using select /*+ set_var(tidb_opt_fix_control='44389:ON') */ * from t where c = 10 and (a = 'xx' or (a = 'kk' and b = 1))`) tk.MustQuery(`show warnings`).Check(testkit.Rows()) // no warning diff --git a/pkg/expression/util.go b/pkg/expression/util.go index 308805f62f6532..43cb1a009553f5 100644 --- a/pkg/expression/util.go +++ b/pkg/expression/util.go @@ -17,7 +17,6 @@ package expression import ( "bytes" "context" - "fmt" "math" "strconv" "strings" @@ -994,9 +993,11 @@ func containOuterNot(expr Expression, not bool) bool { func Contains(exprs []Expression, e Expression) bool { for _, expr := range exprs { // Check string equivalence if one of the expressions is a clone. - str1 := fmt.Sprintf("", e) - str2 := fmt.Sprintf("", expr) - if e == expr || (str1 == str2) { + sameString := false + if e != nil && expr != nil { + sameString = (e.String() == expr.String()) + } + if e == expr || sameString { return true } } diff --git a/pkg/planner/core/casetest/index/BUILD.bazel b/pkg/planner/core/casetest/index/BUILD.bazel index 96df3221e09ffa..3f264708225fa5 100644 --- a/pkg/planner/core/casetest/index/BUILD.bazel +++ b/pkg/planner/core/casetest/index/BUILD.bazel @@ -9,6 +9,7 @@ go_test( ], data = glob(["testdata/**"]), flaky = True, + shard_count = 3, deps = [ "//pkg/testkit", "//pkg/testkit/testdata", diff --git a/pkg/planner/core/casetest/index/index_test.go b/pkg/planner/core/casetest/index/index_test.go index a72e670d772624..3909b655667a49 100644 --- a/pkg/planner/core/casetest/index/index_test.go +++ b/pkg/planner/core/casetest/index/index_test.go @@ -85,12 +85,12 @@ func TestInvisibleIndex(t *testing.T) { tk.MustExec("use test") tk.MustExec("CREATE TABLE t1 ( a INT, KEY( a ) INVISIBLE );") tk.MustExec("INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);") - tk.MustQuery(`select a FROM t1;`).Check( + tk.MustQuery(`EXPLAIN SELECT a FROM t1;`).Check( testkit.Rows( `TableReader_5 10000.00 root data:TableFullScan_4`, `└─TableFullScan_4 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo`)) tk.MustExec("set session tidb_opt_use_invisible_indexes=on;") - tk.MustQuery(`select a FROM t1;`).Check( + tk.MustQuery(`EXPLAIN SELECT a FROM t1;`).Check( testkit.Rows( `IndexReader_7 10000.00 root index:IndexFullScan_6`, `└─IndexFullScan_6 10000.00 cop[tikv] table:t1, index:a(a) keep order:false, stats:pseudo`)) @@ -122,5 +122,4 @@ func TestRangeDerivation(t *testing.T) { }) plan.Check(testkit.Rows(output[i].Plan...)) } - } diff --git a/pkg/util/ranger/types.go b/pkg/util/ranger/types.go index 405ea8959c8d61..ef8977baa080a4 100644 --- a/pkg/util/ranger/types.go +++ b/pkg/util/ranger/types.go @@ -294,26 +294,20 @@ func prefix(tc types.Context, superValue []types.Datum, supValue []types.Datum, return true } -// Check if a list of ranges(subRanges) is a subset of another list of ranges(superRanges). +// Subset checks if a list of ranges(rs) is a subset of another list of ranges(superRanges). // This is true if every range in the first list is a subset of any // range in the second list. Also, we check if all elements of superRanges are covered. -func (subRanges Ranges) Subset(tc types.Context, superRanges Ranges) bool { +func (rs Ranges) Subset(tc types.Context, superRanges Ranges) bool { var subset bool superRangesCovered := make([]bool, len(superRanges)) - if len(subRanges) == 0 { - // Both lists are unrestricted - if len(superRanges) == 0 { - return true - } else { - // unrestricted subRanges and restricted superRanges - return false - } + if len(rs) == 0 { + return len(superRanges) == 0 } else if len(superRanges) == 0 { - // unrestricted superRanges and restricted subRanges + // unrestricted superRanges and restricted rs return true } - for _, subRange := range subRanges { + for _, subRange := range rs { subset = false for i, superRange := range superRanges { if subRange.Subset(tc, superRange) { @@ -335,35 +329,34 @@ func (subRanges Ranges) Subset(tc types.Context, superRanges Ranges) bool { return true } -// check if range(subRange) is a subset of another range(superRange). +// Subset for Range type, check if range(ran) is a subset of another range(superRange). // This is done by: -// - Both subRange and superRange have the same collators. This is not needed for the current code path. +// - Both ran and superRange have the same collators. This is not needed for the current code path. // But, it is used here for future use of the function. -// - Checking if the lower/upper bound of superRange covers the corresponding lower/upper bound of subRange. +// - Checking if the lower/upper bound of superRange covers the corresponding lower/upper bound of ran. // Thus include checking open/closed inetrvals. -func (subRange *Range) Subset(tc types.Context, superRange *Range) bool { - - if len(subRange.LowVal) < len(superRange.LowVal) { +func (ran *Range) Subset(tc types.Context, superRange *Range) bool { + if len(ran.LowVal) < len(superRange.LowVal) { return false } - // Make sure both subRange and superRange have the same collations. + // Make sure both ran and superRange have the same collations. // The current code path for this function always will have same collation - // for subRange and superRange. It is added here for future + // for ran and superRange. It is added here for future // use of the function. for i := 0; i < len(superRange.LowVal); i++ { - if subRange.Collators[i] != superRange.Collators[i] { + if ran.Collators[i] != superRange.Collators[i] { return false } } // Either superRange is closed or both ranges have the same open/close setting. - lowExcludeOK := !superRange.LowExclude || subRange.LowExclude == superRange.LowExclude - highExcludeOK := !superRange.HighExclude || subRange.HighExclude == superRange.HighExclude + lowExcludeOK := !superRange.LowExclude || ran.LowExclude == superRange.LowExclude + highExcludeOK := !superRange.HighExclude || ran.HighExclude == superRange.HighExclude if !lowExcludeOK || !highExcludeOK { return false } - return prefix(tc, superRange.LowVal, subRange.LowVal, len(superRange.LowVal), subRange.Collators) && - prefix(tc, superRange.HighVal, subRange.HighVal, len(superRange.LowVal), subRange.Collators) + return prefix(tc, superRange.LowVal, ran.LowVal, len(superRange.LowVal), ran.Collators) && + prefix(tc, superRange.HighVal, ran.HighVal, len(superRange.LowVal), ran.Collators) }