Look through Gather and Gather Merge nodes.
authorRobert Haas <rhaas@postgresql.org>
Fri, 6 Jun 2025 19:22:13 +0000 (15:22 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 6 Jun 2025 19:22:13 +0000 (15:22 -0400)
contrib/pg_plan_advice/pgpa_join.c

index d1428cc349cbc8bc0faf56061bfb1e4b665d6054..f0054bd0ef24afb31f60cfdb003a0412bfe7ff85 100644 (file)
@@ -154,12 +154,15 @@ pgpa_unroll_join(PlannedStmt *pstmt, Plan *plan,
        Assert(join_unroller != NULL);
 
        /*
-        * We need to pass the join_unroller object down through plan nodes that
-        * pgpa_decompose_join() regards as part of the join strategy.
-        *
-        * XXX. Gather and Gather Merge are going to be a problem here.
+        * We need to pass the join_unroller object down through certain types
+        * of plan nodes -- anything that's considered part of the join strategy,
+        * such as Hash Join's Hash node or a Materialize node inserted on the
+        * inner side of a nested loop as part of the join strategy -- and also
+        * Gather and Gather Merge nodes, which can occur in a join tree but
+        * are not themselves scans or joins.
         */
-       if (IsA(plan, Material) || IsA(plan, Memoize) || IsA(plan, Hash) || IsA(plan, Sort))
+       if (IsA(plan, Material) || IsA(plan, Memoize) || IsA(plan, Hash) ||
+               IsA(plan, Sort) || IsA(plan, Gather) || IsA(plan, GatherMerge))
        {
                *outer_join_unroller = join_unroller;
                return;
@@ -392,6 +395,18 @@ pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(plan));
        }
 
+       if (IsA(outerplan, Gather) || IsA(outerplan, GatherMerge))
+       {
+               outerplan = outerplan->lefttree;
+               elidedouter = pgpa_last_elided_node(pstmt, outerplan);
+       }
+
+       if (IsA(innerplan, Gather) || IsA(innerplan, GatherMerge))
+       {
+               innerplan = innerplan->lefttree;
+               elidedinner = pgpa_last_elided_node(pstmt, innerplan);
+       }
+
        *realouter = outerplan;
        *realinner = innerplan;
        *elidedrealouter = elidedouter;