Skip to content

Commit abe45a9

Browse files
committed
Fix EXPLAIN output for cases where parent table is excluded by constraints.
The previous coding in EXPLAIN always labeled a ModifyTable node with the name of the target table affected by its first child plan. When originally written, this was necessarily the parent table of the inheritance tree, so everything was unconfusing. But when we added NO INHERIT constraints, it became possible for the parent table to be deleted from the plan by constraint exclusion while still leaving child tables present. This led to the ModifyTable plan node being labeled with the first surviving child, which was deemed confusing. Fix it by retaining the parent table's RT index in a new field in ModifyTable. Etsuro Fujita, reviewed by Ashutosh Bapat and myself
1 parent 931bf3e commit abe45a9

File tree

8 files changed

+29
-14
lines changed

8 files changed

+29
-14
lines changed

src/backend/commands/explain.c

+2-12
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,8 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
736736
((Scan *) plan)->scanrelid);
737737
break;
738738
case T_ModifyTable:
739-
/* cf ExplainModifyTarget */
740739
*rels_used = bms_add_member(*rels_used,
741-
linitial_int(((ModifyTable *) plan)->resultRelations));
740+
((ModifyTable *) plan)->nominalRelation);
742741
break;
743742
default:
744743
break;
@@ -2192,16 +2191,7 @@ ExplainScanTarget(Scan *plan, ExplainState *es)
21922191
static void
21932192
ExplainModifyTarget(ModifyTable *plan, ExplainState *es)
21942193
{
2195-
Index rti;
2196-
2197-
/*
2198-
* We show the name of the first target relation. In multi-target-table
2199-
* cases this should always be the parent of the inheritance tree.
2200-
*/
2201-
Assert(plan->resultRelations != NIL);
2202-
rti = linitial_int(plan->resultRelations);
2203-
2204-
ExplainTargetRel((Plan *) plan, rti, es);
2194+
ExplainTargetRel((Plan *) plan, plan->nominalRelation, es);
22052195
}
22062196

22072197
/*

src/backend/nodes/copyfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ _copyModifyTable(const ModifyTable *from)
175175
*/
176176
COPY_SCALAR_FIELD(operation);
177177
COPY_SCALAR_FIELD(canSetTag);
178+
COPY_SCALAR_FIELD(nominalRelation);
178179
COPY_NODE_FIELD(resultRelations);
179180
COPY_SCALAR_FIELD(resultRelIndex);
180181
COPY_NODE_FIELD(plans);

src/backend/nodes/outfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ _outModifyTable(StringInfo str, const ModifyTable *node)
327327

328328
WRITE_ENUM_FIELD(operation, CmdType);
329329
WRITE_BOOL_FIELD(canSetTag);
330+
WRITE_UINT_FIELD(nominalRelation);
330331
WRITE_NODE_FIELD(resultRelations);
331332
WRITE_INT_FIELD(resultRelIndex);
332333
WRITE_NODE_FIELD(plans);

src/backend/optimizer/plan/createplan.c

+2
Original file line numberDiff line numberDiff line change
@@ -4809,6 +4809,7 @@ make_result(PlannerInfo *root,
48094809
ModifyTable *
48104810
make_modifytable(PlannerInfo *root,
48114811
CmdType operation, bool canSetTag,
4812+
Index nominalRelation,
48124813
List *resultRelations, List *subplans,
48134814
List *withCheckOptionLists, List *returningLists,
48144815
List *rowMarks, int epqParam)
@@ -4857,6 +4858,7 @@ make_modifytable(PlannerInfo *root,
48574858

48584859
node->operation = operation;
48594860
node->canSetTag = canSetTag;
4861+
node->nominalRelation = nominalRelation;
48604862
node->resultRelations = resultRelations;
48614863
node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
48624864
node->plans = subplans;

src/backend/optimizer/plan/planner.c

+18-1
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
607607
plan = (Plan *) make_modifytable(root,
608608
parse->commandType,
609609
parse->canSetTag,
610+
parse->resultRelation,
610611
list_make1_int(parse->resultRelation),
611612
list_make1(plan),
612613
withCheckOptionLists,
@@ -790,6 +791,7 @@ inheritance_planner(PlannerInfo *root)
790791
{
791792
Query *parse = root->parse;
792793
int parentRTindex = parse->resultRelation;
794+
int nominalRelation = -1;
793795
List *final_rtable = NIL;
794796
int save_rel_array_size = 0;
795797
RelOptInfo **save_rel_array = NULL;
@@ -924,6 +926,20 @@ inheritance_planner(PlannerInfo *root)
924926
*/
925927
appinfo->child_relid = subroot.parse->resultRelation;
926928

929+
/*
930+
* We'll use the first child relation (even if it's excluded) as the
931+
* nominal target relation of the ModifyTable node. Because of the
932+
* way expand_inherited_rtentry works, this should always be the RTE
933+
* representing the parent table in its role as a simple member of the
934+
* inheritance set. (It would be logically cleaner to use the
935+
* inheritance parent RTE as the nominal target; but since that RTE
936+
* will not be otherwise referenced in the plan, doing so would give
937+
* rise to confusing use of multiple aliases in EXPLAIN output for
938+
* what the user will think is the "same" table.)
939+
*/
940+
if (nominalRelation < 0)
941+
nominalRelation = appinfo->child_relid;
942+
927943
/*
928944
* If this child rel was excluded by constraint exclusion, exclude it
929945
* from the result plan.
@@ -1051,6 +1067,7 @@ inheritance_planner(PlannerInfo *root)
10511067
return (Plan *) make_modifytable(root,
10521068
parse->commandType,
10531069
parse->canSetTag,
1070+
nominalRelation,
10541071
resultRelations,
10551072
subplans,
10561073
withCheckOptionLists,
@@ -2260,7 +2277,7 @@ preprocess_rowmarks(PlannerInfo *root)
22602277
newrc->markType = ROW_MARK_REFERENCE;
22612278
else
22622279
newrc->markType = ROW_MARK_COPY;
2263-
newrc->waitPolicy = LockWaitBlock; /* doesn't matter */
2280+
newrc->waitPolicy = LockWaitBlock; /* doesn't matter */
22642281
newrc->isParent = false;
22652282

22662283
prowmarks = lappend(prowmarks, newrc);

src/backend/optimizer/plan/setrefs.c

+2
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,8 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
754754
splan->plan.targetlist = copyObject(linitial(newRL));
755755
}
756756

757+
splan->nominalRelation += rtoffset;
758+
757759
foreach(l, splan->resultRelations)
758760
{
759761
lfirst_int(l) += rtoffset;

src/include/nodes/plannodes.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ typedef struct PlannedStmt
7070

7171
int nParamExec; /* number of PARAM_EXEC Params used */
7272

73-
bool hasRowSecurity; /* row security applied? */
73+
bool hasRowSecurity; /* row security applied? */
7474

7575
} PlannedStmt;
7676

@@ -174,6 +174,7 @@ typedef struct ModifyTable
174174
Plan plan;
175175
CmdType operation; /* INSERT, UPDATE, or DELETE */
176176
bool canSetTag; /* do we set the command tag/es_processed? */
177+
Index nominalRelation; /* Parent RT index for use of EXPLAIN */
177178
List *resultRelations; /* integer list of RT indexes */
178179
int resultRelIndex; /* index of first resultRel in plan's list */
179180
List *plans; /* plan(s) producing source data */

src/include/optimizer/planmain.h

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ extern Result *make_result(PlannerInfo *root, List *tlist,
8282
Node *resconstantqual, Plan *subplan);
8383
extern ModifyTable *make_modifytable(PlannerInfo *root,
8484
CmdType operation, bool canSetTag,
85+
Index nominalRelation,
8586
List *resultRelations, List *subplans,
8687
List *withCheckOptionLists, List *returningLists,
8788
List *rowMarks, int epqParam);

0 commit comments

Comments
 (0)