diff --git a/expression/constant_propagation.go b/expression/constant_propagation.go index f7c87e8cb6086..8700553c572ca 100644 --- a/expression/constant_propagation.go +++ b/expression/constant_propagation.go @@ -15,6 +15,8 @@ package expression import ( + "errors" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" @@ -278,6 +280,9 @@ func (s *propConstSolver) propagateColumnEQ() { } func (s *propConstSolver) setConds2ConstFalse() { + if MaybeOverOptimized4PlanCache(s.ctx, s.conditions) { + s.ctx.GetSessionVars().StmtCtx.SetSkipPlanCache(errors.New("some parameters may be overwritten when constant propagation")) + } s.conditions = []Expression{&Constant{ Value: types.NewDatum(false), RetType: types.NewFieldType(mysql.TypeTiny), diff --git a/planner/core/plan_cache_test.go b/planner/core/plan_cache_test.go index f555f561f8c43..555bd80d620de 100644 --- a/planner/core/plan_cache_test.go +++ b/planner/core/plan_cache_test.go @@ -879,6 +879,18 @@ func TestNonPreparedPlanParameterType(t *testing.T) { tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1105 skip non-prepared plan-cache: '1' may be converted to INT`)) } +func TestIssue43852(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`create table t6 (a date, b date, key(a))`) + tk.MustExec(`insert into t6 values ('2023-01-21', '2023-01-05')`) + tk.MustExec(`set tidb_enable_non_prepared_plan_cache=1`) + tk.MustQuery(`select * from t6 where a in (2015, '8')`).Check(testkit.Rows()) + tk.MustQuery(`select * from t6 where a in (2009, '2023-01-21')`).Check(testkit.Rows(`2023-01-21 2023-01-05`)) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) +} + func TestNonPreparedPlanTypeRandomly(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -1984,7 +1996,7 @@ func TestNonPreparedPlanExplainWarning(t *testing.T) { "skip non-prepared plan-cache: queries that have generated columns are not supported", "skip non-prepared plan-cache: queries that access views are not supported", "skip non-prepared plan-cache: query has null constants", - "skip non-prepared plan-cache: get a TableDual plan", + "skip non-prepared plan-cache: some parameters may be overwritten when constant propagation", } all := append(supported, unsupported...) @@ -2280,6 +2292,30 @@ func TestNonPreparedPlanCacheAutoStmtRetry(t *testing.T) { require.ErrorContains(t, tk2Err, "Duplicate entry") } +func TestIssue43667Concurrency(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table cycle (pk int key, val int)") + var wg sync.WaitGroup + concurrency := 30 + for i := 0; i < concurrency; i++ { + tk.MustExec(fmt.Sprintf("insert into cycle values (%v,%v)", i, i)) + wg.Add(1) + go func(id int) { + defer wg.Done() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_enable_non_prepared_plan_cache=1") + query := fmt.Sprintf("select (val) from cycle where pk = %v", id) + for j := 0; j < 5000; j++ { + tk.MustQuery(query).Check(testkit.Rows(fmt.Sprintf("%v", id))) + } + }(i) + } + wg.Wait() +} + func TestIssue43667(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store)