Tom Lane wrote:
Anyway, I hadn't looked at your patch before, but now that I have, it's
not even approximately what I was suggesting. What I thought you should
do was change ruleutils.c to print the parameter expressions at the call
site, ie in the T_SubPlan and T_AlternativeSubPlan cases in get_rule_expr.
See patch below against HEAD.
Example of query against catalog:
postgres=# explain verbose 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_catalog.pg_class b (cost=0.00..2459.64 rows=296 width=12)
Output: ((b.oid)::integer + 1), SubPlan 1 ($0 := b.relfilenode, $1 :=
b.relnamespace)
SubPlan 1
-> Index Scan using pg_class_oid_index on pg_catalog.pg_class a
(cost=0.00..8.27 rows=1 width=4)
Output: a.oid
Index Cond: (a.oid = $0)
Filter: (a.relnamespace = $1)
(7 rows)
Explain of alternative subplan (query comes from aggregates.sql in
regression).
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 ($0 := sum(DISTINCT a.four)) 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)
Would the explain above be better if the filter with subplans arguments
showed the EXISTS keyword? Much code from get_sublink_expr could be
reused to show additional info depending on the sublink type and testexpr.
Other info: there are now only appends to the context->buf. The problems
with OUTER var I mentioned earlier are gone now arguments are deparsed
using get_rule_expr instead of deparse_expression.
regards,
Yeb Havinga
diff --git a/src/backend/utils/adt/ruleutils.c
b/src/backend/utils/adt/ruleutils.c
index d16f1c4..68302e4 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -206,6 +206,7 @@ static void get_const_expr(Const *constval, deparse_context
*context,
int showtype);
static void simple_quote_literal(StringInfo buf, const char *val);
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
+static void get_subplan_reference(SubPlan *subplan, deparse_context *context);
static void get_from_clause(Query *query, const char *prefix,
deparse_context *context);
static void get_from_clause_item(Node *jtnode, Query *query,
@@ -4647,20 +4648,13 @@ get_rule_expr(Node *node, deparse_context *context,
break;
case T_SubPlan:
- {
- SubPlan *subplan = (SubPlan *) node;
-
- /*
- * We cannot see an already-planned subplan in
rule deparsing,
- * only while EXPLAINing a query plan. We
don't try to
- * reconstruct the original SQL, just reference
the subplan
- * that appears elsewhere in EXPLAIN's result.
- */
- if (subplan->useHashTable)
- appendStringInfo(buf, "(hashed %s)",
subplan->plan_name);
- else
- appendStringInfo(buf, "(%s)",
subplan->plan_name);
- }
+ /*
+ * We cannot see an already-planned subplan in rule
deparsing, only
+ * while EXPLAINing a query plan. We don't try to
reconstruct the
+ * original SQL, just reference the subplan that
appears elsewhere
+ * in EXPLAIN's result.
+ */
+ get_subplan_reference((SubPlan *) node, context);
break;
case T_AlternativeSubPlan:
@@ -4673,12 +4667,9 @@ get_rule_expr(Node *node, deparse_context *context,
foreach(lc, asplan->subplans)
{
SubPlan *splan = (SubPlan *)
lfirst(lc);
-
Assert(IsA(splan, SubPlan));
- if (splan->useHashTable)
- appendStringInfo(buf, "hashed
%s", splan->plan_name);
- else
- appendStringInfo(buf, "%s",
splan->plan_name);
+ get_subplan_reference(splan, context);
+
if (lnext(lc))
appendStringInfo(buf, " or ");
}
@@ -5934,6 +5925,43 @@ get_sublink_expr(SubLink *sublink, deparse_context
*context)
/* ----------
+ * get_subplan_reference - Parse back a subplan reference
+ *
+ * ----------
+ */
+static void
+get_subplan_reference(SubPlan *subplan, deparse_context *context)
+{
+ StringInfo buf = context->buf;
+
+ if (subplan->useHashTable)
+ appendStringInfo(buf, "hashed ");
+
+ appendStringInfo(buf, "%s", subplan->plan_name);
+
+ /* Add the subplan arguments */
+ if (list_length(subplan->args) > 0)
+ {
+ ListCell *l;
+ int i = 0;
+
+ foreach(l, subplan->args)
+ {
+ Node *n = lfirst(l);
+ appendStringInfo(buf, "%s$%d := ",
+ (i == 0) ? " (" : ", ",
+ i);
+
+ get_rule_expr(n, context, true);
+ i++;
+ }
+
+ appendStringInfoChar(buf, ')');
+ }
+}
+
+
+/* ----------
* get_from_clause - Parse back a FROM clause
*
* "prefix" is the keyword that denotes the start of the list of FROM
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers