elog(ERROR, "unrecognized node type: %d", (int) nodeTag(plan));
}
+ /*
+ * The planner may have decided to implement a semijoin by first making
+ * the nullable side of the plan unique, and then performing a normal join
+ * against the result. Therefore, we might need to descend through a
+ * unique node on either side of the plan.
+ *
+ * XXX. We should really note the unique-ified rels here and emit advice.
+ */
if (elidedouter == NULL)
elidedouter = pgpa_descend_any_unique(pstmt, &outerplan);
-
if (elidedinner == NULL)
elidedinner = pgpa_descend_any_unique(pstmt, &innerplan);
+ /*
+ * The planner may have decided to parallelize part of the join tree, so
+ * we could find a Gather or Gather Merge node here. Note that, if
+ * present, this will appear below both (1) nodes we considered as part of
+ * the join strategy and (2) nodes inserted for uniqueness, because we
+ * currently only consider gathering a partial path on top of the final
+ * path for some RelOptInfo.
+ *
+ * XXX. We should really note the gathered rels here and emit advice.
+ */
if (elidedouter == NULL)
elidedouter = pgpa_descend_any_gather(pstmt, &outerplan);
-
if (elidedinner == NULL)
elidedinner = pgpa_descend_any_gather(pstmt, &innerplan);
+ /*
+ * It's possible that Result node has been inserted either to project a
+ * target list or to implement a one-time filter. If so, we can descend
+ * throught it. Note that a result node without a child would be a
+ * degenerate scan or join, and not something we could descend through.
+ *
+ * XXX. I suspect it's possible for this to happen above the Gather or
+ * Gather Merge node, too, but apparently we have no test case for that
+ * scenario.
+ */
if (elidedouter == NULL && is_result_node_with_child(outerplan))
elidedouter = pgpa_descend_node(pstmt, &outerplan);
-
if (elidedinner == NULL && is_result_node_with_child(innerplan))
elidedinner = pgpa_descend_node(pstmt, &innerplan);