From 99c83aa75bbe3a8893fc4779629e08f927d55bf0 Mon Sep 17 00:00:00 2001 From: Zhijie Hou Date: Mon, 5 Oct 2026 14:44:40 +0800 Subject: [PATCH vTopup] Use computed index to check --- src/backend/replication/logical/relation.c | 54 ++++++++-------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index 8b173e379d0..05e1495c4bc 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -307,40 +307,24 @@ logicalrep_report_missing_or_gen_attrs(LogicalRepRelation *remoterel, static void logicalrep_rel_mark_updatable(LogicalRepRelMapEntry *entry) { - Bitmapset *idkey; LogicalRepRelation *remoterel = &entry->remoterel; - int i; + Relation idxrel; entry->updatable = true; - idkey = RelationGetIndexAttrBitmap(entry->localrel, - INDEX_ATTR_BITMAP_IDENTITY_KEY); - - /* - * Fall back to the PK if no replica identity, but only if the PK is not - * deferrable. INDEX_ATTR_BITMAP_PRIMARY_KEY includes the columns of a - * deferrable PK, but such a PK cannot serve as a replica identity (its - * uniqueness may be transiently violated), and FindLogicalRepLocalIndex() - * will not use it to look up tuples. - */ - if (idkey == NULL) + if (!entry->idxisreplident) { - if (OidIsValid(RelationGetPrimaryKeyIndex(entry->localrel, false))) - idkey = RelationGetIndexAttrBitmap(entry->localrel, - INDEX_ATTR_BITMAP_PRIMARY_KEY); - - /* - * If no replica identity index and no usable PK, the published table - * must have replica identity FULL. - */ - if (idkey == NULL && remoterel->replident != REPLICA_IDENTITY_FULL) + if (remoterel->replident != REPLICA_IDENTITY_FULL) entry->updatable = false; + + return; } - i = -1; - while ((i = bms_next_member(idkey, i)) >= 0) + idxrel = index_open(entry->localindexoid, AccessShareLock); + + for (int i = 0; i < idxrel->rd_index->indnkeyatts; i++) { - int attnum = i + FirstLowInvalidHeapAttributeNumber; + int attnum = idxrel->rd_index->indkey.values[i]; if (!AttrNumberIsForUserDefinedAttr(attnum)) ereport(ERROR, @@ -358,6 +342,8 @@ logicalrep_rel_mark_updatable(LogicalRepRelMapEntry *entry) break; } } + + index_close(idxrel, AccessShareLock); } /* @@ -492,12 +478,6 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) bms_free(generatedattrs); bms_free(missingatts); - /* - * Set if the table's replica identity is enough to apply - * update/delete. - */ - logicalrep_rel_mark_updatable(entry); - /* * Finding a usable index is an infrequent task. It occurs when an * operation is first performed on the relation, or after invalidation @@ -508,6 +488,12 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) entry->attrmap, &entry->idxisreplident); + /* + * Set if the table's replica identity is enough to apply + * update/delete. + */ + logicalrep_rel_mark_updatable(entry); + entry->localrelvalid = true; } @@ -757,9 +743,6 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root, attrmap->maplen * sizeof(AttrNumber)); } - /* Set if the table's replica identity is enough to apply update/delete. */ - logicalrep_rel_mark_updatable(entry); - /* state and statelsn are left set to 0. */ MemoryContextSwitchTo(oldctx); @@ -776,6 +759,9 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root, entry->attrmap, &entry->idxisreplident); + /* Set if the table's replica identity is enough to apply update/delete. */ + logicalrep_rel_mark_updatable(entry); + entry->localrelvalid = true; return entry; -- 2.34.1