v12-0002-Introduce-an-array-of-RangeTblEntry-pointers-in-.patch
text/plain
Filename: v12-0002-Introduce-an-array-of-RangeTblEntry-pointers-in-.patch
Type: text/plain
Part: 1
Message:
Re: executor relation handling
Patch
Format: format-patch
Series: patch v12-0002
Subject: Introduce an array of RangeTblEntry pointers in EState
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/postgres_fdw.c | 6 | 6 |
| src/backend/commands/copy.c | 1 | 1 |
| src/backend/commands/trigger.c | 2 | 1 |
| src/backend/executor/execExprInterp.c | 4 | 3 |
| src/backend/executor/execMain.c | 11 | 8 |
| src/backend/executor/execUtils.c | 23 | 1 |
| src/backend/executor/nodeLockRows.c | 1 | 1 |
| src/backend/replication/logical/worker.c | 2 | 0 |
| src/include/executor/executor.h | 1 | 0 |
| src/include/nodes/execnodes.h | 19 | 0 |
| src/include/parser/parsetree.h | 0 | 10 |
From c89a0b53040d680eefe4e7178e67a2fe878a24f1 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Wed, 3 Oct 2018 16:05:15 +0900
Subject: [PATCH v12 2/5] Introduce an array of RangeTblEntry pointers in
EState
Author: Amit Langote, David Rowley
---
contrib/postgres_fdw/postgres_fdw.c | 12 ++++++------
src/backend/commands/copy.c | 2 +-
src/backend/commands/trigger.c | 3 ++-
src/backend/executor/execExprInterp.c | 7 ++++---
src/backend/executor/execMain.c | 19 +++++++++++--------
src/backend/executor/execUtils.c | 24 +++++++++++++++++++++++-
src/backend/executor/nodeLockRows.c | 2 +-
src/backend/replication/logical/worker.c | 2 ++
src/include/executor/executor.h | 1 +
src/include/nodes/execnodes.h | 19 +++++++++++++++++++
src/include/parser/parsetree.h | 10 ----------
11 files changed, 70 insertions(+), 31 deletions(-)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index c02287a55c..3dd1bab2a2 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1345,7 +1345,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
rtindex = fsplan->scan.scanrelid;
else
rtindex = bms_next_member(fsplan->fs_relids, -1);
- rte = rt_fetch(rtindex, estate->es_range_table);
+ rte = exec_rt_fetch(rtindex, estate->es_range_table_array);
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
/* Get info about foreign table. */
@@ -1731,8 +1731,8 @@ postgresBeginForeignModify(ModifyTableState *mtstate,
FdwModifyPrivateRetrievedAttrs);
/* Find RTE. */
- rte = rt_fetch(resultRelInfo->ri_RangeTableIndex,
- mtstate->ps.state->es_range_table);
+ rte = exec_rt_fetch(resultRelInfo->ri_RangeTableIndex,
+ mtstate->ps.state->es_range_table_array);
/* Construct an execution state. */
fmstate = create_foreign_modify(mtstate->ps.state,
@@ -2036,7 +2036,7 @@ postgresBeginForeignInsert(ModifyTableState *mtstate,
* correspond to this partition if it is one of the UPDATE subplan target
* rels; in that case, we can just use the existing RTE as-is.
*/
- rte = list_nth(estate->es_range_table, resultRelation - 1);
+ rte = exec_rt_fetch(resultRelation, estate->es_range_table_array);
if (rte->relid != RelationGetRelid(rel))
{
rte = copyObject(rte);
@@ -2396,7 +2396,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
* ExecCheckRTEPerms() does.
*/
rtindex = estate->es_result_relation_info->ri_RangeTableIndex;
- rte = rt_fetch(rtindex, estate->es_range_table);
+ rte = exec_rt_fetch(rtindex, estate->es_range_table_array);
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
/* Get info about foreign table. */
@@ -5752,7 +5752,7 @@ conversion_error_callback(void *arg)
RangeTblEntry *rte;
Var *var = (Var *) tle->expr;
- rte = rt_fetch(var->varno, estate->es_range_table);
+ rte = exec_rt_fetch(var->varno, estate->es_range_table_array);
if (var->varattno == 0)
is_wholerow = true;
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 32706fad90..b2fededc9d 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2484,7 +2484,7 @@ CopyFrom(CopyState cstate)
estate->es_result_relations = resultRelInfo;
estate->es_num_result_relations = 1;
estate->es_result_relation_info = resultRelInfo;
- estate->es_range_table = cstate->range_table;
+ ExecInitRangeTable(estate, cstate->range_table);
/* Set up a tuple slot too */
myslot = ExecInitExtraTupleSlot(estate, tupDesc);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 136f9f0627..5ce3720440 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -75,7 +75,8 @@ static int MyTriggerDepth = 0;
* to be changed, however.
*/
#define GetUpdatedColumns(relinfo, estate) \
- (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
+ (exec_rt_fetch((relinfo)->ri_RangeTableIndex,\
+ (estate)->es_range_table_array)->updatedCols)
/* Local function prototypes */
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index c549e3db5d..33cadf8e34 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -3934,10 +3934,11 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
* perhaps other places.)
*/
if (econtext->ecxt_estate &&
- variable->varno <= list_length(econtext->ecxt_estate->es_range_table))
+ variable->varno <= econtext->ecxt_estate->es_range_table_size)
{
- RangeTblEntry *rte = rt_fetch(variable->varno,
- econtext->ecxt_estate->es_range_table);
+ RangeTblEntry *rte =
+ exec_rt_fetch(variable->varno,
+ econtext->ecxt_estate->es_range_table_array);
if (rte->eref)
ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 4ec47ac41e..d5227ae129 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -109,9 +109,9 @@ static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
* to be changed, however.
*/
#define GetInsertedColumns(relinfo, estate) \
- (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)
+ (exec_rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table_array)->insertedCols)
#define GetUpdatedColumns(relinfo, estate) \
- (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
+ (exec_rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table_array)->updatedCols)
/* end of local decls */
@@ -823,7 +823,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
/*
* initialize the node's execution state
*/
- estate->es_range_table = rangeTable;
+ ExecInitRangeTable(estate, rangeTable);
/*
* Allocate an array to store open Relations of each rangeTable item. We
@@ -918,9 +918,10 @@ InitPlan(QueryDesc *queryDesc, int eflags)
resultRelIndex))
{
Relation resultRelDesc;
+ Oid reloid = getrelid(resultRelIndex,
+ estate->es_range_table_array);
- resultRelDesc = heap_open(getrelid(resultRelIndex, rangeTable),
- NoLock);
+ resultRelDesc = heap_open(reloid, NoLock);
Assert(CheckRelationLockedByMe(resultRelDesc, RowExclusiveLock, true));
heap_close(resultRelDesc, NoLock);
}
@@ -962,7 +963,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
continue;
/* get relation's OID (will produce InvalidOid if subquery) */
- relid = getrelid(rc->rti, rangeTable);
+ relid = getrelid(rc->rti, estate->es_range_table_array);
switch (rc->markType)
{
@@ -3072,7 +3073,7 @@ EvalPlanQualBegin(EPQState *epqstate, EState *parentestate)
/*
* We already have a suitable child EPQ tree, so just reset it.
*/
- int rtsize = list_length(parentestate->es_range_table);
+ int rtsize = parentestate->es_range_table_size;
PlanState *planstate = epqstate->planstate;
MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
@@ -3125,7 +3126,7 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
MemoryContext oldcontext;
ListCell *l;
- rtsize = list_length(parentestate->es_range_table);
+ rtsize = parentestate->es_range_table_size;
epqstate->estate = estate = CreateExecutorState();
@@ -3149,6 +3150,8 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
estate->es_snapshot = parentestate->es_snapshot;
estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
estate->es_range_table = parentestate->es_range_table;
+ estate->es_range_table_array = parentestate->es_range_table_array;
+ estate->es_range_table_size = parentestate->es_range_table_size;
estate->es_relations = parentestate->es_relations;
estate->es_plannedstmt = parentestate->es_plannedstmt;
estate->es_junkFilter = parentestate->es_junkFilter;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 4825756a32..2ff36ef364 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -34,6 +34,8 @@
* GetAttributeByName Runtime extraction of columns from tuples.
* GetAttributeByNum
*
+ * ExecInitRangeTable Build an array from the range table list to
+ * allow faster lookups by relid.
* NOTES
* This file has traditionally been the place to stick misc.
* executor support stuff that doesn't really go anyplace else.
@@ -837,7 +839,7 @@ ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
ListCell *l;
Index rti = lfirst_int(lc);
bool is_result_rel = false;
- Oid relid = getrelid(rti, estate->es_range_table);
+ Oid relid = getrelid(rti, estate->es_range_table_array);
/* If this is a result relation, already locked in InitPlan */
foreach(l, stmt->nonleafResultRelations)
@@ -1031,6 +1033,26 @@ ExecCleanTargetListLength(List *targetlist)
}
/*
+ * Initialize executor's range table array
+ */
+void
+ExecInitRangeTable(EState *estate, List *rangeTable)
+{
+ int rti;
+ ListCell *l;
+
+ Assert(estate != NULL);
+ estate->es_range_table = rangeTable;
+ estate->es_range_table_size = list_length(rangeTable);
+ estate->es_range_table_array = (RangeTblEntry **)
+ palloc(estate->es_range_table_size *
+ sizeof(RangeTblEntry *));
+ rti = 0;
+ foreach(l, rangeTable)
+ estate->es_range_table_array[rti++] = lfirst_node(RangeTblEntry, l);
+}
+
+/*
* ExecRangeTableRelation
* Open and lock, if not already done, a range table relation
*/
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index 30de8a95ab..6db345ae7a 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -400,7 +400,7 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
/*
* Create workspace in which we can remember per-RTE locked tuples
*/
- lrstate->lr_ntables = list_length(estate->es_range_table);
+ lrstate->lr_ntables = estate->es_range_table_size;
lrstate->lr_curtuples = (HeapTuple *)
palloc0(lrstate->lr_ntables * sizeof(HeapTuple));
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index e247539d7b..b54e427be4 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -201,6 +201,8 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
rte->relkind = rel->localrel->rd_rel->relkind;
rte->rellockmode = AccessShareLock;
estate->es_range_table = list_make1(rte);
+ estate->es_range_table_array = &rte;
+ estate->es_range_table_size = 1;
resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index f3df6408a9..fdfd48d897 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -478,6 +478,7 @@ extern ExprContext *CreateExprContext(EState *estate);
extern ExprContext *CreateStandaloneExprContext(void);
extern void FreeExprContext(ExprContext *econtext, bool isCommit);
extern void ReScanExprContext(ExprContext *econtext);
+extern void ExecInitRangeTable(EState *estate, List *rangeTable);
#define ResetExprContext(econtext) \
MemoryContextReset((econtext)->ecxt_per_tuple_memory)
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7c47967494..fcdb7118a6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -20,6 +20,7 @@
#include "executor/instrument.h"
#include "lib/pairingheap.h"
#include "nodes/params.h"
+#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "utils/hsearch.h"
#include "utils/queryenvironment.h"
@@ -479,6 +480,8 @@ typedef struct EState
Snapshot es_snapshot; /* time qual to use */
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
List *es_range_table; /* List of RangeTblEntry */
+ struct RangeTblEntry **es_range_table_array; /* 0-based range table */
+ int es_range_table_size; /* size of the range table array */
Relation *es_relations; /* 0-based array of Relations
* es_range_table_size elements in length. */
PlannedStmt *es_plannedstmt; /* link to top of plan tree */
@@ -581,6 +584,22 @@ typedef struct EState
struct JitInstrumentation *es_jit_worker_instr;
} EState;
+/*
+ * exec_rt_fetch
+ *
+ * NB: this will crash and burn if handed an out-of-range RT index
+ */
+#define exec_rt_fetch(rangetblidx, rangetbl) rangetbl[(rangetblidx) - 1]
+
+/*
+ * getrelid
+ *
+ * Given the range index of a relation, return the corresponding
+ * relation OID. Note that InvalidOid will be returned if the
+ * RTE is for a non-relation-type RTE.
+ */
+#define getrelid(rangeindex,rangetable) \
+ (exec_rt_fetch(rangeindex, rangetable)->relid)
/*
* ExecRowMark -
diff --git a/src/include/parser/parsetree.h b/src/include/parser/parsetree.h
index dd9ae658ac..fe16d7d1fa 100644
--- a/src/include/parser/parsetree.h
+++ b/src/include/parser/parsetree.h
@@ -32,16 +32,6 @@
((RangeTblEntry *) list_nth(rangetable, (rangetable_index)-1))
/*
- * getrelid
- *
- * Given the range index of a relation, return the corresponding
- * relation OID. Note that InvalidOid will be returned if the
- * RTE is for a non-relation-type RTE.
- */
-#define getrelid(rangeindex,rangetable) \
- (rt_fetch(rangeindex, rangetable)->relid)
-
-/*
* Given an RTE and an attribute number, return the appropriate
* variable name or alias for that attribute of that RTE.
*/
--
2.11.0