aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execUtils.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2020-10-13 12:57:02 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2020-10-13 12:57:02 +0300
commit1375422c7826a2bf387be29895e961614f69de4b (patch)
tree17299eebfa3734f796d84ad44f3e5ab9f5557259 /src/backend/executor/execUtils.c
parent2050832d0d637358a376a99514071941aa93ed31 (diff)
downloadpostgresql-1375422c7826a2bf387be29895e961614f69de4b.tar.gz
postgresql-1375422c7826a2bf387be29895e961614f69de4b.zip
Create ResultRelInfos later in InitPlan, index them by RT index.
Instead of allocating all the ResultRelInfos upfront in one big array, allocate them in ExecInitModifyTable(). es_result_relations is now an array of ResultRelInfo pointers, rather than an array of structs, and it is indexed by the RT index. This simplifies things: we get rid of the separate concept of a "result rel index", and don't need to set it in setrefs.c anymore. This also allows follow-up optimizations (not included in this commit yet) to skip initializing ResultRelInfos for target relations that were not needed at runtime, and removal of the es_result_relation_info pointer. The EState arrays of regular result rels and root result rels are merged into one array. Similarly, the resultRelations and rootResultRelations lists in PlannedStmt are merged into one. It's not actually clear to me why they were kept separate in the first place, but now that the es_result_relations array is indexed by RT index, it certainly seems pointless. The PlannedStmt->resultRelations list is now only needed for ExecRelationIsTargetRelation(). One visible effect of this change is that ExecRelationIsTargetRelation() will now return 'true' also for the partition root, if a partitioned table is updated. That seems like a good thing, although the function isn't used in core code, and I don't see any reason for an FDW to call it on a partition root. Author: Amit Langote Discussion: https://www.postgresql.org/message-id/CA%2BHiwqGEmiib8FLiHMhKB%2BCH5dRgHSLc5N5wnvc4kym%2BZYpQEQ%40mail.gmail.com
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r--src/backend/executor/execUtils.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index d0e65b86473..6d8c112e2fe 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -124,14 +124,9 @@ CreateExecutorState(void)
estate->es_output_cid = (CommandId) 0;
estate->es_result_relations = NULL;
- estate->es_num_result_relations = 0;
+ estate->es_opened_result_relations = NIL;
estate->es_result_relation_info = NULL;
-
- estate->es_root_result_relations = NULL;
- estate->es_num_root_result_relations = 0;
-
estate->es_tuple_routing_result_relations = NIL;
-
estate->es_trig_target_relations = NIL;
estate->es_param_list_info = NULL;
@@ -711,16 +706,7 @@ ExecCreateScanSlotFromOuterPlan(EState *estate,
bool
ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
{
- ResultRelInfo *resultRelInfos;
- int i;
-
- resultRelInfos = estate->es_result_relations;
- for (i = 0; i < estate->es_num_result_relations; i++)
- {
- if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
- return true;
- }
- return false;
+ return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
}
/* ----------------------------------------------------------------
@@ -779,9 +765,10 @@ ExecInitRangeTable(EState *estate, List *rangeTable)
palloc0(estate->es_range_table_size * sizeof(Relation));
/*
- * es_rowmarks is also parallel to the es_range_table, but it's allocated
- * only if needed.
+ * es_result_relations and es_rowmarks are also parallel to
+ * es_range_table, but are allocated only if needed.
*/
+ estate->es_result_relations = NULL;
estate->es_rowmarks = NULL;
}
@@ -836,6 +823,40 @@ ExecGetRangeTableRelation(EState *estate, Index rti)
}
/*
+ * ExecInitResultRelation
+ * Open relation given by the passed-in RT index and fill its
+ * ResultRelInfo node
+ *
+ * Here, we also save the ResultRelInfo in estate->es_result_relations array
+ * such that it can be accessed later using the RT index.
+ */
+void
+ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
+ Index rti)
+{
+ Relation resultRelationDesc;
+
+ resultRelationDesc = ExecGetRangeTableRelation(estate, rti);
+ InitResultRelInfo(resultRelInfo,
+ resultRelationDesc,
+ rti,
+ NULL,
+ estate->es_instrument);
+
+ if (estate->es_result_relations == NULL)
+ estate->es_result_relations = (ResultRelInfo **)
+ palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
+ estate->es_result_relations[rti - 1] = resultRelInfo;
+
+ /*
+ * Saving in the list allows to avoid needlessly traversing the whole
+ * array when only a few of its entries are possibly non-NULL.
+ */
+ estate->es_opened_result_relations =
+ lappend(estate->es_opened_result_relations, resultRelInfo);
+}
+
+/*
* UpdateChangedParamSet
* Add changed parameters to a plan node's chgParam set
*/