replfieldtype.patch

text/plain

Filename: replfieldtype.patch
Type: text/plain
Part: 0
Message: Re: Restore replication settings when modifying a field type

Patch

Format: unified
File+
src/backend/commands/tablecmds.c 56 4
src/backend/utils/cache/lsyscache.c 18 0
src/include/utils/lsyscache.h 1 0
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 */