* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.184 2009/01/02 20:42:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.185 2009/04/05 19:59:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
ListCell *lst;
- for (i = 0; i < indent; i++)
- appendStringInfo(str, " ");
- appendStringInfo(str, " InitPlan\n");
foreach(lst, planstate->initPlan)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
+ for (i = 0; i < indent; i++)
+ appendStringInfo(str, " ");
+ appendStringInfo(str, " %s\n", sp->plan_name);
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " -> ");
{
ListCell *lst;
- for (i = 0; i < indent; i++)
- appendStringInfo(str, " ");
- appendStringInfo(str, " SubPlan\n");
foreach(lst, planstate->subPlan)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
+ for (i = 0; i < indent; i++)
+ appendStringInfo(str, " ");
+ appendStringInfo(str, " %s\n", sp->plan_name);
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " -> ");
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.428 2009/04/04 21:12:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.429 2009/04/05 19:59:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
COPY_NODE_FIELD(testexpr);
COPY_NODE_FIELD(paramIds);
COPY_SCALAR_FIELD(plan_id);
+ COPY_STRING_FIELD(plan_name);
COPY_SCALAR_FIELD(firstColType);
COPY_SCALAR_FIELD(firstColTypmod);
COPY_SCALAR_FIELD(useHashTable);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.351 2009/04/04 21:12:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.352 2009/04/05 19:59:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
COMPARE_NODE_FIELD(testexpr);
COMPARE_NODE_FIELD(paramIds);
COMPARE_SCALAR_FIELD(plan_id);
+ COMPARE_STRING_FIELD(plan_name);
COMPARE_SCALAR_FIELD(firstColType);
COMPARE_SCALAR_FIELD(firstColTypmod);
COMPARE_SCALAR_FIELD(useHashTable);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.357 2009/04/04 21:12:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.358 2009/04/05 19:59:40 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
WRITE_NODE_FIELD(testexpr);
WRITE_NODE_FIELD(paramIds);
WRITE_INT_FIELD(plan_id);
+ WRITE_STRING_FIELD(plan_name);
WRITE_OID_FIELD(firstColType);
WRITE_INT_FIELD(firstColTypmod);
WRITE_BOOL_FIELD(useHashTable);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.147 2009/03/10 22:09:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.148 2009/04/05 19:59:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int paramid;
/*
- * Initialize the SubPlan node. Note plan_id isn't set till further down,
- * likewise the cost fields.
+ * Initialize the SubPlan node. Note plan_id, plan_name, and cost fields
+ * are set further down.
*/
splan = makeNode(SubPlan);
splan->subLinkType = subLinkType;
root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
splan->plan_id);
+ /* Label the subplan for EXPLAIN purposes */
+ if (isInitPlan)
+ {
+ ListCell *lc;
+ int offset;
+
+ splan->plan_name = palloc(32 + 12 * list_length(splan->setParam));
+ sprintf(splan->plan_name, "InitPlan %d (returns ", splan->plan_id);
+ offset = strlen(splan->plan_name);
+ foreach(lc, splan->setParam)
+ {
+ sprintf(splan->plan_name + offset, "$%d%s",
+ lfirst_int(lc),
+ lnext(lc) ? "," : "");
+ offset += strlen(splan->plan_name + offset);
+ }
+ sprintf(splan->plan_name + offset, ")");
+ }
+ else
+ {
+ splan->plan_name = palloc(32);
+ sprintf(splan->plan_name, "SubPlan %d", splan->plan_id);
+ }
+
/* Lastly, fill in the cost estimates for use later */
cost_subplan(root, splan, plan);
* Make a SubPlan node for it. This is just enough unlike
* build_subplan that we can't share code.
*
- * Note plan_id isn't set till further down, likewise the cost fields.
+ * Note plan_id, plan_name, and cost fields are set further down.
*/
splan = makeNode(SubPlan);
splan->subLinkType = CTE_SUBLINK;
root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
+ /* Label the subplan for EXPLAIN purposes */
+ splan->plan_name = palloc(4 + strlen(cte->ctename) + 1);
+ sprintf(splan->plan_name, "CTE %s", cte->ctename);
+
/* Lastly, fill in the cost estimates for use later */
cost_subplan(root, splan, plan);
}
prm = generate_new_param(root, resulttype, resulttypmod);
node->setParam = list_make1_int(prm->paramid);
+ /* Label the subplan for EXPLAIN purposes */
+ node->plan_name = palloc(64);
+ sprintf(node->plan_name, "InitPlan %d (returns $%d)",
+ node->plan_id, prm->paramid);
+
return prm;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.296 2009/02/25 18:00:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.297 2009/04/05 19:59:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
case T_SubPlan:
{
+ SubPlan *subplan = (SubPlan *) node;
+
/*
* We cannot see an already-planned subplan in rule deparsing,
- * only while EXPLAINing a query plan. For now, just punt.
+ * 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 *) node)->useHashTable)
- appendStringInfo(buf, "(hashed subplan)");
+ if (subplan->useHashTable)
+ appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
else
- appendStringInfo(buf, "(subplan)");
+ appendStringInfo(buf, "(%s)", subplan->plan_name);
}
break;
case T_AlternativeSubPlan:
- /* As above, just punt */
- appendStringInfo(buf, "(alternative subplans)");
+ {
+ AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
+ ListCell *lc;
+
+ /* As above, this can only happen during EXPLAIN */
+ appendStringInfo(buf, "(alternatives: ");
+ 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);
+ if (lnext(lc))
+ appendStringInfo(buf, " or ");
+ }
+ appendStringInfo(buf, ")");
+ }
break;
case T_FieldSelect:
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.147 2009/03/10 22:09:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.148 2009/04/05 19:59:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
List *paramIds; /* IDs of Params embedded in the above */
/* Identification of the Plan tree to use: */
int plan_id; /* Index (from 1) in PlannedStmt.subplans */
+ /* Identification of the SubPlan for EXPLAIN and debugging purposes: */
+ char *plan_name; /* A name assigned during planning */
/* Extra data useful for determining subplan's output type: */
Oid firstColType; /* Type of first column of subplan result */
int32 firstColTypmod; /* Typmod of first column of subplan result */