diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 64 |
1 files changed, 22 insertions, 42 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 7c697a285bd..1293545947e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -15773,7 +15773,10 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) * relation_mark_replica_identity: Update a table's replica identity * * Iff ri_type = REPLICA_IDENTITY_INDEX, indexOid must be the Oid of a suitable - * index. Otherwise, it should be InvalidOid. + * index. Otherwise, it must be InvalidOid. + * + * Caller had better hold an exclusive lock on the relation, as the results + * of running two of these concurrently wouldn't be pretty. */ static void relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, @@ -15785,7 +15788,6 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, HeapTuple pg_index_tuple; Form_pg_class pg_class_form; Form_pg_index pg_index_form; - ListCell *index; /* @@ -15807,29 +15809,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, heap_freetuple(pg_class_tuple); /* - * Check whether the correct index is marked indisreplident; if so, we're - * done. - */ - if (OidIsValid(indexOid)) - { - Assert(ri_type == REPLICA_IDENTITY_INDEX); - - pg_index_tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexOid)); - if (!HeapTupleIsValid(pg_index_tuple)) - elog(ERROR, "cache lookup failed for index %u", indexOid); - pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple); - - if (pg_index_form->indisreplident) - { - ReleaseSysCache(pg_index_tuple); - return; - } - ReleaseSysCache(pg_index_tuple); - } - - /* - * Clear the indisreplident flag from any index that had it previously, - * and set it for any index that should have it now. + * Update the per-index indisreplident flags correctly. */ pg_index = table_open(IndexRelationId, RowExclusiveLock); foreach(index, RelationGetIndexList(rel)) @@ -15843,19 +15823,23 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, elog(ERROR, "cache lookup failed for index %u", thisIndexOid); pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple); - /* - * Unset the bit if set. We know it's wrong because we checked this - * earlier. - */ - if (pg_index_form->indisreplident) + if (thisIndexOid == indexOid) { - dirty = true; - pg_index_form->indisreplident = false; + /* Set the bit if not already set. */ + if (!pg_index_form->indisreplident) + { + dirty = true; + pg_index_form->indisreplident = true; + } } - else if (thisIndexOid == indexOid) + else { - dirty = true; - pg_index_form->indisreplident = true; + /* Unset the bit if set. */ + if (pg_index_form->indisreplident) + { + dirty = true; + pg_index_form->indisreplident = false; + } } if (dirty) @@ -15867,7 +15851,9 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, /* * Invalidate the relcache for the table, so that after we commit * all sessions will refresh the table's replica identity index - * before attempting any UPDATE or DELETE on the table. + * before attempting any UPDATE or DELETE on the table. (If we + * changed the table's pg_class row above, then a relcache inval + * is already queued due to that; but we might not have.) */ CacheInvalidateRelcache(rel); } @@ -15952,12 +15938,6 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot use partial index \"%s\" as replica identity", RelationGetRelationName(indexRel)))); - /* And neither are invalid indexes. */ - if (!indexRel->rd_index->indisvalid) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot use invalid index \"%s\" as replica identity", - RelationGetRelationName(indexRel)))); /* Check index for nullable columns. */ for (key = 0; key < IndexRelationGetNumberOfKeyAttributes(indexRel); key++) |