From: Tom Lane Date: Thu, 30 Aug 2012 16:56:50 +0000 (-0400) Subject: Improve EXPLAIN's ability to cope with LATERAL references in plans. X-Git-Tag: REL9_3_BETA1~992 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d1a4db8d25ec53fd17e99168bc5efa0b16ef6fed;p=postgresql Improve EXPLAIN's ability to cope with LATERAL references in plans. 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. --- diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index f6f7f85f44..ae6278432f 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -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; } /* diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 2e54ede838..c2e83d7f8b 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -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