diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 2feab2184f..a3f94be1d6 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -1640,13 +1640,15 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_rel1->relids, child_rel2->relids); - /* Build correct join relids for child join */ - child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids); - child_joinrelids = add_outer_joins_to_relids(root, child_joinrelids, - child_sjinfo, NULL); - /* Find the AppendRelInfo structures */ - appinfos = find_appinfos_by_relids(root, child_joinrelids, &nappinfos); + appinfos = find_appinfos_by_relids(root, + bms_union(child_rel1->relids, + child_rel2->relids), + &nappinfos); + + /* Build correct join relids for child join */ + child_joinrelids = adjust_child_relids(joinrel->relids, + nappinfos, appinfos); /* * Construct restrictions applicable to the child join from those diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 15e3910b79..76dad17e33 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -871,10 +871,19 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, /* The parent joinrel should have consider_partitionwise_join set. */ Assert(parent_joinrel->consider_partitionwise_join); + /* + * Find the AppendRelInfo structures for the child baserels. We'll need + * these for computing the child join's relid set, and later for mapping + * Vars to the child rel. + */ + appinfos = find_appinfos_by_relids(root, + bms_union(outer_rel->relids, + inner_rel->relids), + &nappinfos); + joinrel->reloptkind = RELOPT_OTHER_JOINREL; - joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids); - joinrel->relids = add_outer_joins_to_relids(root, joinrel->relids, sjinfo, - NULL); + joinrel->relids = adjust_child_relids(parent_joinrel->relids, + nappinfos, appinfos); joinrel->rows = 0; /* cheap startup cost is interesting iff not all tuples to be retrieved */ joinrel->consider_startup = (root->tuple_fraction > 0); @@ -935,9 +944,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, /* Compute information relevant to foreign relations. */ set_foreign_rel_properties(joinrel, outer_rel, inner_rel); - /* Compute information needed for mapping Vars to the child rel */ - appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos); - /* Set up reltarget struct */ build_child_join_reltarget(root, parent_joinrel, joinrel, nappinfos, appinfos); diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 762cc8e53b..6560fe2416 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -62,6 +62,52 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 450 | 0450 | 450 | 0450 (4 rows) +-- left outer join, 3-way +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM prt1 t1 + LEFT JOIN prt1 t2 ON t1.a = t2.a + LEFT JOIN prt1 t3 ON t2.a = t3.a; + QUERY PLAN +-------------------------------------------------------- + Aggregate + -> Append + -> Hash Left Join + Hash Cond: (t2_1.a = t3_1.a) + -> Hash Left Join + Hash Cond: (t1_1.a = t2_1.a) + -> Seq Scan on prt1_p1 t1_1 + -> Hash + -> Seq Scan on prt1_p1 t2_1 + -> Hash + -> Seq Scan on prt1_p1 t3_1 + -> Hash Left Join + Hash Cond: (t2_2.a = t3_2.a) + -> Hash Left Join + Hash Cond: (t1_2.a = t2_2.a) + -> Seq Scan on prt1_p2 t1_2 + -> Hash + -> Seq Scan on prt1_p2 t2_2 + -> Hash + -> Seq Scan on prt1_p2 t3_2 + -> Hash Left Join + Hash Cond: (t2_3.a = t3_3.a) + -> Hash Left Join + Hash Cond: (t1_3.a = t2_3.a) + -> Seq Scan on prt1_p3 t1_3 + -> Hash + -> Seq Scan on prt1_p3 t2_3 + -> Hash + -> Seq Scan on prt1_p3 t3_3 +(29 rows) + +SELECT COUNT(*) FROM prt1 t1 + LEFT JOIN prt1 t2 ON t1.a = t2.a + LEFT JOIN prt1 t3 ON t2.a = t3.a; + count +------- + 300 +(1 row) + -- left outer join, with whole-row reference; partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b; diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql index 9e16f1ca55..48daf3aee3 100644 --- a/src/test/regress/sql/partition_join.sql +++ b/src/test/regress/sql/partition_join.sql @@ -34,6 +34,15 @@ EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; +-- left outer join, 3-way +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM prt1 t1 + LEFT JOIN prt1 t2 ON t1.a = t2.a + LEFT JOIN prt1 t3 ON t2.a = t3.a; +SELECT COUNT(*) FROM prt1 t1 + LEFT JOIN prt1 t2 ON t1.a = t2.a + LEFT JOIN prt1 t3 ON t2.a = t3.a; + -- left outer join, with whole-row reference; partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b;