diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index 70c7ef6603..2b3dd1c677 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -1031,7 +1031,7 @@ Datum gin_clean_pending_list(PG_FUNCTION_ARGS) { Oid indexoid = PG_GETARG_OID(0); - Relation indexRel = index_open(indexoid, AccessShareLock); + Relation indexRel = index_open(indexoid, RowExclusiveLock); IndexBulkDeleteResult stats; GinState ginstate; @@ -1068,7 +1068,7 @@ gin_clean_pending_list(PG_FUNCTION_ARGS) initGinState(&ginstate, indexRel); ginInsertCleanup(&ginstate, true, true, true, &stats); - index_close(indexRel, AccessShareLock); + index_close(indexRel, RowExclusiveLock); PG_RETURN_INT64((int64) stats.pages_deleted); } diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 3b23de9fac..2835a01e15 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 + * because FDWs may wish to use it to determine if their foreign table + * is a target relation. * ---------------------------------------------------------------- */ 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..e2cdc83613 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); + /* Rels are assumed 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..3301331304 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -162,8 +162,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (hasindex) { List *indexoidlist; - ListCell *l; LOCKMODE lmode; + ListCell *l; indexoidlist = RelationGetIndexList(relation); @@ -172,13 +172,10 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, * 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. + * index while we hold lock on the parent rel, and no lock type used + * for queries blocks any other kind of index operation. */ - if (rel->relid == root->parse->resultRelation) - lmode = RowExclusiveLock; - else - lmode = AccessShareLock; + lmode = root->simple_rte_array[varno]->rellockmode; foreach(l, indexoidlist) { @@ -592,8 +589,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 +617,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 @@ -687,15 +683,14 @@ infer_arbiter_indexes(PlannerInfo *root) ListCell *el; /* - * Extract info from the relation descriptor for the index. We know - * that this is a target, so get lock type it is known will ultimately - * be required by the executor. + * Extract info from the relation descriptor for the index. Obtain + * the same lock type that the executor will ultimately use. * * Let executor complain about !indimmediate case directly, because * enforcement needs to occur there anyway when an inference clause is * omitted. */ - idxRel = index_open(indexoid, 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 ecffffbd0c..b419913155 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -5187,11 +5187,10 @@ 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 some type of lock on each. */ 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 +5304,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 +6471,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 plancat.c */ + indexRel = index_open(index->indexoid, NoLock); ginGetStats(indexRel, &ginStats); - index_close(indexRel, AccessShareLock); + index_close(indexRel, NoLock); } else { @@ -6781,11 +6781,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 in plancat.c. */ - 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