Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: do not cache prepared plan if optimization depends on mutable constant #22349

Merged
merged 4 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion expression/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,18 @@ func SplitDNFItems(onExpr Expression) []Expression {
// EvaluateExprWithNull sets columns in schema as null and calculate the final result of the scalar function.
// If the Expression is a non-constant value, it means the result is unknown.
func EvaluateExprWithNull(ctx sessionctx.Context, schema *Schema, expr Expression) Expression {
if ContainMutableConst(ctx, []Expression{expr}) {
ctx.GetSessionVars().StmtCtx.OptimDependOnMutableConst = true
}
return evaluateExprWithNull(ctx, schema, expr)
}

func evaluateExprWithNull(ctx sessionctx.Context, schema *Schema, expr Expression) Expression {
switch x := expr.(type) {
case *ScalarFunction:
args := make([]Expression, len(x.GetArgs()))
for i, arg := range x.GetArgs() {
args[i] = EvaluateExprWithNull(ctx, schema, arg)
args[i] = evaluateExprWithNull(ctx, schema, arg)
}
return NewFunctionInternal(ctx, x.FuncName.L, x.RetType, args...)
case *Column:
Expand Down
2 changes: 1 addition & 1 deletion planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ REBUILD:
e.names = names
e.Plan = p
_, isTableDual := p.(*PhysicalTableDual)
if !isTableDual && prepared.UseCache {
if !isTableDual && prepared.UseCache && !stmtCtx.OptimDependOnMutableConst {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. It seems all places that use ContainMutableConst should be modified. We can only modify EvaluateExprWithNull in this PR and change all other places later in another PR.

cached := NewPSTMTPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan, tps)
preparedStmt.NormalizedPlan, preparedStmt.PlanDigest = NormalizePlan(p)
stmtCtx.SetPlanDigest(preparedStmt.NormalizedPlan, preparedStmt.PlanDigest)
Expand Down
29 changes: 29 additions & 0 deletions planner/core/prepare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,3 +892,32 @@ func (s *testPrepareSuite) TestInvisibleIndex(c *C) {
c.Assert(len(tk.Se.GetSessionVars().StmtCtx.IndexNames), Equals, 1)
c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx_a")
}

// Test for issue https://github.com/pingcap/tidb/issues/22167
func (s *testPrepareSerialSuite) TestPrepareCacheWithJoinTable(c *C) {
defer testleak.AfterTest(c)()
store, dom, err := newStoreWithBootstrap()
c.Assert(err, IsNil)
tk := testkit.NewTestKit(c, store)
orgEnable := core.PreparedPlanCacheEnabled()
defer func() {
dom.Close()
store.Close()
core.SetPreparedPlanCache(orgEnable)
}()
core.SetPreparedPlanCache(true)
tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
c.Assert(err, IsNil)

tk.MustExec("use test")
tk.MustExec("drop table if exists ta, tb")
tk.MustExec("CREATE TABLE ta(k varchar(32) NOT NULL DEFAULT ' ')")
tk.MustExec("CREATE TABLE tb (k varchar(32) NOT NULL DEFAULT ' ', s varchar(1) NOT NULL DEFAULT ' ')")
tk.MustExec("insert into ta values ('a')")
tk.MustExec("set @a=2, @b=1")
tk.MustExec(`prepare stmt from "select * from ta a left join tb b on 1 where ? = 1 or b.s is not null"`)
tk.MustQuery("execute stmt using @a").Check(testkit.Rows())
tk.MustQuery("execute stmt using @b").Check(testkit.Rows("a <nil> <nil>"))
}
43 changes: 22 additions & 21 deletions sessionctx/stmtctx/stmtctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,27 +60,28 @@ type StatementContext struct {

// IsDDLJobInQueue is used to mark whether the DDL job is put into the queue.
// If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker.
IsDDLJobInQueue bool
InInsertStmt bool
InUpdateStmt bool
InDeleteStmt bool
InSelectStmt bool
InLoadDataStmt bool
InExplainStmt bool
InCreateOrAlterStmt bool
IgnoreTruncate bool
IgnoreZeroInDate bool
DupKeyAsWarning bool
BadNullAsWarning bool
DividedByZeroAsWarning bool
TruncateAsWarning bool
OverflowAsWarning bool
InShowWarning bool
UseCache bool
BatchCheck bool
InNullRejectCheck bool
AllowInvalidDate bool
IgnoreNoPartition bool
IsDDLJobInQueue bool
InInsertStmt bool
InUpdateStmt bool
InDeleteStmt bool
InSelectStmt bool
InLoadDataStmt bool
InExplainStmt bool
InCreateOrAlterStmt bool
IgnoreTruncate bool
IgnoreZeroInDate bool
DupKeyAsWarning bool
BadNullAsWarning bool
DividedByZeroAsWarning bool
TruncateAsWarning bool
OverflowAsWarning bool
InShowWarning bool
UseCache bool
BatchCheck bool
InNullRejectCheck bool
AllowInvalidDate bool
IgnoreNoPartition bool
OptimDependOnMutableConst bool

// mu struct holds variables that change during execution.
mu struct {
Expand Down