From 019c5fb2b826e335e145a7884b6584dd27de4969 Mon Sep 17 00:00:00 2001 From: Jun-Seok Heo Date: Fri, 28 Sep 2018 09:45:58 +0900 Subject: [PATCH] fix: #7579 --- executor/prepared_test.go | 43 ++++++++++++++++++++++++++++ expression/util.go | 2 +- planner/core/find_best_task.go | 2 +- planner/core/logical_plan_builder.go | 2 +- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/executor/prepared_test.go b/executor/prepared_test.go index 3e19ca79b9e95..8a255a3b2d6c9 100644 --- a/executor/prepared_test.go +++ b/executor/prepared_test.go @@ -322,3 +322,46 @@ func generateBatchSQL(paramCount int) (sql string, paramSlice []interface{}) { } return "insert into t values " + strings.Join(placeholders, ","), params } + +func (s *testSuite) TestPreparedIssue7579(c *C) { + orgEnable := plannercore.PreparedPlanCacheEnabled() + orgCapacity := plannercore.PreparedPlanCacheCapacity + defer func() { + plannercore.SetPreparedPlanCache(orgEnable) + plannercore.PreparedPlanCacheCapacity = orgCapacity + }() + flags := []bool{false, true} + for _, flag := range flags { + plannercore.SetPreparedPlanCache(flag) + plannercore.PreparedPlanCacheCapacity = 100 + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, index a_idx(a))") + tk.MustExec("insert into t values (1,1), (2,2), (null,3)") + + r := tk.MustQuery("select a, b from t order by b asc;") + r.Check(testkit.Rows("1 1", "2 2", " 3")) + + tk.MustExec(`prepare stmt from 'select a, b from t where ? order by b asc'`) + + r = tk.MustQuery(`execute stmt using @param;`) + r.Check(nil) + + tk.MustExec(`set @param = true`) + r = tk.MustQuery(`execute stmt using @param;`) + r.Check(testkit.Rows("1 1", "2 2", " 3")) + + tk.MustExec(`set @param = false`) + r = tk.MustQuery(`execute stmt using @param;`) + r.Check(nil) + + tk.MustExec(`set @param = 1`) + r = tk.MustQuery(`execute stmt using @param;`) + r.Check(testkit.Rows("1 1", "2 2", " 3")) + + tk.MustExec(`set @param = 0`) + r = tk.MustQuery(`execute stmt using @param;`) + r.Check(nil) + } +} diff --git a/expression/util.go b/expression/util.go index 70cf52e9a7df7..bfdea1e028964 100644 --- a/expression/util.go +++ b/expression/util.go @@ -191,7 +191,7 @@ func SubstituteCorCol2Constant(expr Expression) (Expression, error) { case *Constant: if x.DeferredExpr != nil { newExpr := FoldConstant(x) - return &Constant{Value: newExpr.(*Constant).Value, RetType: x.GetType()}, nil + return &Constant{Value: newExpr.(*Constant).Value, RetType: x.GetType(), DeferredExpr: x.DeferredExpr}, nil } } return expr, nil diff --git a/planner/core/find_best_task.go b/planner/core/find_best_task.go index f84a6578bf98d..dec22b1559e2e 100644 --- a/planner/core/find_best_task.go +++ b/planner/core/find_best_task.go @@ -179,7 +179,7 @@ func (ds *DataSource) tryToGetMemTask(prop *property.PhysicalProperty) (task tas // tryToGetDualTask will check if the push down predicate has false constant. If so, it will return table dual. func (ds *DataSource) tryToGetDualTask() (task, error) { for _, cond := range ds.pushedDownConds { - if _, ok := cond.(*expression.Constant); ok { + if con, ok := cond.(*expression.Constant); ok && con.DeferredExpr == nil { result, err := expression.EvalBool(ds.ctx, []expression.Expression{cond}, chunk.Row{}) if err != nil { return nil, errors.Trace(err) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 35653f2db8a8f..54c4361357442 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -470,7 +470,7 @@ func (b *planBuilder) buildSelection(p LogicalPlan, where ast.ExprNode, AggMappe } cnfItems := expression.SplitCNFItems(expr) for _, item := range cnfItems { - if con, ok := item.(*expression.Constant); ok { + if con, ok := item.(*expression.Constant); ok && con.DeferredExpr == nil { ret, err := expression.EvalBool(b.ctx, expression.CNFExprs{con}, chunk.Row{}) if err != nil || ret { continue