Hi, I think ExplainModifyTarget should show the parent of the inheritance tree in multi-target-table cases, as described there, but noticed that it doesn't always work like that. Here is an example.
postgres=# create table parent (a int check (a < 0) no inherit); CREATE TABLE postgres=# create table child (a int check (a >= 0)); CREATE TABLE postgres=# alter table child inherit parent; ALTER TABLE postgres=# explain update parent set a = a * 2 where a >= 0; QUERY PLAN --------------------------------------------------------------- Update on child (cost=0.00..42.00 rows=800 width=10) -> Seq Scan on child (cost=0.00..42.00 rows=800 width=10) Filter: (a >= 0) (3 rows) IIUC, I think this is because ExplainModifyTarget doesn't take into account that the parent *can* be excluded by constraint exclusion. So, I added a field to ModifyTable to record the parent, apart from resultRelations. (More precisely, the parent in its role as a simple member of the inheritance tree is recorded so that appending digits to refname in select_rtable_names_for_explain works as before.) Attached is a proposed patch for that. Thanks, Best regards, Etsuro Fujita
*** a/src/backend/commands/explain.c --- b/src/backend/commands/explain.c *************** *** 728,736 **** ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) ((Scan *) plan)->scanrelid); break; case T_ModifyTable: - /* cf ExplainModifyTarget */ *rels_used = bms_add_member(*rels_used, ! linitial_int(((ModifyTable *) plan)->resultRelations)); break; default: break; --- 728,735 ---- ((Scan *) plan)->scanrelid); break; case T_ModifyTable: *rels_used = bms_add_member(*rels_used, ! ((ModifyTable *) plan)->resultRelation); break; default: break; *************** *** 2109,2122 **** ExplainScanTarget(Scan *plan, ExplainState *es) static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es) { ! Index rti; ! ! /* ! * We show the name of the first target relation. In multi-target-table ! * cases this should always be the parent of the inheritance tree. ! */ ! Assert(plan->resultRelations != NIL); ! rti = linitial_int(plan->resultRelations); ExplainTargetRel((Plan *) plan, rti, es); } --- 2108,2114 ---- static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es) { ! Index rti = plan->resultRelation; ExplainTargetRel((Plan *) plan, rti, es); } *** a/src/backend/nodes/copyfuncs.c --- b/src/backend/nodes/copyfuncs.c *************** *** 175,180 **** _copyModifyTable(const ModifyTable *from) --- 175,181 ---- */ COPY_SCALAR_FIELD(operation); COPY_SCALAR_FIELD(canSetTag); + COPY_SCALAR_FIELD(resultRelation); COPY_NODE_FIELD(resultRelations); COPY_SCALAR_FIELD(resultRelIndex); COPY_NODE_FIELD(plans); *** a/src/backend/nodes/outfuncs.c --- b/src/backend/nodes/outfuncs.c *************** *** 327,332 **** _outModifyTable(StringInfo str, const ModifyTable *node) --- 327,333 ---- WRITE_ENUM_FIELD(operation, CmdType); WRITE_BOOL_FIELD(canSetTag); + WRITE_UINT_FIELD(resultRelation); WRITE_NODE_FIELD(resultRelations); WRITE_INT_FIELD(resultRelIndex); WRITE_NODE_FIELD(plans); *** a/src/backend/optimizer/plan/createplan.c --- b/src/backend/optimizer/plan/createplan.c *************** *** 4809,4814 **** make_result(PlannerInfo *root, --- 4809,4815 ---- ModifyTable * make_modifytable(PlannerInfo *root, CmdType operation, bool canSetTag, + Index resultRelation, List *resultRelations, List *subplans, List *withCheckOptionLists, List *returningLists, List *rowMarks, int epqParam) *************** *** 4857,4862 **** make_modifytable(PlannerInfo *root, --- 4858,4864 ---- node->operation = operation; node->canSetTag = canSetTag; + node->resultRelation = resultRelation; node->resultRelations = resultRelations; node->resultRelIndex = -1; /* will be set correctly in setrefs.c */ node->plans = subplans; *** a/src/backend/optimizer/plan/planner.c --- b/src/backend/optimizer/plan/planner.c *************** *** 607,612 **** subquery_planner(PlannerGlobal *glob, Query *parse, --- 607,613 ---- plan = (Plan *) make_modifytable(root, parse->commandType, parse->canSetTag, + parse->resultRelation, list_make1_int(parse->resultRelation), list_make1(plan), withCheckOptionLists, *************** *** 790,795 **** inheritance_planner(PlannerInfo *root) --- 791,797 ---- { Query *parse = root->parse; int parentRTindex = parse->resultRelation; + int pseudoParentRTindex = -1; List *final_rtable = NIL; int save_rel_array_size = 0; RelOptInfo **save_rel_array = NULL; *************** *** 925,930 **** inheritance_planner(PlannerInfo *root) --- 927,940 ---- appinfo->child_relid = subroot.parse->resultRelation; /* + * If this child rel was the first target relation, it should always be + * the parent rel in its role as a simple member of the inheritance set. + * Get it for use of EXPLAIN. + */ + if (pseudoParentRTindex == -1) + pseudoParentRTindex = appinfo->child_relid; + + /* * If this child rel was excluded by constraint exclusion, exclude it * from the result plan. */ *************** *** 1051,1056 **** inheritance_planner(PlannerInfo *root) --- 1061,1067 ---- return (Plan *) make_modifytable(root, parse->commandType, parse->canSetTag, + pseudoParentRTindex, resultRelations, subplans, withCheckOptionLists, *** a/src/backend/optimizer/plan/setrefs.c --- b/src/backend/optimizer/plan/setrefs.c *************** *** 754,759 **** set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) --- 754,761 ---- splan->plan.targetlist = copyObject(linitial(newRL)); } + splan->resultRelation += rtoffset; + foreach(l, splan->resultRelations) { lfirst_int(l) += rtoffset; *** a/src/include/nodes/plannodes.h --- b/src/include/nodes/plannodes.h *************** *** 174,179 **** typedef struct ModifyTable --- 174,180 ---- Plan plan; CmdType operation; /* INSERT, UPDATE, or DELETE */ bool canSetTag; /* do we set the command tag/es_processed? */ + Index resultRelation; /* Parent RT index for use of EXPLAIN */ List *resultRelations; /* integer list of RT indexes */ int resultRelIndex; /* index of first resultRel in plan's list */ List *plans; /* plan(s) producing source data */ *** a/src/include/optimizer/planmain.h --- b/src/include/optimizer/planmain.h *************** *** 82,87 **** extern Result *make_result(PlannerInfo *root, List *tlist, --- 82,88 ---- Node *resconstantqual, Plan *subplan); extern ModifyTable *make_modifytable(PlannerInfo *root, CmdType operation, bool canSetTag, + Index resultRelation, List *resultRelations, List *subplans, List *withCheckOptionLists, List *returningLists, List *rowMarks, int epqParam);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers