diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c index 2a1f983..130e15f 100644 --- a/src/backend/replication/logical/proto.c +++ b/src/backend/replication/logical/proto.c @@ -668,8 +668,7 @@ logicalrep_write_attrs(StringInfo out, Relation rel) /* fetch bitmap of REPLICATION IDENTITY attributes */ replidentfull = (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL); if (!replidentfull) - idattrs = RelationGetIndexAttrBitmap(rel, - INDEX_ATTR_BITMAP_IDENTITY_KEY); + idattrs = RelationSetIdentityKeyBitmap(rel); /* send the attributes */ for (i = 0; i < desc->natts; i++) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 29702d6..218ab91 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -5206,6 +5206,104 @@ restart: } } +Bitmapset * +RelationSetIdentityKeyBitmap(Relation relation) +{ + Bitmapset *idindexattrs; /* columns in the replica identity */ + List *indexoidlist; + List *newindexoidlist; + Oid relpkindex; + Oid relreplindex; + ListCell *l; + MemoryContext oldcxt; + + /* Quick exit if we already computed the result. */ + if (relation->rd_idattr != NULL) + return bms_copy(relation->rd_idattr); + + /* Fast path if definitely no indexes */ + if (!RelationGetForm(relation)->relhasindex) + return NULL; + + /* + * Get cached list of index OIDs. If we have to start over, we do so here. + */ +restart: + indexoidlist = RelationGetIndexList(relation); + + /* Fall out if no indexes (but relhasindex was set) */ + if (indexoidlist == NIL) + return NULL; + + /* Save some values to compare after building attributes */ + relpkindex = relation->rd_pkindex; + relreplindex = relation->rd_replidindex; + + /* + * build attributes to idindexattrs. + */ + idindexattrs = NULL; + foreach(l, indexoidlist) + { + Oid indexOid = lfirst_oid(l); + Relation indexDesc; + int i; + bool isIDKey; /* replica identity index */ + + indexDesc = RelationIdGetRelation(indexOid); + + /* Is this index the configured (or default) replica identity? */ + isIDKey = (indexOid == relreplindex); + + /* Collect simple attribute references */ + for (i = 0; i < indexDesc->rd_index->indnatts; i++) + { + int attrnum = indexDesc->rd_index->indkey.values[i]; + + /* Romove non-key columns here. */ + if (attrnum != 0) + { + if (isIDKey && i < indexDesc->rd_index->indnkeyatts) + idindexattrs = bms_add_member(idindexattrs, + attrnum - FirstLowInvalidHeapAttributeNumber); + } + } + RelationClose(indexDesc); + } + + /* Check if we need to redo */ + newindexoidlist = RelationGetIndexList(relation); + if (equal(indexoidlist, newindexoidlist) && + relpkindex == relation->rd_pkindex && + relreplindex == relation->rd_replidindex) + { + /* Still the same index set, so proceed */ + list_free(newindexoidlist); + list_free(indexoidlist); + } + else + { + /* Gotta do it over ... might as well not leak memory */ + list_free(newindexoidlist); + list_free(indexoidlist); + bms_free(idindexattrs); + + goto restart; + } + + /* Don't leak the old values of these bitmaps, if any */ + bms_free(relation->rd_idattr); + relation->rd_idattr = NULL; + + /* Now save copies of the bitmaps in the relcache entry */ + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + relation->rd_idattr = bms_copy(idindexattrs); + MemoryContextSwitchTo(oldcxt); + + /* We return our original working copy for caller to play with */ + return idindexattrs; +} + /* * RelationGetExclusionInfo -- get info about index's exclusion constraint * diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 2fcdf79..de49ecc 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -65,6 +65,8 @@ typedef enum IndexAttrBitmapKind extern Bitmapset *RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind); +extern Bitmapset *RelationSetIdentityKeyBitmap(Relation relation); + extern void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs,