diff --git a/util/ranger/ranger_test.go b/util/ranger/ranger_test.go index db54c134b6cfd..e424a6b640881 100644 --- a/util/ranger/ranger_test.go +++ b/util/ranger/ranger_test.go @@ -17,6 +17,8 @@ package ranger_test import ( "context" "fmt" + "strconv" + "strings" "testing" "github.com/pingcap/tidb/config" @@ -31,6 +33,7 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/ranger" "github.com/stretchr/testify/require" @@ -2620,3 +2623,43 @@ func TestIssue44389(t *testing.T) { testKit.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...)) } } + +func checkIndexRange(t *testing.T, tk *testkit.TestKit, expectedIndexName, expectedIndexRange string) { + tkProcess := tk.Session().ShowProcess() + ps := []*util.ProcessInfo{tkProcess} + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + rows := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)).Rows() + useIndex := false + for _, row := range rows { + if strings.Contains(row[4].(string), expectedIndexName) { + require.True(t, strings.Contains(row[6].(string), expectedIndexRange)) + useIndex = true + break + } + } + require.True(t, useIndex) +} + +func TestIssue44389ForPreparedPlanCache(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, c int, index idx_ab(a, b))") + tk.MustExec("set @@tidb_opt_fix_control = '44389:ON'") + + // The plan using CNF item index range result, it + tk.MustExec("prepare stmt1 from 'select * from t where c = 10 and (a = 1 or (a = 3 and b = ?))'") + tk.MustExec("set @x = 2") + tk.MustExec("execute stmt1 using @x") + checkIndexRange(t, tk, "idx_ab", "[1,1], [3 2,3 2]") + tk.MustExec("execute stmt1 using @x") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec("prepare stmt2 from 'select * from t where c = 10 and (a = 1 or (a >= ? and a <= ? and b = 2))'") + tk.MustExec("set @x = 3, @y = 3") + tk.MustExec("execute stmt2 using @x, @y") + checkIndexRange(t, tk, "idx_ab", "[1,1], [3 2,3 2]") + tk.MustExec("execute stmt1 using @x") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +} diff --git a/util/ranger/testdata/ranger_suite_in.json b/util/ranger/testdata/ranger_suite_in.json index a862e85f2450e..d4e288764abcb 100644 --- a/util/ranger/testdata/ranger_suite_in.json +++ b/util/ranger/testdata/ranger_suite_in.json @@ -121,6 +121,7 @@ "name": "TestIssue44389", "cases": [ "select * from t where c = 10 and (a = 'xx' or (a = 'kk' and b = 1))", + "select * from t where c = 10 and (a = 'xx' or (a = 'hh' and b > 2))", "select * from t where c = 10 and ((a = 'xx' or a = 'yy') or ((a = 'kk' and b = 1) or (a = 'hh' and b = 2)))" ] } diff --git a/util/ranger/testdata/ranger_suite_out.json b/util/ranger/testdata/ranger_suite_out.json index 8e5385a843848..72baa1ae1d331 100644 --- a/util/ranger/testdata/ranger_suite_out.json +++ b/util/ranger/testdata/ranger_suite_out.json @@ -740,6 +740,19 @@ "xx 4 10" ] }, + { + "SQL": "select * from t where c = 10 and (a = 'xx' or (a = 'hh' and b > 2))", + "Plan": [ + "IndexLookUp_11 0.04 root ", + "├─IndexRangeScan_8(Build) 43.33 cop[tikv] table:t, index:idx_ab(a, b) range:(\"hh\" 2,\"hh\" +inf], [\"xx\",\"xx\"], keep order:false, stats:pseudo", + "└─Selection_10(Probe) 0.04 cop[tikv] eq(test.t.c, 10)", + " └─TableRowIDScan_9 43.33 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Result": [ + "hh 3 10", + "xx 4 10" + ] + }, { "SQL": "select * from t where c = 10 and ((a = 'xx' or a = 'yy') or ((a = 'kk' and b = 1) or (a = 'hh' and b = 2)))", "Plan": [