Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fbcce08

Browse files
committed
Change EXPLAIN output so that subplans and initplans (particularly CTEs)
are individually labeled, rather than just grouped under an "InitPlan" or "SubPlan" heading. This in turn makes it possible for decompilation of a subplan reference to usefully identify which subplan it's referencing. I also made InitPlans identify which parameter symbol(s) they compute, so that references to those parameters elsewhere in the plan tree can be connected to the initplan that will be executed. Per a gripe from Robert Haas about EXPLAIN output of a WITH query being inadequate, plus some longstanding pet peeves of my own.
1 parent 329a532 commit fbcce08

File tree

7 files changed

+82
-22
lines changed

7 files changed

+82
-22
lines changed

src/backend/commands/explain.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.184 2009/01/02 20:42:00 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.185 2009/04/05 19:59:39 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -951,14 +951,14 @@ explain_outNode(StringInfo str,
951951
{
952952
ListCell *lst;
953953

954-
for (i = 0; i < indent; i++)
955-
appendStringInfo(str, " ");
956-
appendStringInfo(str, " InitPlan\n");
957954
foreach(lst, planstate->initPlan)
958955
{
959956
SubPlanState *sps = (SubPlanState *) lfirst(lst);
960957
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
961958

959+
for (i = 0; i < indent; i++)
960+
appendStringInfo(str, " ");
961+
appendStringInfo(str, " %s\n", sp->plan_name);
962962
for (i = 0; i < indent; i++)
963963
appendStringInfo(str, " ");
964964
appendStringInfo(str, " -> ");
@@ -1099,14 +1099,14 @@ explain_outNode(StringInfo str,
10991099
{
11001100
ListCell *lst;
11011101

1102-
for (i = 0; i < indent; i++)
1103-
appendStringInfo(str, " ");
1104-
appendStringInfo(str, " SubPlan\n");
11051102
foreach(lst, planstate->subPlan)
11061103
{
11071104
SubPlanState *sps = (SubPlanState *) lfirst(lst);
11081105
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
11091106

1107+
for (i = 0; i < indent; i++)
1108+
appendStringInfo(str, " ");
1109+
appendStringInfo(str, " %s\n", sp->plan_name);
11101110
for (i = 0; i < indent; i++)
11111111
appendStringInfo(str, " ");
11121112
appendStringInfo(str, " -> ");

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.428 2009/04/04 21:12:31 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.429 2009/04/05 19:59:39 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1116,6 +1116,7 @@ _copySubPlan(SubPlan *from)
11161116
COPY_NODE_FIELD(testexpr);
11171117
COPY_NODE_FIELD(paramIds);
11181118
COPY_SCALAR_FIELD(plan_id);
1119+
COPY_STRING_FIELD(plan_name);
11191120
COPY_SCALAR_FIELD(firstColType);
11201121
COPY_SCALAR_FIELD(firstColTypmod);
11211122
COPY_SCALAR_FIELD(useHashTable);

src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Portions Copyright (c) 1994, Regents of the University of California
2323
*
2424
* IDENTIFICATION
25-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.351 2009/04/04 21:12:31 tgl Exp $
25+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.352 2009/04/05 19:59:40 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -341,6 +341,7 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
341341
COMPARE_NODE_FIELD(testexpr);
342342
COMPARE_NODE_FIELD(paramIds);
343343
COMPARE_SCALAR_FIELD(plan_id);
344+
COMPARE_STRING_FIELD(plan_name);
344345
COMPARE_SCALAR_FIELD(firstColType);
345346
COMPARE_SCALAR_FIELD(firstColTypmod);
346347
COMPARE_SCALAR_FIELD(useHashTable);

src/backend/nodes/outfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.357 2009/04/04 21:12:31 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.358 2009/04/05 19:59:40 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -961,6 +961,7 @@ _outSubPlan(StringInfo str, SubPlan *node)
961961
WRITE_NODE_FIELD(testexpr);
962962
WRITE_NODE_FIELD(paramIds);
963963
WRITE_INT_FIELD(plan_id);
964+
WRITE_STRING_FIELD(plan_name);
964965
WRITE_OID_FIELD(firstColType);
965966
WRITE_INT_FIELD(firstColTypmod);
966967
WRITE_BOOL_FIELD(useHashTable);

src/backend/optimizer/plan/subselect.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.147 2009/03/10 22:09:26 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.148 2009/04/05 19:59:40 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -412,8 +412,8 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable,
412412
int paramid;
413413

414414
/*
415-
* Initialize the SubPlan node. Note plan_id isn't set till further down,
416-
* likewise the cost fields.
415+
* Initialize the SubPlan node. Note plan_id, plan_name, and cost fields
416+
* are set further down.
417417
*/
418418
splan = makeNode(SubPlan);
419419
splan->subLinkType = subLinkType;
@@ -606,6 +606,30 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable,
606606
root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
607607
splan->plan_id);
608608

609+
/* Label the subplan for EXPLAIN purposes */
610+
if (isInitPlan)
611+
{
612+
ListCell *lc;
613+
int offset;
614+
615+
splan->plan_name = palloc(32 + 12 * list_length(splan->setParam));
616+
sprintf(splan->plan_name, "InitPlan %d (returns ", splan->plan_id);
617+
offset = strlen(splan->plan_name);
618+
foreach(lc, splan->setParam)
619+
{
620+
sprintf(splan->plan_name + offset, "$%d%s",
621+
lfirst_int(lc),
622+
lnext(lc) ? "," : "");
623+
offset += strlen(splan->plan_name + offset);
624+
}
625+
sprintf(splan->plan_name + offset, ")");
626+
}
627+
else
628+
{
629+
splan->plan_name = palloc(32);
630+
sprintf(splan->plan_name, "SubPlan %d", splan->plan_id);
631+
}
632+
609633
/* Lastly, fill in the cost estimates for use later */
610634
cost_subplan(root, splan, plan);
611635

@@ -875,7 +899,7 @@ SS_process_ctes(PlannerInfo *root)
875899
* Make a SubPlan node for it. This is just enough unlike
876900
* build_subplan that we can't share code.
877901
*
878-
* Note plan_id isn't set till further down, likewise the cost fields.
902+
* Note plan_id, plan_name, and cost fields are set further down.
879903
*/
880904
splan = makeNode(SubPlan);
881905
splan->subLinkType = CTE_SUBLINK;
@@ -931,6 +955,10 @@ SS_process_ctes(PlannerInfo *root)
931955

932956
root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
933957

958+
/* Label the subplan for EXPLAIN purposes */
959+
splan->plan_name = palloc(4 + strlen(cte->ctename) + 1);
960+
sprintf(splan->plan_name, "CTE %s", cte->ctename);
961+
934962
/* Lastly, fill in the cost estimates for use later */
935963
cost_subplan(root, splan, plan);
936964
}
@@ -2134,5 +2162,10 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
21342162
prm = generate_new_param(root, resulttype, resulttypmod);
21352163
node->setParam = list_make1_int(prm->paramid);
21362164

2165+
/* Label the subplan for EXPLAIN purposes */
2166+
node->plan_name = palloc(64);
2167+
sprintf(node->plan_name, "InitPlan %d (returns $%d)",
2168+
node->plan_id, prm->paramid);
2169+
21372170
return prm;
21382171
}

src/backend/utils/adt/ruleutils.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.296 2009/02/25 18:00:01 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.297 2009/04/05 19:59:40 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -4404,20 +4404,42 @@ get_rule_expr(Node *node, deparse_context *context,
44044404

44054405
case T_SubPlan:
44064406
{
4407+
SubPlan *subplan = (SubPlan *) node;
4408+
44074409
/*
44084410
* We cannot see an already-planned subplan in rule deparsing,
4409-
* only while EXPLAINing a query plan. For now, just punt.
4411+
* only while EXPLAINing a query plan. We don't try to
4412+
* reconstruct the original SQL, just reference the subplan
4413+
* that appears elsewhere in EXPLAIN's result.
44104414
*/
4411-
if (((SubPlan *) node)->useHashTable)
4412-
appendStringInfo(buf, "(hashed subplan)");
4415+
if (subplan->useHashTable)
4416+
appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
44134417
else
4414-
appendStringInfo(buf, "(subplan)");
4418+
appendStringInfo(buf, "(%s)", subplan->plan_name);
44154419
}
44164420
break;
44174421

44184422
case T_AlternativeSubPlan:
4419-
/* As above, just punt */
4420-
appendStringInfo(buf, "(alternative subplans)");
4423+
{
4424+
AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
4425+
ListCell *lc;
4426+
4427+
/* As above, this can only happen during EXPLAIN */
4428+
appendStringInfo(buf, "(alternatives: ");
4429+
foreach(lc, asplan->subplans)
4430+
{
4431+
SubPlan *splan = (SubPlan *) lfirst(lc);
4432+
4433+
Assert(IsA(splan, SubPlan));
4434+
if (splan->useHashTable)
4435+
appendStringInfo(buf, "hashed %s", splan->plan_name);
4436+
else
4437+
appendStringInfo(buf, "%s", splan->plan_name);
4438+
if (lnext(lc))
4439+
appendStringInfo(buf, " or ");
4440+
}
4441+
appendStringInfo(buf, ")");
4442+
}
44214443
break;
44224444

44234445
case T_FieldSelect:

src/include/nodes/primnodes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
13-
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.147 2009/03/10 22:09:26 tgl Exp $
13+
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.148 2009/04/05 19:59:40 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -502,6 +502,8 @@ typedef struct SubPlan
502502
List *paramIds; /* IDs of Params embedded in the above */
503503
/* Identification of the Plan tree to use: */
504504
int plan_id; /* Index (from 1) in PlannedStmt.subplans */
505+
/* Identification of the SubPlan for EXPLAIN and debugging purposes: */
506+
char *plan_name; /* A name assigned during planning */
505507
/* Extra data useful for determining subplan's output type: */
506508
Oid firstColType; /* Type of first column of subplan result */
507509
int32 firstColTypmod; /* Typmod of first column of subplan result */

0 commit comments

Comments
 (0)