switch (nodeTag(plan))
{
case T_MergeJoin:
- if (elidedouter == NULL && is_sorting_plan(outerplan))
- elidedouter = pgpa_descend_node(pstmt, &outerplan);
-
- if (elidedouter == NULL && is_result_node_with_child(outerplan))
- elidedouter = pgpa_descend_node(pstmt, &outerplan);
-
+ /*
+ * The planner may have chosen to place a Material node on the
+ * inner side of the MergeJoin; if this is present, we record it
+ * as part of the join strategy.
+ */
if (elidedinner == NULL && IsA(innerplan, Material))
{
elidedinner = pgpa_descend_node(pstmt, &innerplan);
else
strategy = JSTRAT_MERGE_JOIN_PLAIN;
+ /*
+ * For a MergeJoin, either the outer or the inner subplan, or
+ * both, may have needed to be sorted; we must disregard any Sort
+ * or IncrementalSort node to find the real inner or outer subplan.
+ */
+ if (elidedouter == NULL && is_sorting_plan(outerplan))
+ elidedouter = pgpa_descend_node(pstmt, &outerplan);
if (elidedinner == NULL && is_sorting_plan(innerplan))
elidedinner = pgpa_descend_node(pstmt, &innerplan);
-
- if (elidedinner == NULL && is_result_node_with_child(innerplan))
- elidedinner = pgpa_descend_node(pstmt, &innerplan);
break;
case T_NestLoop:
+ /*
+ * The planner may have chosen to place a Material or Memoize
+ * node on the inner side of the NestLoop; if this is present,
+ * we record it as part of the join strategy.
+ */
if (elidedinner == NULL && IsA(innerplan, Material))
{
elidedinner = pgpa_descend_node(pstmt, &innerplan);
break;
case T_HashJoin:
+ /*
+ * The inner subplan of a HashJoin is always a Hash node; the real
+ * inner subplan is the Hash node's child.
+ */
Assert(IsA(innerplan, Hash));
Assert(elidedinner == NULL);
elidedinner = pgpa_descend_node(pstmt, &innerplan);