{
SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
+ /* ignore full joins --- their ordering is predetermined */
+ if (sjinfo->jointype == JOIN_FULL)
+ continue;
+
if (bms_overlap(sjinfo->min_lefthand, join_plus_rhs) &&
!bms_is_subset(sjinfo->min_righthand, join_plus_rhs))
{
sjinfo->min_righthand);
more = true;
}
- /* full joins constrain both sides symmetrically */
- if (sjinfo->jointype == JOIN_FULL &&
- bms_overlap(sjinfo->min_righthand, join_plus_rhs) &&
- !bms_is_subset(sjinfo->min_lefthand, join_plus_rhs))
- {
- join_plus_rhs = bms_add_members(join_plus_rhs,
- sjinfo->min_lefthand);
- more = true;
- }
}
} while (more);
if (bms_overlap(join_plus_rhs, join_lateral_rels))
rel->partial_pathlist = NIL;
/* Set up the dummy path */
- add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL, NULL,
+ add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL,
+ rel->lateral_relids,
0, false, NIL, -1));
/* Set or update cheapest_total_path and related fields */
RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo,
List *parent_restrictlist)
{
+ bool rel1_is_simple = IS_SIMPLE_REL(rel1);
+ bool rel2_is_simple = IS_SIMPLE_REL(rel2);
int nparts;
int cnt_parts;
{
RelOptInfo *child_rel1 = rel1->part_rels[cnt_parts];
RelOptInfo *child_rel2 = rel2->part_rels[cnt_parts];
+ bool rel1_empty = (child_rel1 == NULL ||
+ IS_DUMMY_REL(child_rel1));
+ bool rel2_empty = (child_rel2 == NULL ||
+ IS_DUMMY_REL(child_rel2));
SpecialJoinInfo *child_sjinfo;
List *child_restrictlist;
RelOptInfo *child_joinrel;
AppendRelInfo **appinfos;
int nappinfos;
+ /*
+ * Check for cases where we can prove that this segment of the join
+ * returns no rows, due to one or both inputs being empty (including
+ * inputs that have been pruned away entirely). If so just ignore it.
+ * These rules are equivalent to populate_joinrel_with_paths's rules
+ * for dummy input relations.
+ */
+ switch (parent_sjinfo->jointype)
+ {
+ case JOIN_INNER:
+ case JOIN_SEMI:
+ if (rel1_empty || rel2_empty)
+ continue; /* ignore this join segment */
+ break;
+ case JOIN_LEFT:
+ case JOIN_ANTI:
+ if (rel1_empty)
+ continue; /* ignore this join segment */
+ break;
+ case JOIN_FULL:
+ if (rel1_empty && rel2_empty)
+ continue; /* ignore this join segment */
+ break;
+ default:
+ /* other values not expected here */
+ elog(ERROR, "unrecognized join type: %d",
+ (int) parent_sjinfo->jointype);
+ break;
+ }
+
+ /*
+ * If a child has been pruned entirely then we can't generate paths
+ * for it, so we have to reject partitionwise joining unless we were
+ * able to eliminate this partition above.
+ */
+ if (child_rel1 == NULL || child_rel2 == NULL)
+ {
+ /*
+ * Mark the joinrel as unpartitioned so that later functions treat
+ * it correctly.
+ */
+ joinrel->nparts = 0;
+ return;
+ }
+
+ /*
+ * If a leaf relation has consider_partitionwise_join=false, it means
+ * that it's a dummy relation for which we skipped setting up tlist
+ * expressions and adding EC members in set_append_rel_size(), so
+ * again we have to fail here.
+ */
+ if (rel1_is_simple && !child_rel1->consider_partitionwise_join)
+ {
+ Assert(child_rel1->reloptkind == RELOPT_OTHER_MEMBER_REL);
+ Assert(IS_DUMMY_REL(child_rel1));
+ joinrel->nparts = 0;
+ return;
+ }
+ if (rel2_is_simple && !child_rel2->consider_partitionwise_join)
+ {
+ Assert(child_rel2->reloptkind == RELOPT_OTHER_MEMBER_REL);
+ Assert(IS_DUMMY_REL(child_rel2));
+ joinrel->nparts = 0;
+ return;
+ }
+
/* We should never try to join two overlapping sets of rels. */
Assert(!bms_overlap(child_rel1->relids, child_rel2->relids));
child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids);
duplication hint:
error hint:
- QUERY PLAN
--------------------------------------------------------
+ QUERY PLAN
+-------------------------------------------------
Hash Join
- Hash Cond: (p1.id = p2.id)
- -> Append
- -> Seq Scan on p1
- -> Seq Scan on p1_c1
- -> Seq Scan on p1_c2
- -> Seq Scan on p1_c3
- -> Seq Scan on p1_c4
- -> Seq Scan on p1_c1_c1
- -> Seq Scan on p1_c1_c2
- -> Seq Scan on p1_c3_c1
- -> Seq Scan on p1_c3_c2
+ Hash Cond: (p2.id = p1.id)
+ -> Gather
+ Workers Planned: 8
+ -> Parallel Append
+ -> Seq Scan on p2
+ -> Seq Scan on p2_c1
+ -> Seq Scan on p2_c3
+ -> Parallel Seq Scan on p2_c2
+ -> Parallel Seq Scan on p2_c4
+ -> Parallel Seq Scan on p2_c1_c1
+ -> Parallel Seq Scan on p2_c1_c2
+ -> Parallel Seq Scan on p2_c3_c1
+ -> Parallel Seq Scan on p2_c3_c2
-> Hash
- -> Gather
- Workers Planned: 8
- -> Parallel Append
- -> Seq Scan on p2
- -> Seq Scan on p2_c1
- -> Seq Scan on p2_c3
- -> Parallel Seq Scan on p2_c2
- -> Parallel Seq Scan on p2_c4
- -> Parallel Seq Scan on p2_c1_c1
- -> Parallel Seq Scan on p2_c1_c2
- -> Parallel Seq Scan on p2_c3_c1
- -> Parallel Seq Scan on p2_c3_c2
+ -> Append
+ -> Seq Scan on p1
+ -> Seq Scan on p1_c1
+ -> Seq Scan on p1_c2
+ -> Seq Scan on p1_c3
+ -> Seq Scan on p1_c4
+ -> Seq Scan on p1_c1_c1
+ -> Seq Scan on p1_c1_c2
+ -> Seq Scan on p1_c3_c1
+ -> Seq Scan on p1_c3_c2
(25 rows)
-- Number of workers results to the largest number
duplication hint:
error hint:
- QUERY PLAN
--------------------------------------------------------
+ QUERY PLAN
+-------------------------------------------------
Hash Join
- Hash Cond: (p2.id = p1.id)
- -> Append
- -> Seq Scan on p2
- -> Seq Scan on p2_c1
- -> Seq Scan on p2_c2
- -> Seq Scan on p2_c3
- -> Seq Scan on p2_c4
- -> Seq Scan on p2_c1_c1
- -> Seq Scan on p2_c1_c2
- -> Seq Scan on p2_c3_c1
- -> Seq Scan on p2_c3_c2
+ Hash Cond: (p1.id = p2.id)
+ -> Gather
+ Workers Planned: 8
+ -> Parallel Append
+ -> Seq Scan on p1
+ -> Seq Scan on p1_c1
+ -> Seq Scan on p1_c3
+ -> Parallel Seq Scan on p1_c2
+ -> Parallel Seq Scan on p1_c4
+ -> Parallel Seq Scan on p1_c1_c1
+ -> Parallel Seq Scan on p1_c1_c2
+ -> Parallel Seq Scan on p1_c3_c1
+ -> Parallel Seq Scan on p1_c3_c2
-> Hash
- -> Gather
- Workers Planned: 8
- -> Parallel Append
- -> Seq Scan on p1
- -> Seq Scan on p1_c1
- -> Seq Scan on p1_c3
- -> Parallel Seq Scan on p1_c2
- -> Parallel Seq Scan on p1_c4
- -> Parallel Seq Scan on p1_c1_c1
- -> Parallel Seq Scan on p1_c1_c2
- -> Parallel Seq Scan on p1_c3_c1
- -> Parallel Seq Scan on p1_c3_c2
+ -> Append
+ -> Seq Scan on p2
+ -> Seq Scan on p2_c1
+ -> Seq Scan on p2_c2
+ -> Seq Scan on p2_c3
+ -> Seq Scan on p2_c4
+ -> Seq Scan on p2_c1_c1
+ -> Seq Scan on p2_c1_c2
+ -> Seq Scan on p2_c3_c1
+ -> Seq Scan on p2_c3_c2
(25 rows)
-- Parallel index scan
duplication hint:
error hint:
- QUERY PLAN
------------------------------------------------------------------------------
+ QUERY PLAN
+-----------------------------------------------------------------------
Hash Join
- Hash Cond: (p2.id = p1.id)
- -> Append
- -> Seq Scan on p2
- -> Seq Scan on p2_c1
- -> Seq Scan on p2_c2
- -> Seq Scan on p2_c3
- -> Seq Scan on p2_c4
- -> Seq Scan on p2_c1_c1
- -> Seq Scan on p2_c1_c2
- -> Seq Scan on p2_c3_c1
- -> Seq Scan on p2_c3_c2
+ Hash Cond: (p1.id = p2.id)
+ -> Gather
+ Workers Planned: 8
+ -> Parallel Append
+ -> Parallel Index Scan using p1_pkey on p1
+ -> Parallel Index Scan using p1_c1_pkey on p1_c1
+ -> Parallel Index Scan using p1_c2_pkey on p1_c2
+ -> Parallel Index Scan using p1_c3_pkey on p1_c3
+ -> Parallel Index Scan using p1_c4_pkey on p1_c4
+ -> Parallel Index Scan using p1_c1_c1_pkey on p1_c1_c1
+ -> Parallel Index Scan using p1_c1_c2_pkey on p1_c1_c2
+ -> Parallel Index Scan using p1_c3_c1_pkey on p1_c3_c1
+ -> Parallel Index Scan using p1_c3_c2_pkey on p1_c3_c2
-> Hash
- -> Gather
- Workers Planned: 8
- -> Parallel Append
- -> Parallel Index Scan using p1_pkey on p1
- -> Parallel Index Scan using p1_c1_pkey on p1_c1
- -> Parallel Index Scan using p1_c2_pkey on p1_c2
- -> Parallel Index Scan using p1_c3_pkey on p1_c3
- -> Parallel Index Scan using p1_c4_pkey on p1_c4
- -> Parallel Index Scan using p1_c1_c1_pkey on p1_c1_c1
- -> Parallel Index Scan using p1_c1_c2_pkey on p1_c1_c2
- -> Parallel Index Scan using p1_c3_c1_pkey on p1_c3_c1
- -> Parallel Index Scan using p1_c3_c2_pkey on p1_c3_c2
+ -> Append
+ -> Seq Scan on p2
+ -> Seq Scan on p2_c1
+ -> Seq Scan on p2_c2
+ -> Seq Scan on p2_c3
+ -> Seq Scan on p2_c4
+ -> Seq Scan on p2_c1_c1
+ -> Seq Scan on p2_c1_c2
+ -> Seq Scan on p2_c3_c1
+ -> Seq Scan on p2_c3_c2
(25 rows)
-- This hint doesn't turn on parallel, so the Parallel hint is ignored