aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execCurrent.c11
-rw-r--r--src/backend/executor/execMain.c116
-rw-r--r--src/backend/executor/execUtils.c9
3 files changed, 74 insertions, 62 deletions
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index 7480cf50ad0..aadf7493827 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -91,21 +91,22 @@ execCurrentOf(CurrentOfExpr *cexpr,
* the other code can't, while the non-FOR-UPDATE case allows use of WHERE
* CURRENT OF with an insensitive cursor.
*/
- if (queryDesc->estate->es_rowMarks)
+ if (queryDesc->estate->es_rowmarks)
{
ExecRowMark *erm;
- ListCell *lc;
+ Index i;
/*
* Here, the query must have exactly one FOR UPDATE/SHARE reference to
* the target table, and we dig the ctid info out of that.
*/
erm = NULL;
- foreach(lc, queryDesc->estate->es_rowMarks)
+ for (i = 0; i < queryDesc->estate->es_range_table_size; i++)
{
- ExecRowMark *thiserm = (ExecRowMark *) lfirst(lc);
+ ExecRowMark *thiserm = queryDesc->estate->es_rowmarks[i];
- if (!RowMarkRequiresRowShareLock(thiserm->markType))
+ if (thiserm == NULL ||
+ !RowMarkRequiresRowShareLock(thiserm->markType))
continue; /* ignore non-FOR UPDATE/SHARE items */
if (thiserm->relid == table_oid)
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index b6abad554a4..0a766ef1e5a 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -909,61 +909,68 @@ InitPlan(QueryDesc *queryDesc, int eflags)
}
/*
- * Next, build the ExecRowMark list from the PlanRowMark(s), if any.
+ * Next, build the ExecRowMark array from the PlanRowMark(s), if any.
*/
- estate->es_rowMarks = NIL;
- foreach(l, plannedstmt->rowMarks)
+ if (plannedstmt->rowMarks)
{
- PlanRowMark *rc = (PlanRowMark *) lfirst(l);
- Oid relid;
- Relation relation;
- ExecRowMark *erm;
+ estate->es_rowmarks = (ExecRowMark **)
+ palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
+ foreach(l, plannedstmt->rowMarks)
+ {
+ PlanRowMark *rc = (PlanRowMark *) lfirst(l);
+ Oid relid;
+ Relation relation;
+ ExecRowMark *erm;
- /* ignore "parent" rowmarks; they are irrelevant at runtime */
- if (rc->isParent)
- continue;
+ /* ignore "parent" rowmarks; they are irrelevant at runtime */
+ if (rc->isParent)
+ continue;
- /* get relation's OID (will produce InvalidOid if subquery) */
- relid = exec_rt_fetch(rc->rti, estate)->relid;
+ /* get relation's OID (will produce InvalidOid if subquery) */
+ relid = exec_rt_fetch(rc->rti, estate)->relid;
- /* open relation, if we need to access it for this mark type */
- switch (rc->markType)
- {
- case ROW_MARK_EXCLUSIVE:
- case ROW_MARK_NOKEYEXCLUSIVE:
- case ROW_MARK_SHARE:
- case ROW_MARK_KEYSHARE:
- case ROW_MARK_REFERENCE:
- relation = ExecGetRangeTableRelation(estate, rc->rti);
- break;
- case ROW_MARK_COPY:
- /* no physical table access is required */
- relation = NULL;
- break;
- default:
- elog(ERROR, "unrecognized markType: %d", rc->markType);
- relation = NULL; /* keep compiler quiet */
- break;
- }
+ /* open relation, if we need to access it for this mark type */
+ switch (rc->markType)
+ {
+ case ROW_MARK_EXCLUSIVE:
+ case ROW_MARK_NOKEYEXCLUSIVE:
+ case ROW_MARK_SHARE:
+ case ROW_MARK_KEYSHARE:
+ case ROW_MARK_REFERENCE:
+ relation = ExecGetRangeTableRelation(estate, rc->rti);
+ break;
+ case ROW_MARK_COPY:
+ /* no physical table access is required */
+ relation = NULL;
+ break;
+ default:
+ elog(ERROR, "unrecognized markType: %d", rc->markType);
+ relation = NULL; /* keep compiler quiet */
+ break;
+ }
- /* Check that relation is a legal target for marking */
- if (relation)
- CheckValidRowMarkRel(relation, rc->markType);
-
- erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
- erm->relation = relation;
- erm->relid = relid;
- erm->rti = rc->rti;
- erm->prti = rc->prti;
- erm->rowmarkId = rc->rowmarkId;
- erm->markType = rc->markType;
- erm->strength = rc->strength;
- erm->waitPolicy = rc->waitPolicy;
- erm->ermActive = false;
- ItemPointerSetInvalid(&(erm->curCtid));
- erm->ermExtra = NULL;
-
- estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
+ /* Check that relation is a legal target for marking */
+ if (relation)
+ CheckValidRowMarkRel(relation, rc->markType);
+
+ erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
+ erm->relation = relation;
+ erm->relid = relid;
+ erm->rti = rc->rti;
+ erm->prti = rc->prti;
+ erm->rowmarkId = rc->rowmarkId;
+ erm->markType = rc->markType;
+ erm->strength = rc->strength;
+ erm->waitPolicy = rc->waitPolicy;
+ erm->ermActive = false;
+ ItemPointerSetInvalid(&(erm->curCtid));
+ erm->ermExtra = NULL;
+
+ Assert(erm->rti > 0 && erm->rti <= estate->es_range_table_size &&
+ estate->es_rowmarks[erm->rti - 1] == NULL);
+
+ estate->es_rowmarks[erm->rti - 1] = erm;
+ }
}
/*
@@ -2394,13 +2401,12 @@ ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
ExecRowMark *
ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
{
- ListCell *lc;
-
- foreach(lc, estate->es_rowMarks)
+ if (rti > 0 && rti <= estate->es_range_table_size &&
+ estate->es_rowmarks != NULL)
{
- ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
+ ExecRowMark *erm = estate->es_rowmarks[rti - 1];
- if (erm->rti == rti)
+ if (erm)
return erm;
}
if (!missing_ok)
@@ -3131,6 +3137,7 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
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_rowmarks = parentestate->es_rowmarks;
estate->es_plannedstmt = parentestate->es_plannedstmt;
estate->es_junkFilter = parentestate->es_junkFilter;
estate->es_output_cid = parentestate->es_output_cid;
@@ -3148,7 +3155,6 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
}
/* es_result_relation_info must NOT be copied */
/* es_trig_target_relations must NOT be copied */
- estate->es_rowMarks = parentestate->es_rowMarks;
estate->es_top_eflags = parentestate->es_top_eflags;
estate->es_instrument = parentestate->es_instrument;
/* es_auxmodifytables must NOT be copied */
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index d98e90e7117..71c6b5dc0a8 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -113,6 +113,7 @@ CreateExecutorState(void)
estate->es_range_table_array = NULL;
estate->es_range_table_size = 0;
estate->es_relations = NULL;
+ estate->es_rowmarks = NULL;
estate->es_plannedstmt = NULL;
estate->es_junkFilter = NULL;
@@ -142,8 +143,6 @@ CreateExecutorState(void)
estate->es_tupleTable = NIL;
- estate->es_rowMarks = NIL;
-
estate->es_processed = 0;
estate->es_lastoid = InvalidOid;
@@ -709,6 +708,12 @@ ExecInitRangeTable(EState *estate, List *rangeTable)
*/
estate->es_relations = (Relation *)
palloc0(estate->es_range_table_size * sizeof(Relation));
+
+ /*
+ * es_rowmarks is also parallel to the es_range_table_array, but it's
+ * allocated only if needed.
+ */
+ estate->es_rowmarks = NULL;
}
/*