first elided node -> last elided node
authorRobert Haas <rhaas@postgresql.org>
Fri, 6 Jun 2025 16:31:55 +0000 (12:31 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 6 Jun 2025 16:31:55 +0000 (12:31 -0400)
contrib/pg_plan_advice/pgpa_join.c
contrib/pg_plan_advice/pgpa_walker.c
contrib/pg_plan_advice/pgpa_walker.h

index b3bfef37dca80f16902ffb853e9e164a3bf5ae66..ca73af4181225425c9a8faba4b44e08f3ea5f613 100644 (file)
@@ -319,6 +319,10 @@ pgpa_destroy_join_unroller(pgpa_join_unroller *join_unroller)
  * on top, then we can't "look through" that node -- indeed, what's going to be
  * relevant for our purposes is the ElidedNode on top of that plan node, rather
  * than the plan node itself.
+ *
+ * If there are multiple elided nodes, we want that one that would have been
+ * uppermost in the plan tree prior to setrefs processing; we expect to find
+ * that one last in the list of elided nodes.
  */
 static pgpa_join_strategy
 pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
@@ -331,8 +335,8 @@ pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
        ElidedNode *elidedinner;
        pgpa_join_strategy strategy;
 
-       elidedouter = pgpa_first_elided_node(pstmt, outerplan);
-       elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+       elidedouter = pgpa_last_elided_node(pstmt, outerplan);
+       elidedinner = pgpa_last_elided_node(pstmt, innerplan);
 
        switch (nodeTag(plan))
        {
@@ -340,19 +344,19 @@ pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
                        if (elidedouter == NULL && IsA(outerplan, Sort))
                        {
                                outerplan = outerplan->lefttree;
-                               elidedouter = pgpa_first_elided_node(pstmt, outerplan);
+                               elidedouter = pgpa_last_elided_node(pstmt, outerplan);
                        }
 
                        if (elidedinner == NULL && IsA(innerplan, Sort))
                        {
                                innerplan = innerplan->lefttree;
-                               elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+                               elidedinner = pgpa_last_elided_node(pstmt, innerplan);
                        }
 
                        if (elidedinner == NULL && IsA(innerplan, Material))
                        {
                                innerplan = innerplan->lefttree;
-                               elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+                               elidedinner = pgpa_last_elided_node(pstmt, innerplan);
                                strategy = JSTRAT_MERGE_JOIN_MATERIALIZE;
                        }
                        else
@@ -363,13 +367,13 @@ pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
                        if (elidedinner == NULL && IsA(innerplan, Material))
                        {
                                innerplan = innerplan->lefttree;
-                               elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+                               elidedinner = pgpa_last_elided_node(pstmt, innerplan);
                                strategy = JSTRAT_NESTED_LOOP_MATERIALIZE;
                        }
                        else if (elidedinner == NULL && IsA(innerplan, Memoize))
                        {
                                innerplan = innerplan->lefttree;
-                               elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+                               elidedinner = pgpa_last_elided_node(pstmt, innerplan);
                                strategy = JSTRAT_NESTED_LOOP_MEMOIZE;
                        }
                        else
@@ -380,7 +384,7 @@ pgpa_decompose_join(PlannedStmt *pstmt, Plan *plan,
                        Assert(IsA(innerplan, Hash));
                        Assert(elidedinner == NULL);
                        innerplan = innerplan->lefttree;
-                       elidedinner = pgpa_first_elided_node(pstmt, innerplan);
+                       elidedinner = pgpa_last_elided_node(pstmt, innerplan);
                        strategy = JSTRAT_HASH_JOIN;
                        break;
 
index 6bf8ae7bdf0b9095886e80ad7222ed7076067747..af75dca87eba1de93a7d576211987d3e3979ab38 100644 (file)
@@ -111,13 +111,15 @@ pgpa_plan_walker(pgpa_plan_walker_context *context, Plan *plan,
 }
 
 ElidedNode *
-pgpa_first_elided_node(PlannedStmt *pstmt, Plan *plan)
+pgpa_last_elided_node(PlannedStmt *pstmt, Plan *plan)
 {
+       ElidedNode *elided_node = NULL;
+
        foreach_node(ElidedNode, n, pstmt->elidedNodes)
        {
                if (n->plan_node_id == plan->plan_node_id)
-                       return n;
+                       elided_node = n;
        }
 
-       return NULL;
+       return elided_node;
 }
index b8b0226e3de2e4d54341bd2a9fc911918154b9f0..bb7dce08e8170dcaf84e2d5dbae285198af13347 100644 (file)
@@ -11,4 +11,4 @@ extern void
 pgpa_plan_walker(pgpa_plan_walker_context *context, Plan *plan,
                                 pgpa_join_unroller *join_unroller);
 
-extern ElidedNode *pgpa_first_elided_node(PlannedStmt *pstmt, Plan *plan);
+extern ElidedNode *pgpa_last_elided_node(PlannedStmt *pstmt, Plan *plan);