diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-05-01 08:23:01 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-05-01 08:23:01 -0400 |
commit | e180c8aa8caf5c55a273d4a8e6092e77ff3cff10 (patch) | |
tree | db85b867105969b352fdd95ac83d506fae3f8e04 /src/backend/executor/execMain.c | |
parent | e18b2c480da478f62781e06488cda56fe1b4e919 (diff) | |
download | postgresql-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.c | 55 |
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 */ |