use_rellockmode_for_indexes_too_v3.patch
application/octet-stream
Filename: use_rellockmode_for_indexes_too_v3.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/executor/execUtils.c | 4 | 0 |
| src/backend/executor/nodeBitmapIndexscan.c | 4 | 11 |
| src/backend/executor/nodeIndexonlyscan.c | 4 | 11 |
| src/backend/executor/nodeIndexscan.c | 4 | 11 |
| src/backend/optimizer/plan/planner.c | 1 | 0 |
| src/backend/optimizer/util/plancat.c | 8 | 20 |
| src/backend/utils/adt/selfuncs.c | 11 | 9 |
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 3b23de9..0deaf8f 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -664,6 +664,10 @@ ExecCreateScanSlotFromOuterPlan(EState *estate,
*
* Detect whether a relation (identified by rangetable index)
* is one of the target relations of the query.
+ *
+ * Note: This is currently no longer used in core. We keep it
+ * around to allow FDWs to use it in order to determine if the foreign
+ * table is the target of an UPDATE/DELETE.
* ----------------------------------------------------------------
*/
bool
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index bd837d3..604f4f1 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -211,7 +211,7 @@ BitmapIndexScanState *
ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
{
BitmapIndexScanState *indexstate;
- bool relistarget;
+ LOCKMODE lockmode;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -260,16 +260,9 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
return indexstate;
- /*
- * Open the index relation.
- *
- * If the parent table is one of the target relations of the query, then
- * InitPlan already opened and write-locked the index, so we can avoid
- * taking another lock here. Otherwise we need a normal reader's lock.
- */
- relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
- indexstate->biss_RelationDesc = index_open(node->indexid,
- relistarget ? NoLock : AccessShareLock);
+ /* Open the index relation. */
+ lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
+ indexstate->biss_RelationDesc = index_open(node->indexid, lockmode);
/*
* Initialize index-specific scan state
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 2d954b7..7711728 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -493,7 +493,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
{
IndexOnlyScanState *indexstate;
Relation currentRelation;
- bool relistarget;
+ LOCKMODE lockmode;
TupleDesc tupDesc;
/*
@@ -556,16 +556,9 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
return indexstate;
- /*
- * Open the index relation.
- *
- * If the parent table is one of the target relations of the query, then
- * InitPlan already opened and write-locked the index, so we can avoid
- * taking another lock here. Otherwise we need a normal reader's lock.
- */
- relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
- indexstate->ioss_RelationDesc = index_open(node->indexid,
- relistarget ? NoLock : AccessShareLock);
+ /* Open the index relation. */
+ lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
+ indexstate->ioss_RelationDesc = index_open(node->indexid, lockmode);
/*
* Initialize index-specific scan state
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8f39cc2..399ac01 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -901,7 +901,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
{
IndexScanState *indexstate;
Relation currentRelation;
- bool relistarget;
+ LOCKMODE lockmode;
/*
* create state structure
@@ -964,16 +964,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
return indexstate;
- /*
- * Open the index relation.
- *
- * If the parent table is one of the target relations of the query, then
- * InitPlan already opened and write-locked the index, so we can avoid
- * taking another lock here. Otherwise we need a normal reader's lock.
- */
- relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
- indexstate->iss_RelationDesc = index_open(node->indexid,
- relistarget ? NoLock : AccessShareLock);
+ /* Open the index relation. */
+ lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
+ indexstate->iss_RelationDesc = index_open(node->indexid, lockmode);
/*
* Initialize index-specific scan state
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index c430189..15fe132 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6285,6 +6285,7 @@ plan_create_index_workers(Oid tableOid, Oid indexOid)
/* Build RelOptInfo */
rel = build_simple_rel(root, 1, NULL);
+ /* Already locked by the caller */
heap = table_open(tableOid, NoLock);
index = index_open(indexOid, NoLock);
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 31a3784..c01dbb8 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -161,25 +161,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
if (hasindex)
{
+ RangeTblEntry *rte;
List *indexoidlist;
ListCell *l;
- LOCKMODE lmode;
+ rte = root->simple_rte_array[varno];
indexoidlist = RelationGetIndexList(relation);
- /*
- * For each index, we get the same type of lock that the executor will
- * need, and do not release it. This saves a couple of trips to the
- * shared lock manager while not creating any real loss of
- * concurrency, because no schema changes could be happening on the
- * index while we hold lock on the parent rel, and neither lock type
- * blocks any other kind of index operation.
- */
- if (rel->relid == root->parse->resultRelation)
- lmode = RowExclusiveLock;
- else
- lmode = AccessShareLock;
-
foreach(l, indexoidlist)
{
Oid indexoid = lfirst_oid(l);
@@ -194,7 +182,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
/*
* Extract info from the relation descriptor for the index.
*/
- indexRelation = index_open(indexoid, lmode);
+ indexRelation = index_open(indexoid, rte->rellockmode);
index = indexRelation->rd_index;
/*
@@ -592,8 +580,8 @@ infer_arbiter_indexes(PlannerInfo *root)
OnConflictExpr *onconflict = root->parse->onConflict;
/* Iteration state */
+ RangeTblEntry *rte;
Relation relation;
- Oid relationObjectId;
Oid indexOidFromConstraint = InvalidOid;
List *indexList;
ListCell *l;
@@ -620,10 +608,9 @@ infer_arbiter_indexes(PlannerInfo *root)
* the rewriter or when expand_inherited_rtentry() added it to the query's
* rangetable.
*/
- relationObjectId = rt_fetch(root->parse->resultRelation,
- root->parse->rtable)->relid;
+ rte = rt_fetch(root->parse->resultRelation, root->parse->rtable);
- relation = table_open(relationObjectId, NoLock);
+ relation = table_open(rte->relid, NoLock);
/*
* Build normalized/BMS representation of plain indexed attributes, as
@@ -695,7 +682,8 @@ infer_arbiter_indexes(PlannerInfo *root)
* enforcement needs to occur there anyway when an inference clause is
* omitted.
*/
- idxRel = index_open(indexoid, RowExclusiveLock);
+ Assert(rte->rellockmode >= RowExclusiveLock);
+ idxRel = index_open(indexoid, rte->rellockmode);
idxForm = idxRel->rd_index;
if (!idxForm->indisvalid)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index ecffffb..23bfb71 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5187,11 +5187,11 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
/*
* Open the table and index so we can read from them. We should
- * already have at least AccessShareLock on the table, but not
- * necessarily on the index.
+ * already have at least AccessShareLock on the table. The index
+ * should have been locked in get_relation_info.
*/
heapRel = table_open(rte->relid, NoLock);
- indexRel = index_open(index->indexoid, AccessShareLock);
+ indexRel = index_open(index->indexoid, NoLock);
/* extract index key information from the index's pg_index info */
indexInfo = BuildIndexInfo(indexRel);
@@ -5305,7 +5305,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
/* Clean everything up */
ExecDropSingleTupleTableSlot(slot);
- index_close(indexRel, AccessShareLock);
+ index_close(indexRel, NoLock);
table_close(heapRel, NoLock);
MemoryContextSwitchTo(oldcontext);
@@ -6472,9 +6472,10 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
*/
if (!index->hypothetical)
{
- indexRel = index_open(index->indexoid, AccessShareLock);
+ /* Lock should have already been obtained in get_relation_info */
+ indexRel = index_open(index->indexoid, NoLock);
ginGetStats(indexRel, &ginStats);
- index_close(indexRel, AccessShareLock);
+ index_close(indexRel, NoLock);
}
else
{
@@ -6781,11 +6782,12 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
&spc_seq_page_cost);
/*
- * Obtain some data from the index itself.
+ * Obtain some data from the index itself. A lock should have already
+ * been obtained on the index during get_relation_info.
*/
- indexRel = index_open(index->indexoid, AccessShareLock);
+ indexRel = index_open(index->indexoid, NoLock);
brinGetStats(indexRel, &statsData);
- index_close(indexRel, AccessShareLock);
+ index_close(indexRel, NoLock);
/*
* Compute index correlation