diff --git a/executor/explainfor_test.go b/executor/explainfor_test.go index cc42d4b5c0107..1708b0f7463c8 100644 --- a/executor/explainfor_test.go +++ b/executor/explainfor_test.go @@ -20,6 +20,7 @@ import ( "fmt" "math" "strconv" + "strings" "sync" . "github.com/pingcap/check" @@ -958,7 +959,7 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { tk.MustExec("set @a=9, @b=10, @c=11;") tk.MustQuery("execute stmt using @a, @a;").Check(testkit.Rows("10 10 10")) tk.MustQuery("execute stmt using @a, @c;").Check(testkit.Rows("10 10 10", "11 11 11")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) // a>=9 and a<=9 --> a=9 tk.MustQuery("execute stmt using @c, @a;").Check(testkit.Rows("10 10 10")) tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) @@ -1527,3 +1528,28 @@ func (s *testSuite) TestIssue28792(c *C) { r2 := tk.MustQuery("EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 use index () on t12.b = t97.b;").Rows() c.Assert(r1, DeepEquals, r2) } + +func (s *testSuite) TestIssue38533(c *C) { + store, dom, err := newStoreWithBootstrap() + c.Assert(err, IsNil) + defer func() { + dom.Close() + store.Close() + }() + tk := testkit.NewTestKit(c, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int, key (a))") + tk.MustExec(`prepare st from "select /*+ use_index(t, a) */ a from t where a=? and a=?"`) + tk.MustExec(`set @a=1`) + tk.MustExec(`execute st using @a, @a`) + + tkProcess := tk.Se.ShowProcess() + ps := []*util.ProcessInfo{tkProcess} + tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + plan := tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() + c.Assert(strings.Contains(plan[1][0].(string), "RangeScan"), IsTrue) // range-scan instead of full-scan + + tk.MustExec(`execute st using @a, @a`) + tk.MustExec(`execute st using @a, @a`) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +} diff --git a/planner/core/prepare_test.go b/planner/core/prepare_test.go index baf701af22a0e..e0933a3bcf3f4 100644 --- a/planner/core/prepare_test.go +++ b/planner/core/prepare_test.go @@ -1520,7 +1520,7 @@ func (s *testPlanSerialSuite) TestIssue29303(c *C) { tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows()) tk.MustExec(`set @a="龂", @b="龂", @c="龂", @d="龂"`) tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows("� 龂 � 龂")) - tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) } func (s *testPlanSerialSuite) TestIssue28942(c *C) { @@ -2037,11 +2037,10 @@ func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { tk.MustExec("insert into t1 values('0000','7777',1)") tk.MustExec("prepare s1 from 'select * from t1 where c1=? and c2>=? and c2<=?'") tk.MustExec("set @a1='0000', @b1='9999'") - // IndexLookup plan would be built, we should cache it. tk.MustQuery("execute s1 using @a1, @b1, @b1").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute s1 using @a1, @a1, @b1").Check(testkit.Rows("0000 7777 1")) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // c2>=9999 and c2<=9999 --> c2=9999 tk.MustExec("create table t2(c1 bigint(20) primary key, c2 varchar(20))") tk.MustExec("insert into t2 values(1,'7777')") @@ -2057,11 +2056,10 @@ func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { tk.MustExec("insert into t3 values(2,1,1)") tk.MustExec("prepare s3 from 'select /*+ use_index_merge(t3) */ * from t3 where (c1 >= ? and c1 <= ?) or c2 > 1'") tk.MustExec("set @a3=1,@b3=3") - // TableReader plan would be built, we should cache it. tk.MustQuery("execute s3 using @a3,@a3").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute s3 using @a3,@b3").Check(testkit.Rows("2 1 1")) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // c1>=1 and c1<=1 --> c1==1 tk.MustExec("prepare s3 from 'select /*+ use_index_merge(t3) */ * from t3 where (c1 >= ? and c1 <= ?) or c2 > 1'") tk.MustExec("set @a3=1,@b3=3") @@ -2078,7 +2076,7 @@ func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { tk.MustQuery("execute s4 using @a4,@a4").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute s4 using @a4,@b4").Check(testkit.Rows("2 1 1")) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // c1>=3 and c1<=3 --> c1=3 tk.MustExec("prepare s4 from 'select /*+ use_index_merge(t4) */ * from t4 where (c1 >= ? and c1 <= ?) or c2 > 1'") tk.MustExec("set @a4=1,@b4=3") @@ -2171,7 +2169,7 @@ func (s *testPlanSerialSuite) TestIssue23671(c *C) { tk.MustQuery("execute s1 using @a, @b, @c").Check(testkit.Rows("1 1")) tk.MustExec("set @a=1, @b=1, @c=10") tk.MustQuery("execute s1 using @a, @b, @c").Check(testkit.Rows("1 1", "2 2")) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // b>=1 and b<=1 --> b=1 } func (s *testPrepareSerialSuite) TestIssue29296(c *C) { diff --git a/util/ranger/detacher.go b/util/ranger/detacher.go index 51bf22e9b62c1..5d99155b0537b 100644 --- a/util/ranger/detacher.go +++ b/util/ranger/detacher.go @@ -504,7 +504,9 @@ func extractValueInfo(expr expression.Expression) *valueInfo { // accesses: The condition will be used to build range. // filters: filters is the part that some access conditions need to be evaluate again since it's only the prefix part of char column. // newConditions: We'll simplify the given conditions if there're multiple in conditions or eq conditions on the same column. -// e.g. if there're a in (1, 2, 3) and a in (2, 3, 4). This two will be combined to a in (2, 3) and pushed to newConditions. +// +// e.g. if there're a in (1, 2, 3) and a in (2, 3, 4). This two will be combined to a in (2, 3) and pushed to newConditions. +// // columnValues: the constant column values for all index columns. columnValues[i] is nil if cols[i] is not constant. // bool: indicate whether there's nil range when merging eq and in conditions. func ExtractEqAndInCondition(sctx sessionctx.Context, conditions []expression.Expression, cols []*expression.Column, @@ -577,8 +579,7 @@ func ExtractEqAndInCondition(sctx sessionctx.Context, conditions []expression.Ex columnValues[i] = &valueInfo{mutable: true} } if expression.MaybeOverOptimized4PlanCache(sctx, conditions) { - // TODO: optimize it more elaborately, e.g. return [2 3, 2 3] as accesses for 'where a = 2 and b = 3 and c >= ? and c <= ?' - return nil, conditions, nil, nil, false + sctx.GetSessionVars().StmtCtx.SkipPlanCache = true } } }