]> granicus.if.org Git - postgresql/commitdiff
Improve EXPLAIN's ability to cope with LATERAL references in plans.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Aug 2012 16:56:50 +0000 (12:56 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Aug 2012 16:56:50 +0000 (12:56 -0400)
push_child_plan/pop_child_plan didn't bother to adjust the "ancestors"
list of parent plan nodes when descending to a child plan node.  I think
this was okay when it was written, but it's not okay in the presence of
LATERAL references, since a subplan node could easily be returning a
LATERAL value back up to the same nestloop node that provides the value.
Per changed regression test results, the omission led to failure to
interpret Param nodes that have perfectly good interpretations.

src/backend/utils/adt/ruleutils.c
src/test/regress/expected/join.out

index f6f7f85f4435cb8f15fac4f452f62f607d0226d0..ae6278432fd41ea5a48f4c6fd8c45fa1a1deb528 100644 (file)
@@ -2312,14 +2312,8 @@ push_child_plan(deparse_namespace *dpns, PlanState *ps,
        /* Save state for restoration later */
        *save_dpns = *dpns;
 
-       /*
-        * Currently we don't bother to adjust the ancestors list, because an
-        * OUTER_VAR or INNER_VAR reference really shouldn't contain any Params
-        * that would be set by the parent node itself.  If we did want to adjust
-        * the list, lcons'ing dpns->planstate onto dpns->ancestors would be the
-        * appropriate thing --- and pop_child_plan would need to undo the change
-        * to the list.
-        */
+       /* Link current plan node into ancestors list */
+       dpns->ancestors = lcons(dpns->planstate, dpns->ancestors);
 
        /* Set attention on selected child */
        set_deparse_planstate(dpns, ps);
@@ -2331,8 +2325,16 @@ push_child_plan(deparse_namespace *dpns, PlanState *ps,
 static void
 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
 {
+       List       *ancestors;
+
+       /* Get rid of ancestors list cell added by push_child_plan */
+       ancestors = list_delete_first(dpns->ancestors);
+
        /* Restore fields changed by push_child_plan */
        *dpns = *save_dpns;
+
+       /* Make sure dpns->ancestors is right (may be unnecessary) */
+       dpns->ancestors = ancestors;
 }
 
 /*
index 2e54ede838709c1dc5b917fef2d13891660b7540..c2e83d7f8bbb1663714b459539349d9f22855662 100644 (file)
@@ -3172,7 +3172,7 @@ explain (costs off)
  Nested Loop
    ->  Seq Scan on int8_tbl a
    ->  Hash Left Join
-         Hash Cond: (x.q2 = ($0))
+         Hash Cond: (x.q2 = (a.q1))
          ->  Seq Scan on int8_tbl x
          ->  Hash
                ->  Seq Scan on int4_tbl y