diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 8ad877e1652af27dff6b932d1d0d8c80f4761c1f..d8f27a1175b412d0dc3f893c175f4f7586da4d96 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -7,7 +7,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -951,14 +951,14 @@ explain_outNode(StringInfo str, { 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, " -> "); @@ -1099,14 +1099,14 @@ explain_outNode(StringInfo 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, " -> "); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index bbeac65597083d324a9821ca1282a468a4289201..5fac94f86317f082ee835c29c5dd9be0baf82e69 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -1116,6 +1116,7 @@ _copySubPlan(SubPlan *from) 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); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index c5f09cab82ae006903eea3836fca54a317f3e7d0..36f2bcc2d517b4203b06766bfcab7998061352d4 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -341,6 +341,7 @@ _equalSubPlan(SubPlan *a, SubPlan *b) 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); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index f3ca8d36228a07c5aa7e72ded6c0f13c741baef2..67f051311fd37570a0e75fae2cff3960ce8073e1 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * 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* @@ -961,6 +961,7 @@ _outSubPlan(StringInfo str, SubPlan *node) 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); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 2cf177ab01eebfcbaac63aa803cd954ab34d0b52..595ff1d46bb6338e05867b776802c8c8767f3e9f 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -412,8 +412,8 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, 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; @@ -606,6 +606,30 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, 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); @@ -875,7 +899,7 @@ SS_process_ctes(PlannerInfo *root) * 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; @@ -931,6 +955,10 @@ SS_process_ctes(PlannerInfo *root) 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); } @@ -2134,5 +2162,10 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *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; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index f05e6a2cb938c675cbaa0194d14ac0021d32d768..8d06f54e479d46b32eae5ab7a471a498ca068a5a 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * 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 $ * *------------------------------------------------------------------------- */ @@ -4404,20 +4404,42 @@ get_rule_expr(Node *node, deparse_context *context, 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: diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 9cb4e8e50ee3398cc58c13e45ad09ae808d986f9..7fc7c00d63eb31914985c72682dddb1a71bb7558 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -502,6 +502,8 @@ typedef struct SubPlan 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 */