Tom Lane wrote:
In principle it could look something like
(SubPlan N ($0 := b.oid))
but with a few parameters and a bunch of other stuff on the same line
that would get out of hand.
The patch I submitted to implement this, hits bogus varno:65001 in get_variable
when I explain the following query from the aggregates.sql regression
test.
select ten, sum(distinct four) from onek a
group by ten
having exists (select 1 from onek b where sum(distinct a.four) =
b.four);
The explain without the subplan argument-patch shows
regression=# explain verbose select ten, sum(distinct four) from
onek a
group by ten
having exists (select 1 from onek b where sum(distinct a.four) =
b.four);
QUERY
PLAN
------------------------------------------------------------------------------
GroupAggregate (cost=197.83..216.52 rows=10 width=8)
Output: a.ten, sum(DISTINCT a.four)
Filter: (alternatives: SubPlan 1 or hashed SubPlan 2)
-> Sort (cost=197.83..200.33 rows=1000 width=8)
Output: a.ten, a.four
Sort Key: a.ten
-> Seq Scan on public.onek a (cost=0.00..148.00 rows=1000
width=8)
Output: a.ten, a.four
SubPlan 1
-> Seq Scan on public.onek b (cost=0.00..150.50 rows=250
width=0)
Filter: ($0 = b.four)
SubPlan 2
-> Seq Scan on public.onek b (cost=0.00..148.00 rows=1000
width=4)
Output: b.four
(14 rows)
The subplan argument list contains a aggref node, with a var argument
that has the 65001 varno. Apparently the OUTER varno is set by
search_indexed_tlist_for_var and it seems like correct behaviour, see
stack trace below.
I'm unsure what is a good approach to solve this problem: let
get_variable not give an error in this case?
regards,
Yeb Havinga
#0 search_indexed_tlist_for_var (var=0xe32dc0, itlist=0xe67290,
newvarno=65001, rtoffset=0)
at setrefs.c:1568
#1 0x0000000000697581 in fix_upper_expr_mutator (node=0xe32dc0,
context=0x7fffabcde850)
at setrefs.c:1853
#2 0x0000000000697529 in fix_upper_expr (glob=0xe77178, node=0xe32dc0,
subplan_itlist=0xe67290,
rtoffset=0) at setrefs.c:1839
#3 0x0000000000696b6e in set_upper_references (glob=0xe77178,
plan=0xe66f80, rtoffset=0)
postgres=#
explain select oid::int + 1,(select oid from pg_class a where a.oid =
b.relfilenode and a.relnamespace = b.relnamespace) from pg_class b;
QUERY
PLAN
---------------------------------------------------------------------------------------------
Seq Scan on pg_class b (cost=0.00..2459.64 rows=296 width=12)
SubPlan 1 ($0 := b.relfilenode, $1 := b.relnamespace)
-> Index Scan using pg_class_oid_index on pg_class a
(cost=0.00..8.27 rows=1 width=4)
Index Cond: (oid = $0)
Filter: (relnamespace = $1)
(5 rows)
index 56d9c5b..454d59b 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -1686,20 +1686,47 @@ static void
ExplainSubPlans(List *plans, const char *relationship, ExplainState
*es)
{
ListCell *lst;
foreach(lst, plans)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
- SubPlan *sp = (SubPlan *) sps->xprstate.expr;
+ SubPlan *sp = (SubPlan *) sps->xprstate.expr;
+ StringInfo signature = makeStringInfo();
+ int i = 0;
+ List *context;
+ bool useprefix;
+ ListCell *c;
+
+ context = deparse_context_for_plan((Node
*)exec_subplan_get_plan(es->pstmt, sp),
+
NULL,
+
es->rtable,
+
es->pstmt->subplans);
+ useprefix = list_length(es->rtable) > 1;
+
+ appendStringInfoString(signature, sp->plan_name);
+
+ foreach(c, sp->args)
+ {
+ Node *n = lfirst(c);
+ appendStringInfo(signature, "%s$%d := %s",
+ (i == 0) ? "
(" : ", ",
+ i,
+
deparse_expression(n, context, useprefix, true));
+ i++;
+ }
+
+ if (i > 0)
+ appendStringInfoString(signature, ")");
ExplainNode(exec_subplan_get_plan(es->pstmt, sp),
sps->planstate,
NULL,
- relationship, sp->plan_name,
+ relationship,
+ signature->data,
es);
}
}
/*
* Explain a property, such as sort keys or targets, that takes the
form of
* a list of unlabeled items. "data" is a list of C strings.