From eccb8002c7fafda469cebc4884e0da74d67dce0f Mon Sep 17 00:00:00 2001 From: pingcap-github-bot Date: Wed, 6 May 2020 14:02:45 +0800 Subject: [PATCH] executor: disallow subquery in insert values clause reference upper scope (#16872) (#16952) Co-authored-by: cfzjywxk Co-authored-by: lysu --- executor/executor_test.go | 26 ++++++++++++++++++++++++++ planner/core/planbuilder.go | 14 ++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 50f921eb7ab1a..bd2b3d8ab508b 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -5441,3 +5441,29 @@ func (s *testSuite1) TestIssue16854(c *C) { tk.MustQuery("select distinct a from t order by a").Check(testkit.Rows("WAITING", "PRINTED", "WAITING,PRINTED", "STOCKUP", "WAITING,STOCKUP", "PRINTED,STOCKUP", "WAITING,PRINTED,STOCKUP")) tk.MustExec("drop table t") } + +// this is from jira issue #5856 +func (s *testSuite1) TestInsertValuesWithSubQuery(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2(a int, b int, c int)") + defer tk.MustExec("drop table if exists t2") + + // should not reference upper scope + c.Assert(tk.ExecToErr("insert into t2 values (11, 8, (select not b))"), NotNil) + c.Assert(tk.ExecToErr("insert into t2 set a = 11, b = 8, c = (select b))"), NotNil) + + // subquery reference target table is allowed + tk.MustExec("insert into t2 values(1, 1, (select b from t2))") + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ")) + tk.MustExec("insert into t2 set a = 1, b = 1, c = (select b+1 from t2)") + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ", "1 1 2")) + + // insert using column should work normally + tk.MustExec("delete from t2") + tk.MustExec("insert into t2 values(2, 4, a)") + tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2")) + tk.MustExec("insert into t2 set a = 3, b = 5, c = b") + tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2", "3 5 5")) +} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 13fa6d49faaf8..e053f4c0a9ba2 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -2139,7 +2139,12 @@ func (b *PlanBuilder) buildSetValuesOfInsert(ctx context.Context, insert *ast.In return ErrBadGeneratedColumn.GenWithStackByArgs(assign.Column.Name.O, tableInfo.Name.O) } b.curClause = fieldList - expr, _, err := b.rewriteWithPreprocess(ctx, assign.Expr, mockTablePlan, nil, nil, true, checkRefColumn) + // subquery in insert values should not reference upper scope + usingPlan := mockTablePlan + if _, ok := assign.Expr.(*ast.SubqueryExpr); ok { + usingPlan = LogicalTableDual{}.Init(b.ctx, b.getSelectOffset()) + } + expr, _, err := b.rewriteWithPreprocess(ctx, assign.Expr, usingPlan, nil, nil, true, checkRefColumn) if err != nil { return err } @@ -2212,7 +2217,12 @@ func (b *PlanBuilder) buildValuesListOfInsert(ctx context.Context, insert *ast.I } default: b.curClause = fieldList - expr, _, err = b.rewriteWithPreprocess(ctx, valueItem, mockTablePlan, nil, nil, true, checkRefColumn) + // subquery in insert values should not reference upper scope + usingPlan := mockTablePlan + if _, ok := valueItem.(*ast.SubqueryExpr); ok { + usingPlan = LogicalTableDual{}.Init(b.ctx, b.getSelectOffset()) + } + expr, _, err = b.rewriteWithPreprocess(ctx, valueItem, usingPlan, nil, nil, true, checkRefColumn) } if err != nil { return err