aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c256
1 files changed, 73 insertions, 183 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 2e27e26ba44..783eecbc133 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -827,86 +827,8 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_plannedstmt = plannedstmt;
- /*
- * Initialize ResultRelInfo data structures, and open the result rels.
- */
- if (plannedstmt->resultRelations)
- {
- List *resultRelations = plannedstmt->resultRelations;
- int numResultRelations = list_length(resultRelations);
- ResultRelInfo *resultRelInfos;
- ResultRelInfo *resultRelInfo;
-
- resultRelInfos = (ResultRelInfo *)
- palloc(numResultRelations * sizeof(ResultRelInfo));
- resultRelInfo = resultRelInfos;
- foreach(l, resultRelations)
- {
- Index resultRelationIndex = lfirst_int(l);
- Relation resultRelation;
-
- resultRelation = ExecGetRangeTableRelation(estate,
- resultRelationIndex);
- InitResultRelInfo(resultRelInfo,
- resultRelation,
- resultRelationIndex,
- NULL,
- estate->es_instrument);
- resultRelInfo++;
- }
- estate->es_result_relations = resultRelInfos;
- estate->es_num_result_relations = numResultRelations;
-
- /* es_result_relation_info is NULL except when within ModifyTable */
- estate->es_result_relation_info = NULL;
-
- /*
- * In the partitioned result relation case, also build ResultRelInfos
- * for all the partitioned table roots, because we will need them to
- * fire statement-level triggers, if any.
- */
- if (plannedstmt->rootResultRelations)
- {
- int num_roots = list_length(plannedstmt->rootResultRelations);
-
- resultRelInfos = (ResultRelInfo *)
- palloc(num_roots * sizeof(ResultRelInfo));
- resultRelInfo = resultRelInfos;
- foreach(l, plannedstmt->rootResultRelations)
- {
- Index resultRelIndex = lfirst_int(l);
- Relation resultRelDesc;
-
- resultRelDesc = ExecGetRangeTableRelation(estate,
- resultRelIndex);
- InitResultRelInfo(resultRelInfo,
- resultRelDesc,
- resultRelIndex,
- NULL,
- estate->es_instrument);
- resultRelInfo++;
- }
-
- estate->es_root_result_relations = resultRelInfos;
- estate->es_num_root_result_relations = num_roots;
- }
- else
- {
- estate->es_root_result_relations = NULL;
- estate->es_num_root_result_relations = 0;
- }
- }
- else
- {
- /*
- * if no result relation, then set state appropriately
- */
- 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;
- }
+ /* es_result_relation_info is NULL except when within ModifyTable */
+ estate->es_result_relation_info = NULL;
/*
* Next, build the ExecRowMark array from the PlanRowMark(s), if any.
@@ -1334,8 +1256,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
*
* 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,
- * or the es_root_result_relations array (if any), or the
- * es_tuple_routing_result_relations list (if any). (Note: in self-join
+ * or the es_tuple_routing_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.)
*
@@ -1352,30 +1273,16 @@ ResultRelInfo *
ExecGetTriggerResultRel(EState *estate, Oid relid)
{
ResultRelInfo *rInfo;
- int nr;
ListCell *l;
Relation rel;
MemoryContext oldcontext;
/* First, search through the query result relations */
- rInfo = estate->es_result_relations;
- nr = estate->es_num_result_relations;
- while (nr > 0)
+ foreach(l, estate->es_opened_result_relations)
{
+ rInfo = lfirst(l);
if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
return rInfo;
- 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--;
}
/*
@@ -1428,35 +1335,6 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
return rInfo;
}
-/*
- * Close any relations that have been opened by ExecGetTriggerResultRel().
- */
-void
-ExecCleanUpTriggerState(EState *estate)
-{
- ListCell *l;
-
- foreach(l, estate->es_trig_target_relations)
- {
- ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
-
- /*
- * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
- * might be issuing a duplicate close against a Relation opened by
- * ExecGetRangeTableRelation.
- */
- Assert(resultRelInfo->ri_RangeTableIndex == 0);
-
- /*
- * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
- * these rels, we needn't call ExecCloseIndices either.
- */
- Assert(resultRelInfo->ri_NumIndices == 0);
-
- table_close(resultRelInfo->ri_RelationDesc, NoLock);
- }
-}
-
/* ----------------------------------------------------------------
* ExecPostprocessPlan
*
@@ -1512,9 +1390,6 @@ ExecPostprocessPlan(EState *estate)
static void
ExecEndPlan(PlanState *planstate, EState *estate)
{
- ResultRelInfo *resultRelInfo;
- Index num_relations;
- Index i;
ListCell *l;
/*
@@ -1541,29 +1416,69 @@ ExecEndPlan(PlanState *planstate, EState *estate)
ExecResetTupleTable(estate->es_tupleTable, false);
/*
- * close indexes of result relation(s) if any. (Rels themselves get
- * closed next.)
+ * Close any Relations that have been opened for range table entries or
+ * result relations.
*/
- resultRelInfo = estate->es_result_relations;
- for (i = estate->es_num_result_relations; i > 0; i--)
+ ExecCloseResultRelations(estate);
+ ExecCloseRangeTableRelations(estate);
+}
+
+/*
+ * Close any relations that have been opened for ResultRelInfos.
+ */
+void
+ExecCloseResultRelations(EState *estate)
+{
+ ListCell *l;
+
+ /*
+ * close indexes of result relation(s) if any. (Rels themselves are
+ * closed in ExecCloseRangeTableRelations())
+ */
+ foreach(l, estate->es_opened_result_relations)
{
+ ResultRelInfo *resultRelInfo = lfirst(l);
+
ExecCloseIndices(resultRelInfo);
- resultRelInfo++;
}
- /*
- * close whatever rangetable Relations have been opened. We do not
- * release any locks we might hold on those rels.
- */
- num_relations = estate->es_range_table_size;
- for (i = 0; i < num_relations; i++)
+ /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
+ foreach(l, estate->es_trig_target_relations)
+ {
+ ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
+
+ /*
+ * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
+ * might be issuing a duplicate close against a Relation opened by
+ * ExecGetRangeTableRelation.
+ */
+ Assert(resultRelInfo->ri_RangeTableIndex == 0);
+
+ /*
+ * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
+ * these rels, we needn't call ExecCloseIndices either.
+ */
+ Assert(resultRelInfo->ri_NumIndices == 0);
+
+ table_close(resultRelInfo->ri_RelationDesc, NoLock);
+ }
+}
+
+/*
+ * Close all relations opened by ExecGetRangeTableRelation().
+ *
+ * We do not release any locks we might hold on those rels.
+ */
+void
+ExecCloseRangeTableRelations(EState *estate)
+{
+ int i;
+
+ for (i = 0; i < estate->es_range_table_size; i++)
{
if (estate->es_relations[i])
table_close(estate->es_relations[i], NoLock);
}
-
- /* likewise close any trigger target relations */
- ExecCleanUpTriggerState(estate);
}
/* ----------------------------------------------------------------
@@ -2758,17 +2673,9 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
/*
* Child EPQ EStates share the parent's copy of unchanging state such as
- * the snapshot, rangetable, result-rel info, and external Param info.
- * They need their own copies of local state, including a tuple table,
- * es_param_exec_vals, etc.
- *
- * The ResultRelInfo array management is trickier than it looks. We
- * create fresh arrays for the child but copy all the content from the
- * parent. This is because it's okay for the child to share any
- * per-relation state the parent has already created --- but if the child
- * sets up any ResultRelInfo fields, such as its own junkfilter, that
- * state must *not* propagate back to the parent. (For one thing, the
- * pointed-to data is in a memory context that won't last long enough.)
+ * the snapshot, rangetable, and external Param info. They need their own
+ * copies of local state, including a tuple table, es_param_exec_vals,
+ * result-rel info, etc.
*/
rcestate->es_direction = ForwardScanDirection;
rcestate->es_snapshot = parentestate->es_snapshot;
@@ -2781,30 +2688,12 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
rcestate->es_plannedstmt = parentestate->es_plannedstmt;
rcestate->es_junkFilter = parentestate->es_junkFilter;
rcestate->es_output_cid = parentestate->es_output_cid;
- if (parentestate->es_num_result_relations > 0)
- {
- int numResultRelations = parentestate->es_num_result_relations;
- int numRootResultRels = parentestate->es_num_root_result_relations;
- ResultRelInfo *resultRelInfos;
-
- resultRelInfos = (ResultRelInfo *)
- palloc(numResultRelations * sizeof(ResultRelInfo));
- memcpy(resultRelInfos, parentestate->es_result_relations,
- numResultRelations * sizeof(ResultRelInfo));
- rcestate->es_result_relations = resultRelInfos;
- rcestate->es_num_result_relations = numResultRelations;
-
- /* Also transfer partitioned root result relations. */
- if (numRootResultRels > 0)
- {
- resultRelInfos = (ResultRelInfo *)
- palloc(numRootResultRels * sizeof(ResultRelInfo));
- memcpy(resultRelInfos, parentestate->es_root_result_relations,
- numRootResultRels * sizeof(ResultRelInfo));
- rcestate->es_root_result_relations = resultRelInfos;
- rcestate->es_num_root_result_relations = numRootResultRels;
- }
- }
+
+ /*
+ * ResultRelInfos needed by subplans are initialized from scratch when the
+ * subplans themselves are initialized.
+ */
+ parentestate->es_result_relations = NULL;
/* es_result_relation_info must NOT be copied */
/* es_trig_target_relations must NOT be copied */
rcestate->es_top_eflags = parentestate->es_top_eflags;
@@ -2914,8 +2803,9 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
* This is a cut-down version of ExecutorEnd(); basically we want to do most
* of the normal cleanup, but *not* close result relations (which we are
* just sharing from the outer query). We do, however, have to close any
- * trigger target relations that got opened, since those are not shared.
- * (There probably shouldn't be any of the latter, but just in case...)
+ * result and trigger target relations that got opened, since those are not
+ * shared. (There probably shouldn't be any of the latter, but just in
+ * case...)
*/
void
EvalPlanQualEnd(EPQState *epqstate)
@@ -2957,8 +2847,8 @@ EvalPlanQualEnd(EPQState *epqstate)
/* throw away the per-estate tuple table, some node may have used it */
ExecResetTupleTable(estate->es_tupleTable, false);
- /* close any trigger target relations attached to this EState */
- ExecCleanUpTriggerState(estate);
+ /* Close any result and trigger target relations attached to this EState */
+ ExecCloseResultRelations(estate);
MemoryContextSwitchTo(oldcontext);