replidfieldtype.patch

text/plain

Filename: replidfieldtype.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 62 3
src/backend/utils/adt/ruleutils.c 38 0
src/include/utils/ruleutils.h 2 0
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 05593f3316..02f8dbeabf 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -174,6 +174,8 @@ typedef struct AlteredTableInfo
 	List	   *changedConstraintDefs;	/* string definitions of same */
 	List	   *changedIndexOids;	/* OIDs of indexes to rebuild */
 	List	   *changedIndexDefs;	/* string definitions of same */
+	Oid		   changedReplIdentOid;	/* OID of index to reset REPLICA IDENTIFY */
+	char	   *changedReplIdentDef;	/* string definitions of same */
 } AlteredTableInfo;
 
 /* Struct describing one new constraint to check in Phase 3 scan */
@@ -459,6 +461,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,
@@ -10715,6 +10718,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 					{
 						Assert(foundObject.objectSubId == 0);
 						RememberIndexForRebuilding(foundObject.objectId, tab);
+
+						if (RelationGetForm(rel)->relreplident==REPLICA_IDENTITY_INDEX)
+							RememberReplicaIdentForRebuilding(foundObject.objectId, tab);
 					}
 					else if (relKind == RELKIND_SEQUENCE)
 					{
@@ -10749,9 +10755,18 @@ 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))
+						RememberReplicaIdentForRebuilding(indId, tab);
+
+					break;
+				}
 
 			case OCLASS_REWRITE:
 				/* XXX someday see if we can cope with revising views */
@@ -11075,6 +11090,36 @@ 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	   *defstring;
+
+	/*
+	 * This de-duplication check is critical for two independent reasons: we
+	 * mustn't try to recreate the same constraint twice, and if a constraint
+	 * depends on more than one column whose type is to be altered, we must
+	 * capture its definition string before applying any of the column type
+	 * changes.  ruleutils.c will get confused if we ask again later.
+	 */
+	if (OidIsValid(tab->changedReplIdentOid))
+		return;
+
+	/* OK, capture the constraint's existing definition string */
+	defstring = pg_get_replidentdef_command(indoid);
+
+	/* not a replica identify */
+	if (defstring==NULL)
+		return;
+
+	tab->changedReplIdentOid = indoid;
+	tab->changedReplIdentDef = defstring;
+}
+
 /*
  * Subroutine for ATExecAlterColumnType: remember that an index needs
  * to be rebuilt (which we might already know).
@@ -11222,6 +11267,15 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
 		add_exact_object_address(&obj, objects);
 	}
 
+	if (OidIsValid(tab->changedReplIdentOid))
+	{
+		Oid relid = IndexGetRelation(tab->changedReplIdentOid, false);
+		ATPostAlterTypeParse(InvalidOid, relid, InvalidOid,
+							 tab->changedReplIdentDef,
+							 wqueue, lockmode, tab->rewrite);
+	}
+
+
 	/*
 	 * It should be okay to use DROP_RESTRICT here, since nothing else should
 	 * be depending on these objects.
@@ -11373,6 +11427,11 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
 											 NIL,
 											 con->conname);
 				}
+				else if (cmd->subtype == AT_ReplicaIdentity)
+				{
+					tab->subcmds[AT_PASS_MISC] =
+						lappend(tab->subcmds[AT_PASS_MISC], cmd);
+				}
 				else if (cmd->subtype == AT_SetNotNull)
 				{
 					/*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3e64390d81..c5efe93c0c 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1854,6 +1854,44 @@ pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
 	return deparse_expression((Node *) constr_expr, context, true, false);
 }
 
+/*
+ * pg_get_replidentdef_command
+ *
+ * Returns the definition for the REPLICA IDENTITY, ie, everything that needs to
+ * appear after "ALTER TABLE ... REPLICA IDENTITY USING INDEX <indexname>".
+ */
+char *pg_get_replidentdef_command(Oid indId)
+{
+	Oid			relId;
+	HeapTuple	ht_idx;
+	Form_pg_index idxrec;
+
+	StringInfoData buf;
+
+	ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indId));
+	if (!HeapTupleIsValid(ht_idx))
+		elog(ERROR, "cache lookup failed for index %u", indId);
+
+	idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
+	/* not a replica identify */
+	if (!idxrec->indisreplident)
+	{
+		ReleaseSysCache(ht_idx);
+		return NULL;
+	}
+	relId = idxrec->indrelid;
+	ReleaseSysCache(ht_idx);
+
+	initStringInfo(&buf);
+	appendStringInfoString(&buf, "ALTER TABLE ");
+
+	appendStringInfoString(&buf, generate_qualified_relation_name(relId));
+	appendStringInfoString(&buf, " REPLICA IDENTITY USING INDEX ");
+	appendStringInfoString(&buf, quote_identifier(get_rel_name(indId)));
+
+	return buf.data;
+}
+
 /*
  * pg_get_constraintdef
  *
diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h
index d34cad2f4b..71c3da1316 100644
--- a/src/include/utils/ruleutils.h
+++ b/src/include/utils/ruleutils.h
@@ -24,6 +24,8 @@ extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
 extern char *pg_get_partkeydef_columns(Oid relid, bool pretty);
 extern char *pg_get_partconstrdef_string(Oid partitionId, char *aliasname);
 
+extern char *pg_get_replidentdef_command(Oid indId);
+
 extern char *pg_get_constraintdef_command(Oid constraintId);
 extern char *deparse_expression(Node *expr, List *dpcontext,
 								bool forceprefix, bool showimplicit);