Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#40280
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
qw4990 authored and ti-chi-bot committed Feb 15, 2023
1 parent b85e280 commit 3bb2603
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
32 changes: 30 additions & 2 deletions planner/core/plan_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,24 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
stmtCtx.UseCache = stmtAst.UseCache

var bindSQL string
var ignorePlanCache = false
if stmtCtx.UseCache {
var ignoreByBinding bool
bindSQL, ignoreByBinding = GetBindSQL4PlanCache(sctx, stmt)
if ignoreByBinding {
stmtCtx.SetSkipPlanCache(errors.Errorf("skip plan-cache: ignore plan cache by binding"))
}
}

// In rc or for update read, we need the latest schema version to decide whether we need to
// rebuild the plan. So we set this value in rc or for update read. In other cases, let it be 0.
var latestSchemaVersion int64

<<<<<<< HEAD
if stmtAst.UseCache {
bindSQL, ignorePlanCache = GetBindSQL4PlanCache(sctx, stmt)
=======
if stmtCtx.UseCache {
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
if sctx.GetSessionVars().IsIsolation(ast.ReadCommitted) || stmt.ForUpdateRead {
// In Rc or ForUpdateRead, we should check if the information schema has been changed since
// last time. If it changed, we should rebuild the plan. Here, we use a different and more
Expand All @@ -148,21 +158,35 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,

paramNum, paramTypes := parseParamTypes(sctx, params)

<<<<<<< HEAD
if stmtAst.UseCache && stmtAst.CachedPlan != nil && !ignorePlanCache { // for point query plan
if plan, names, ok, err := getPointQueryPlan(stmtAst, sessVars, stmtCtx); ok {
=======
if stmtCtx.UseCache && stmtAst.CachedPlan != nil { // for point query plan
if plan, names, ok, err := getCachedPointPlan(stmtAst, sessVars, stmtCtx); ok {
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
return plan, names, err
}
}

<<<<<<< HEAD
if stmtAst.UseCache && !ignorePlanCache { // for general plans
if plan, names, ok, err := getGeneralPlan(sctx, isGeneralPlanCache, cacheKey, bindSQL, is, stmt,
=======
if stmtCtx.UseCache { // for non-point plans
if plan, names, ok, err := getCachedPlan(sctx, isNonPrepared, cacheKey, bindSQL, is, stmt,
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
paramTypes); err != nil || ok {
return plan, names, err
}
}

<<<<<<< HEAD
return generateNewPlan(ctx, sctx, isGeneralPlanCache, is, stmt, ignorePlanCache, cacheKey,
latestSchemaVersion, paramNum, paramTypes, bindSQL)
=======
return generateNewPlan(ctx, sctx, isNonPrepared, is, stmt, cacheKey, latestSchemaVersion, paramNum, paramTypes, bindSQL)
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
}

// parseParamTypes get parameters' types in PREPARE statement
Expand Down Expand Up @@ -253,8 +277,12 @@ func getGeneralPlan(sctx sessionctx.Context, isGeneralPlanCache bool, cacheKey k

// generateNewPlan call the optimizer to generate a new plan for current statement
// and try to add it to cache
<<<<<<< HEAD
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlanCache bool, is infoschema.InfoSchema, stmt *PlanCacheStmt,
ignorePlanCache bool, cacheKey kvcache.Key, latestSchemaVersion int64, paramNum int,
=======
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isNonPrepared bool, is infoschema.InfoSchema, stmt *PlanCacheStmt, cacheKey kvcache.Key, latestSchemaVersion int64, paramNum int,
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
paramTypes []*types.FieldType, bindSQL string) (Plan, []*types.FieldName, error) {
stmtAst := stmt.PreparedAst
sessVars := sctx.GetSessionVars()
Expand All @@ -276,7 +304,7 @@ func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlan
if containTableDual(p) && paramNum > 0 {
stmtCtx.SetSkipPlanCache(errors.New("skip plan-cache: get a TableDual plan"))
}
if stmtCtx.UseCache && !ignorePlanCache {
if stmtCtx.UseCache {
// rebuild key to exclude kv.TiFlash when stmt is not read only
if _, isolationReadContainTiFlash := sessVars.IsolationReadEngines[kv.TiFlash]; isolationReadContainTiFlash && !IsReadOnly(stmtAst.Stmt, sessVars) {
delete(sessVars.IsolationReadEngines, kv.TiFlash)
Expand Down
30 changes: 30 additions & 0 deletions planner/core/plan_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,37 @@ func TestPlanCacheDiagInfo(t *testing.T) {
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: some parameters may be overwritten"))
}

<<<<<<< HEAD
func TestIssue40224(t *testing.T) {
=======
func TestIssue40225(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int, key(a))")
tk.MustExec("prepare st from 'select * from t where a<?'")
tk.MustExec("set @a='1'")
tk.MustExec("execute st using @a")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 skip plan-cache: '1' may be converted to INT")) // plan-cache limitation
tk.MustExec("create binding for select * from t where a<1 using select /*+ ignore_plan_cache() */ * from t where a<1")
tk.MustExec("execute st using @a")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 skip plan-cache: ignore plan cache by binding"))
// no warning about plan-cache limitations('1' -> INT) since plan-cache is totally disabled.

tk.MustExec("prepare st from 'select * from t where a>?'")
tk.MustExec("set @a=1")
tk.MustExec("execute st using @a")
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1"))
tk.MustExec("create binding for select * from t where a>1 using select /*+ ignore_plan_cache() */ * from t where a>1")
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
}

func TestUncacheableReason(t *testing.T) {
>>>>>>> 7fafb6db45d (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
Expand Down

0 comments on commit 3bb2603

Please sign in to comment.