diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b7c8d663fc..de4da64e06 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -176,6 +176,7 @@ typedef struct AlteredTableInfo List *changedConstraintDefs; /* string definitions of same */ List *changedIndexOids; /* OIDs of indexes to rebuild */ List *changedIndexDefs; /* string definitions of same */ + List *changedReplIdentName; /* fullname of index to reset REPLICA IDENTIFY */ } AlteredTableInfo; /* Struct describing one new constraint to check in Phase 3 scan */ @@ -482,6 +483,7 @@ static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd, LOCKMODE lockmode); static void RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab); static void RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab); +static void RememberReplicaIdentForRebuilding(Oid indoid, AlteredTableInfo *tab); static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode); static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, @@ -553,6 +555,7 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx, Relation partitionTbl); static List *GetParentedForeignKeyRefs(Relation partition); static void ATDetachCheckNoForeignKeyRefs(Relation partition); +static void relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, bool is_internal); /* ---------------------------------------------------------------- @@ -4274,7 +4277,10 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode, Relation rel; ListCell *lcmd; - if (subcmds == NIL) + if (subcmds == NIL && pass != AT_PASS_MISC) + continue; + if (subcmds == NIL && pass == AT_PASS_MISC && + tab->changedReplIdentName==NIL) continue; /* @@ -4295,6 +4301,18 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode, if (pass == AT_PASS_ALTER_TYPE) ATPostAlterTypeCleanup(wqueue, tab, lockmode); + if (pass == AT_PASS_MISC && tab->changedReplIdentName) + { + Relation idxrel; + ObjectAddress address = get_object_address(OBJECT_INDEX, + (Node*)tab->changedReplIdentName, &idxrel, + AccessExclusiveLock, false); + relation_close(idxrel, NoLock); + + relation_mark_replica_identity(rel, REPLICA_IDENTITY_INDEX, + address.objectId, true); + } + relation_close(rel, NoLock); } } @@ -11231,6 +11249,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, { Assert(foundObject.objectSubId == 0); RememberIndexForRebuilding(foundObject.objectId, tab); + if (RelationGetForm(rel)->relreplident==REPLICA_IDENTITY_INDEX && + index_is_replident(foundObject.objectId)) + RememberReplicaIdentForRebuilding(foundObject.objectId, tab); } else if (relKind == RELKIND_SEQUENCE) { @@ -11265,9 +11286,20 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, } case OCLASS_CONSTRAINT: - Assert(foundObject.objectSubId == 0); - RememberConstraintForRebuilding(foundObject.objectId, tab); - break; + { + Oid indId; + + Assert(foundObject.objectSubId == 0); + RememberConstraintForRebuilding(foundObject.objectId, tab); + + indId = get_constraint_index(foundObject.objectId); + if (OidIsValid(indId) && + RelationGetForm(rel)->relreplident==REPLICA_IDENTITY_INDEX && + index_is_replident(indId)) + RememberReplicaIdentForRebuilding(indId, tab); + + break; + } case OCLASS_REWRITE: /* XXX someday see if we can cope with revising views */ @@ -11590,6 +11622,26 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab) } } +/* + * Subroutine for ATExecAlterColumnType: remember that a replica identify + * needs to be reset (which we might already know). + */ +static void +RememberReplicaIdentForRebuilding(Oid indoid, AlteredTableInfo *tab) +{ + char *nspName; + char *relName; + + /* just in case */ + if (tab->changedReplIdentName) + return; + + relName = get_rel_name(indoid); + nspName = get_namespace_name(get_rel_namespace(indoid)); + + tab->changedReplIdentName = list_make2(makeString(nspName), makeString(relName)); +} + /* * Subroutine for ATExecAlterColumnType: remember that an index needs * to be rebuilt (which we might already know). diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index fb0599f7f1..d74c5a1427 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -3227,3 +3227,21 @@ get_index_column_opclass(Oid index_oid, int attno) return opclass; } + +bool +index_is_replident(Oid index_oid) +{ + HeapTuple tuple; + Form_pg_index rd_index; + bool result; + + tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid)); + if (!HeapTupleIsValid(tuple)) + return false; + + rd_index = (Form_pg_index) GETSTRUCT(tuple); + result = rd_index->indisreplident; + ReleaseSysCache(tuple); + + return result; +} diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 370f62a133..b91cb84b15 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -181,6 +181,7 @@ extern char *get_namespace_name_or_temp(Oid nspid); extern Oid get_range_subtype(Oid rangeOid); extern Oid get_range_collation(Oid rangeOid); extern Oid get_index_column_opclass(Oid index_oid, int attno); +extern bool index_is_replident(Oid index_oid); #define type_is_array(typid) (get_element_type(typid) != InvalidOid) /* type_is_array_domain accepts both plain arrays and domains over arrays */