diff --git a/planner/core/logical_plan_test.go b/planner/core/logical_plan_test.go index fdbe835b61d9b..9a2dc7e34fb5b 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -2727,3 +2727,27 @@ func (s *testPlanSuite) TestFastPlanContextTables(c *C) { } } } + +func (s *testPlanSuite) TestSimplyOuterJoinWithOnlyOuterExpr(c *C) { + defer testleak.AfterTest(c)() + sql := "select * from t t1 right join t t0 ON TRUE where CONCAT_WS(t0.e=t0.e, 0, NULL) IS NULL" + ctx := context.TODO() + stmt, err := s.ParseOneStmt(sql, "", "") + c.Assert(err, IsNil) + Preprocess(s.ctx, stmt, s.is) + builder := &PlanBuilder{ + ctx: MockContext(), + is: s.is, + colMapper: make(map[*ast.ColumnNameExpr]int), + } + p, err := builder.Build(ctx, stmt) + c.Assert(err, IsNil) + p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) + c.Assert(err, IsNil) + proj, ok := p.(*LogicalProjection) + c.Assert(ok, IsTrue) + join, ok := proj.Children()[0].(*LogicalJoin) + c.Assert(ok, IsTrue) + // previous wrong JoinType is InnerJoin + c.Assert(join.JoinType, Equals, RightOuterJoin) +} diff --git a/planner/core/rule_predicate_push_down.go b/planner/core/rule_predicate_push_down.go index d6da5db811369..029e161b681a5 100644 --- a/planner/core/rule_predicate_push_down.go +++ b/planner/core/rule_predicate_push_down.go @@ -303,6 +303,10 @@ func simplifyOuterJoin(p *LogicalJoin, predicates []expression.Expression) { // then simplify embedding outer join. canBeSimplified := false for _, expr := range predicates { + // avoid the case where the expr only refers to the schema of outerTable + if expression.ExprFromSchema(expr, outerTable.Schema()) { + continue + } isOk := isNullRejected(p.ctx, innerTable.Schema(), expr) if isOk { canBeSimplified = true