diff --git a/planner/core/issuetest/planner_issue_test.go b/planner/core/issuetest/planner_issue_test.go new file mode 100644 index 0000000000000..a52053ac46d08 --- /dev/null +++ b/planner/core/issuetest/planner_issue_test.go @@ -0,0 +1,36 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package issuetest + +import ( + "testing" + + "github.com/pingcap/tidb/testkit" +) + +func TestIssue43645(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("CREATE TABLE t1(id int,col1 varchar(10),col2 varchar(10),col3 varchar(10));") + tk.MustExec("CREATE TABLE t2(id int,col1 varchar(10),col2 varchar(10),col3 varchar(10));") + tk.MustExec("INSERT INTO t1 values(1,NULL,NULL,null),(2,NULL,NULL,null),(3,NULL,NULL,null);") + tk.MustExec("INSERT INTO t2 values(1,'a','aa','aaa'),(2,'b','bb','bbb'),(3,'c','cc','ccc');") + + rs := tk.MustQuery("WITH tmp AS (SELECT t2.* FROM t2) select (SELECT tmp.col1 FROM tmp WHERE tmp.id=t1.id ) col1, (SELECT tmp.col2 FROM tmp WHERE tmp.id=t1.id ) col2, (SELECT tmp.col3 FROM tmp WHERE tmp.id=t1.id ) col3 from t1;") + rs.Sort().Check(testkit.Rows("a aa aaa", "b bb bbb", "c cc ccc")) +} diff --git a/planner/core/rule_predicate_push_down.go b/planner/core/rule_predicate_push_down.go index bcefe8ec1bae0..836f75050a80a 100644 --- a/planner/core/rule_predicate_push_down.go +++ b/planner/core/rule_predicate_push_down.go @@ -941,13 +941,26 @@ func (p *LogicalCTE) PredicatePushDown(predicates []expression.Expression, opt * if !p.isOuterMostCTE { return predicates, p.self } - if len(predicates) == 0 { + pushedPredicates := make([]expression.Expression, len(predicates)) + copy(pushedPredicates, predicates) + // The filter might change the correlated status of the cte. + // We forbid the push down that makes the change for now. + // Will support it later. + if !p.cte.IsInApply { + for i := len(pushedPredicates) - 1; i >= 0; i-- { + if len(expression.ExtractCorColumns(pushedPredicates[i])) == 0 { + continue + } + pushedPredicates = append(pushedPredicates[0:i], pushedPredicates[i+1:]...) + } + } + if len(pushedPredicates) == 0 { p.cte.pushDownPredicates = append(p.cte.pushDownPredicates, expression.NewOne()) return predicates, p.self } newPred := make([]expression.Expression, 0, len(predicates)) - for i := range predicates { - newPred = append(newPred, predicates[i].Clone()) + for i := range pushedPredicates { + newPred = append(newPred, pushedPredicates[i].Clone()) ResolveExprAndReplace(newPred[i], p.cte.ColumnMap) } p.cte.pushDownPredicates = append(p.cte.pushDownPredicates, expression.ComposeCNFCondition(p.ctx, newPred...))