diff --git a/optimizer/plan/plan_test.go b/optimizer/plan/plan_test.go index 4c674c1284..f1b394270d 100644 --- a/optimizer/plan/plan_test.go +++ b/optimizer/plan/plan_test.go @@ -542,13 +542,33 @@ func (s *testPlanSuite) TestJoinPath(c *C) { "InnerJoin{Table(t2)->Index(t1.i1)}->Fields", }, { - "select * from t1 left join (t2 join t3 on t2.i1 = t3.c1) on t1.c1 = t2.i2", + `select * from + t1 left join + (t2 join + t3 + on t2.i1 = t3.c1) + on t1.c1 = t2.i2`, "OuterJoin{Table(t1)->InnerJoin{Index(t2.i2)->Table(t3)}}->Fields", }, { - "select * from (t1, t2) left join t3 on t2.c1 = t3.i1 where t2.i2 between 1 and 4 and t1.i1 = 3", + `select * from + (t1, t2) left join + t3 + on t2.c1 = t3.i1 + where t2.i2 between 1 and 4 and t1.i1 = 3`, "OuterJoin{InnerJoin{Index(t1.i1)->Index(t2.i2)}->Index(t3.i1)}->Fields", }, + { + `select * from + t1 join ( + (t2 join t3 + on t2.i3 = t3.i3 and t2.c2 > t3.c3 + ) left join t4 + on t3.c3 = t4.i4 + ) + on t1.i1 = 1 and t1.c1 = t2.i2`, + "InnerJoin{Index(t1.i1)->OuterJoin{InnerJoin{Index(t2.i2)->Index(t3.i3)}->Index(t4.i4)}}->Fields", + }, } for _, ca := range cases { comment := Commentf("for %s", ca.sql) diff --git a/optimizer/plan/planbuilder_join.go b/optimizer/plan/planbuilder_join.go index b14cd79056..24cd715daa 100644 --- a/optimizer/plan/planbuilder_join.go +++ b/optimizer/plan/planbuilder_join.go @@ -437,10 +437,15 @@ func (p *joinPath) optimizeJoinOrder(availablePaths []*joinPath) { } } p.reattach(pathMap, availablePaths) + for path := range pathMap { + path.optimizeJoinOrder(availablePaths) + } } p.inners = ordered } +// reattach is called by inner joinPath to retry attach conditions to inner paths +// after an inner path has been added to available paths. func (p *joinPath) reattach(pathMap map[*joinPath]bool, availablePaths []*joinPath) { if len(p.conditions) != 0 { conMap := map[ast.ExprNode]bool{}