aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-05-01 08:23:01 -0400
committerRobert Haas <rhaas@postgresql.org>2017-05-01 08:23:01 -0400
commite180c8aa8caf5c55a273d4a8e6092e77ff3cff10 (patch)
treedb85b867105969b352fdd95ac83d506fae3f8e04 /src/backend/executor/execMain.c
parente18b2c480da478f62781e06488cda56fe1b4e919 (diff)
downloadpostgresql-e180c8aa8caf5c55a273d4a8e6092e77ff3cff10.tar.gz
postgresql-e180c8aa8caf5c55a273d4a8e6092e77ff3cff10.zip
Fire per-statement triggers on partitioned tables.
Even though no actual tuples are ever inserted into a partitioned table (the actual tuples are in the partitions, not the partitioned table itself), we still need to have a ResultRelInfo for the partitioned table, or per-statement triggers won't get fired. Amit Langote, per a report from Rajkumar Raghuwanshi. Reviewed by me. Discussion: http://postgr.es/m/CAKcux6%3DwYospCRY2J4XEFuVy0L41S%3Dfic7rmkbsU-GXhhSbmBg%40mail.gmail.com
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 5c12fb457d5..cdb1a6a5f5d 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -861,17 +861,52 @@ InitPlan(QueryDesc *queryDesc, int eflags)
/*
* In the partitioned result relation case, lock the non-leaf result
- * relations too. We don't however need ResultRelInfos for them.
+ * relations too. A subset of these are the roots of respective
+ * partitioned tables, for which we also allocate ResulRelInfos.
*/
+ estate->es_root_result_relations = NULL;
+ estate->es_num_root_result_relations = 0;
if (plannedstmt->nonleafResultRelations)
{
+ int num_roots = list_length(plannedstmt->rootResultRelations);
+
+ /*
+ * Firstly, build ResultRelInfos for all the partitioned table
+ * roots, because we will need them to fire the statement-level
+ * triggers, if any.
+ */
+ resultRelInfos = (ResultRelInfo *)
+ palloc(num_roots * sizeof(ResultRelInfo));
+ resultRelInfo = resultRelInfos;
+ foreach(l, plannedstmt->rootResultRelations)
+ {
+ Index resultRelIndex = lfirst_int(l);
+ Oid resultRelOid;
+ Relation resultRelDesc;
+
+ resultRelOid = getrelid(resultRelIndex, rangeTable);
+ resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
+ InitResultRelInfo(resultRelInfo,
+ resultRelDesc,
+ lfirst_int(l),
+ NULL,
+ estate->es_instrument);
+ resultRelInfo++;
+ }
+
+ estate->es_root_result_relations = resultRelInfos;
+ estate->es_num_root_result_relations = num_roots;
+
+ /* Simply lock the rest of them. */
foreach(l, plannedstmt->nonleafResultRelations)
{
- Index resultRelationIndex = lfirst_int(l);
- Oid resultRelationOid;
+ Index resultRelIndex = lfirst_int(l);
- resultRelationOid = getrelid(resultRelationIndex, rangeTable);
- LockRelationOid(resultRelationOid, RowExclusiveLock);
+ /* We locked the roots above. */
+ if (!list_member_int(plannedstmt->rootResultRelations,
+ resultRelIndex))
+ LockRelationOid(getrelid(resultRelIndex, rangeTable),
+ RowExclusiveLock);
}
}
}
@@ -883,6 +918,8 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_result_relations = NULL;
estate->es_num_result_relations = 0;
estate->es_result_relation_info = NULL;
+ estate->es_root_result_relations = NULL;
+ estate->es_num_root_result_relations = 0;
}
/*
@@ -1565,6 +1602,14 @@ ExecEndPlan(PlanState *planstate, EState *estate)
resultRelInfo++;
}
+ /* Close the root target relation(s). */
+ resultRelInfo = estate->es_root_result_relations;
+ for (i = estate->es_num_root_result_relations; i > 0; i--)
+ {
+ heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ resultRelInfo++;
+ }
+
/*
* likewise close any trigger target relations
*/