diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c index edc97a7662..06fa5c5647 100644 --- a/src/backend/replication/logical/proto.c +++ b/src/backend/replication/logical/proto.c @@ -582,8 +582,47 @@ 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); + { + Oid idindex = rel->rd_replidindex; + + /* + * Building the index list determines the replica index OID as a side + * effect, so do so now unless we already have it. + */ + if (rel->rd_replidindex == InvalidOid) + { + list_free(RelationGetIndexList(rel)); + idindex = rel->rd_replidindex; + } + + /* + * Now build the bitmap. We cannot use RelationGetIndexAttrBitmap + * here: it would try to build IndexInfo for all the relation's + * indexes, which would be a problem, as the right authorization + * environment for that has not been set up yet (a problem + * particularly if there are any SQL-language functions.) + * + * It would be nice to cache this somewhere, but it's not clear how to + * invalidate it when the time comes. + */ + if (OidIsValid(idindex)) + { + HeapTuple tuple; + Form_pg_index index; + int natts; + + tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(idindex)); + if (!tuple) + elog(ERROR, "cache lookup failed for index %u", idindex); + index = (Form_pg_index) GETSTRUCT(tuple); + natts = index->indnkeyatts; + + for (i = 0; i < natts; i++) + idattrs = bms_add_member(idattrs, index->indkey.values[i] - + FirstLowInvalidHeapAttributeNumber); + ReleaseSysCache(tuple); + } + } /* send the attributes */ for (i = 0; i < desc->natts; i++)