use_rellockmode_for_indexes_too.patch
application/octet-stream
Filename: use_rellockmode_for_indexes_too.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| 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 | 3 | 15 |
| src/backend/utils/adt/selfuncs.c | 24 | 7 |
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 3b23de9fac..0deaf8f1b7 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 bd837d3cd8..604f4f1132 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 2d954b722a..7711728495 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 8f39cc2b6b..399ac0109c 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 c430189572..15fe132ead 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 31a3784536..e134dd0d06 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;
/*
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index ecffffbd0c..39e1eca47c 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5191,7 +5191,14 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
* necessarily on the index.
*/
heapRel = table_open(rte->relid, NoLock);
- indexRel = index_open(index->indexoid, AccessShareLock);
+
+ /*
+ * We use the same lock level as the relation as it may have
+ * already been locked with that level. Using the same lock level
+ * can save a trip to the shared lock manager.
+ */
+ Assert(rte->rellockmode != NoLock);
+ indexRel = index_open(index->indexoid, rte->rellockmode);
/* extract index key information from the index's pg_index info */
indexInfo = BuildIndexInfo(indexRel);
@@ -5305,7 +5312,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);
@@ -6444,6 +6451,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double *indexPages)
{
IndexOptInfo *index = path->indexinfo;
+ RangeTblEntry *rte = root->simple_rte_array[path->path.parent->relid];
List *indexQuals = get_quals_from_indexclauses(path->indexclauses);
List *selectivityQuals;
double numPages = index->pages,
@@ -6472,9 +6480,15 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
*/
if (!index->hypothetical)
{
- indexRel = index_open(index->indexoid, AccessShareLock);
+ /*
+ * We use the same lock level as the relation as it may have already
+ * been locked with that level. Using the same lock level can save a
+ * trip to the shared lock manager.
+ */
+ Assert(rte->rellockmode != NoLock);
+ indexRel = index_open(index->indexoid, rte->rellockmode);
ginGetStats(indexRel, &ginStats);
- index_close(indexRel, AccessShareLock);
+ index_close(indexRel, NoLock);
}
else
{
@@ -6781,11 +6795,14 @@ 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. We use the same lock level as
+ * the relation as it may have already been locked with that level. Using
+ * the same lock level can save a trip to the shared lock manager.
*/
- indexRel = index_open(index->indexoid, AccessShareLock);
+ Assert(rte->rellockmode != NoLock);
+ indexRel = index_open(index->indexoid, rte->rellockmode);
brinGetStats(indexRel, &statsData);
- index_close(indexRel, AccessShareLock);
+ index_close(indexRel, NoLock);
/*
* Compute index correlation