From 2ff8683dff093f81fb0913312bfeca6c8d02de56 Mon Sep 17 00:00:00 2001 From: amitlan Date: Thu, 18 Jun 2020 13:12:21 +0900 Subject: [PATCH v3 2/4] Don't make "root" ResultRelInfo for insert queries For inserts on partitioned tables, we don't need a separate ResultRelInfo for the root partitioned table, which being the query's main target relation already has one, unlike UPDATE and DELETE where only the leaf partitions are in the list of target relations. We need a ResultRelInfo for the root partitioned table in the UPDATE and DELETE cases so as to fire statement triggers on them. Also, in the UPDATE's case it is used as the target result relation when moving a row from one row to another. --- src/backend/executor/execPartition.c | 2 +- src/backend/executor/nodeModifyTable.c | 19 ++++++------------- src/backend/optimizer/plan/planner.c | 12 +----------- src/backend/optimizer/plan/setrefs.c | 11 ++++++++--- src/include/nodes/pathnodes.h | 4 +++- src/include/nodes/plannodes.h | 8 ++++++-- 6 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index fb6ce49..ef17acd 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -522,7 +522,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, leaf_part_rri = makeNode(ResultRelInfo); InitResultRelInfo(leaf_part_rri, partrel, - node ? node->rootRelation : 1, + rootResultRelInfo->ri_RangeTableIndex, rootrel, estate->es_instrument); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 20a4c47..09a9871 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1738,15 +1738,7 @@ static void fireBSTriggers(ModifyTableState *node) { ModifyTable *plan = (ModifyTable *) node->ps.plan; - ResultRelInfo *resultRelInfo = node->resultRelInfo; - - /* - * If the node modifies a partitioned table, we must fire its triggers. - * Note that in that case, node->resultRelInfo points to the first leaf - * partition, not the root table. - */ - if (node->rootResultRelInfo != NULL) - resultRelInfo = node->rootResultRelInfo; + ResultRelInfo *resultRelInfo = getTargetResultRelInfo(node); switch (node->operation) { @@ -1772,17 +1764,18 @@ fireBSTriggers(ModifyTableState *node) * Return the target rel ResultRelInfo. * * This relation is the same as : - * - the relation for which we will fire AFTER STATEMENT triggers. + * - the relation for which we will fire BEFIRE/AFTER STATEMENT triggers. * - the relation into whose tuple format all captured transition tuples must * be converted. - * - the root partitioned table. + * - the root partitioned table mentioned in an UPDATE or DELETE query. */ static ResultRelInfo * getTargetResultRelInfo(ModifyTableState *node) { /* - * Note that if the node modifies a partitioned table, node->resultRelInfo - * points to the first leaf partition, not the root table. + * Note that if the node performs an UPDATE or DELETE on a partitioned + * table, node->resultRelInfo points to the first leaf partition, not the + * root table. */ if (node->rootResultRelInfo != NULL) return node->rootResultRelInfo; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index b40a112..9486873 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -2329,22 +2329,12 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, */ if (parse->commandType != CMD_SELECT && !inheritance_update) { - Index rootRelation; + Index rootRelation = 0; List *withCheckOptionLists; List *returningLists; List *rowMarks; /* - * If target is a partition root table, we need to mark the - * ModifyTable node appropriately for that. - */ - if (rt_fetch(parse->resultRelation, parse->rtable)->relkind == - RELKIND_PARTITIONED_TABLE) - rootRelation = parse->resultRelation; - else - rootRelation = 0; - - /* * Set up the WITH CHECK OPTION and RETURNING lists-of-lists, if * needed. */ diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index f3d1a12..05a0882 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -930,12 +930,17 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) splan->resultRelations); /* - * If the main target relation is a partitioned table, also - * add the partition root's RT index to rootResultRelations, - * and remember its index in that list in rootResultRelIndex. + * If the main target relation of an inherited UPDATE/DELETE + * operation is a partitioned table, also add the partition + * root's RT index to rootResultRelations, and remember its + * index in that list in rootResultRelIndex. We don't need + * this for INSERT though as there are no other result + * relations present in query beside the partition root whose + * index is given by resultRelIndex. */ if (splan->rootRelation) { + Assert(splan->operation != CMD_INSERT); splan->rootResultRelIndex = list_length(root->glob->rootResultRelations); root->glob->rootResultRelations = diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b0..2a2db9c 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -1813,7 +1813,9 @@ typedef struct ModifyTablePath CmdType operation; /* INSERT, UPDATE, or DELETE */ bool canSetTag; /* do we set the command tag/es_processed? */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */ - Index rootRelation; /* Root RT index, if target is partitioned */ + Index rootRelation; /* RT index of root partitioned target + * relation; valid only for UPDATE or DELETE, + * 0 for INSERT */ bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ List *subpaths; /* Path(s) producing source data */ diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 7314d2f..13043d1 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -221,11 +221,15 @@ typedef struct ModifyTable CmdType operation; /* INSERT, UPDATE, or DELETE */ bool canSetTag; /* do we set the command tag/es_processed? */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */ - Index rootRelation; /* Root RT index, if target is partitioned */ + Index rootRelation; /* RT index of root partitioned target + * relation; valid only for UPDATE or DELETE, + * 0 for INSERT */ bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ int resultRelIndex; /* index of first resultRel in plan's list */ - int rootResultRelIndex; /* index of the partitioned table root */ + int rootResultRelIndex; /* index of root partitioned target + * relation in plan's list; valid only for + * UPDATE or DELETE, -1 for INSERT */ List *plans; /* plan(s) producing source data */ List *withCheckOptionLists; /* per-target-table WCO lists */ List *returningLists; /* per-target-table RETURNING tlists */ -- 1.8.3.1