mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Fix interaction of triggers, partitioning, and EXPLAIN ANALYZE.
Add a new EState member es_leaf_result_relations, so that the trigger code knows about ResultRelInfos created by tuple routing. Also make sure ExplainPrintTriggers knows about partition-related ResultRelInfos. Etsuro Fujita, reviewed by Amit Langote Discussion: http://postgr.es/m/57163e18-8e56-da83-337a-22f2c0008051@lab.ntt.co.jp
This commit is contained in:
@ -1365,16 +1365,18 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
*
|
||||
* Get a ResultRelInfo for a trigger target relation. Most of the time,
|
||||
* triggers are fired on one of the result relations of the query, and so
|
||||
* we can just return a member of the es_result_relations array. (Note: in
|
||||
* self-join situations there might be multiple members with the same OID;
|
||||
* if so it doesn't matter which one we pick.) However, it is sometimes
|
||||
* necessary to fire triggers on other relations; this happens mainly when an
|
||||
* RI update trigger queues additional triggers on other relations, which will
|
||||
* be processed in the context of the outer query. For efficiency's sake,
|
||||
* we want to have a ResultRelInfo for those triggers too; that can avoid
|
||||
* repeated re-opening of the relation. (It also provides a way for EXPLAIN
|
||||
* ANALYZE to report the runtimes of such triggers.) So we make additional
|
||||
* ResultRelInfo's as needed, and save them in es_trig_target_relations.
|
||||
* we can just return a member of the es_result_relations array, the
|
||||
* es_root_result_relations array (if any), or the es_leaf_result_relations
|
||||
* list (if any). (Note: in self-join situations there might be multiple
|
||||
* members with the same OID; if so it doesn't matter which one we pick.)
|
||||
* However, it is sometimes necessary to fire triggers on other relations;
|
||||
* this happens mainly when an RI update trigger queues additional triggers
|
||||
* on other relations, which will be processed in the context of the outer
|
||||
* query. For efficiency's sake, we want to have a ResultRelInfo for those
|
||||
* triggers too; that can avoid repeated re-opening of the relation. (It
|
||||
* also provides a way for EXPLAIN ANALYZE to report the runtimes of such
|
||||
* triggers.) So we make additional ResultRelInfo's as needed, and save them
|
||||
* in es_trig_target_relations.
|
||||
*/
|
||||
ResultRelInfo *
|
||||
ExecGetTriggerResultRel(EState *estate, Oid relid)
|
||||
@ -1395,6 +1397,23 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
|
||||
rInfo++;
|
||||
nr--;
|
||||
}
|
||||
/* Second, search through the root result relations, if any */
|
||||
rInfo = estate->es_root_result_relations;
|
||||
nr = estate->es_num_root_result_relations;
|
||||
while (nr > 0)
|
||||
{
|
||||
if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
|
||||
return rInfo;
|
||||
rInfo++;
|
||||
nr--;
|
||||
}
|
||||
/* Third, search through the leaf result relations, if any */
|
||||
foreach(l, estate->es_leaf_result_relations)
|
||||
{
|
||||
rInfo = (ResultRelInfo *) lfirst(l);
|
||||
if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
|
||||
return rInfo;
|
||||
}
|
||||
/* Nope, but maybe we already made an extra ResultRelInfo for it */
|
||||
foreach(l, estate->es_trig_target_relations)
|
||||
{
|
||||
@ -3238,6 +3257,7 @@ EvalPlanQualEnd(EPQState *epqstate)
|
||||
void
|
||||
ExecSetupPartitionTupleRouting(Relation rel,
|
||||
Index resultRTindex,
|
||||
EState *estate,
|
||||
PartitionDispatch **pd,
|
||||
ResultRelInfo **partitions,
|
||||
TupleConversionMap ***tup_conv_maps,
|
||||
@ -3301,7 +3321,10 @@ ExecSetupPartitionTupleRouting(Relation rel,
|
||||
partrel,
|
||||
resultRTindex,
|
||||
rel,
|
||||
0);
|
||||
estate->es_instrument);
|
||||
|
||||
estate->es_leaf_result_relations =
|
||||
lappend(estate->es_leaf_result_relations, leaf_part_rri);
|
||||
|
||||
/*
|
||||
* Open partition indices (remember we do not support ON CONFLICT in
|
||||
|
Reference in New Issue
Block a user