plan: not build dual for AntiSemiJoin when condition is constant false (#8648)

This commit is contained in:
Kenan Yao
2018-12-11 17:18:53 +08:00
committed by Yiding Cui
parent e2b3912296
commit 080768ddda
2 changed files with 35 additions and 4 deletions

View File

@ -421,6 +421,34 @@ func (s *testPlanSuite) TestSimplifyOuterJoin(c *C) {
}
}
func (s *testPlanSuite) TestAntiSemiJoinConstFalse(c *C) {
defer testleak.AfterTest(c)()
tests := []struct {
sql string
best string
joinType string
}{
{
sql: "select a from t t1 where not exists (select a from t t2 where t1.a = t2.a and t2.b = 1 and t2.b = 2)",
best: "Join{DataScan(t1)->DataScan(t2)}->Projection",
joinType: "anti semi join",
},
}
for _, ca := range tests {
comment := Commentf("for %s", ca.sql)
stmt, err := s.ParseOneStmt(ca.sql, "", "")
c.Assert(err, IsNil, comment)
p, err := BuildLogicalPlan(s.ctx, stmt, s.is)
c.Assert(err, IsNil, comment)
p, err = logicalOptimize(flagDecorrelate|flagPredicatePushDown|flagPrunColumns, p.(LogicalPlan))
c.Assert(err, IsNil, comment)
c.Assert(ToString(p), Equals, ca.best, comment)
join, _ := p.(LogicalPlan).Children()[0].(*LogicalJoin)
joinType := fmt.Sprintf("%s", join.JoinType.String())
c.Assert(joinType, Equals, ca.joinType, comment)
}
}
func newPartitionInfoSchema(definitions []model.PartitionDefinition) infoschema.InfoSchema {
tableInfo := *MockTable()
cols := make([]*model.ColumnInfo, 0, len(tableInfo.Columns))

View File

@ -159,10 +159,13 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret
tempCond = append(tempCond, predicates...)
tempCond = expression.ExtractFiltersFromDNFs(p.ctx, tempCond)
tempCond = expression.PropagateConstant(p.ctx, tempCond)
// Return table dual when filter is constant false or null.
dual := conds2TableDual(p, tempCond)
if dual != nil {
return ret, dual
// Return table dual when filter is constant false or null. Not applicable to AntiSemiJoin.
// TODO: For AntiSemiJoin, we can use outer plan to substitute LogicalJoin actually.
if p.JoinType != AntiSemiJoin {
dual := conds2TableDual(p, tempCond)
if dual != nil {
return ret, dual
}
}
equalCond, leftPushCond, rightPushCond, otherCond = extractOnCondition(tempCond, leftPlan, rightPlan, true, true)
p.LeftConditions = nil