wip-post-alter-type-cleanup-divide.patch

text/plain

Filename: wip-post-alter-type-cleanup-divide.patch
Type: text/plain
Part: 0
Message: Re: BUG #15672: PostgreSQL 11.1/11.2 crashed after dropping a partition table

Patch

Format: unified
File+
src/backend/commands/indexcmds.c 1 1
src/backend/commands/tablecmds.c 54 16
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 5dcedc337a..ca514919d1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -872,7 +872,7 @@ DefineIndex(Oid relationId,
 		CreateComments(indexRelationId, RelationRelationId, 0,
 					   stmt->idxcomment);
 
-	if (partitioned)
+	if (partitioned && !is_alter_table)
 	{
 		/*
 		 * Unless caller specified to skip this step (via ONLY), process each
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 93f13a4778..fb10d640e5 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -426,7 +426,9 @@ static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 					  AlterTableCmd *cmd, LOCKMODE lockmode);
 static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
 								List *options, LOCKMODE lockmode);
-static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab,
+static void ATPostAlterTypeCleanup1(List **wqueue, AlteredTableInfo *tab,
+					   LOCKMODE lockmode);
+static void ATPostAlterTypeCleanup2(List **wqueue, AlteredTableInfo *tab,
 					   LOCKMODE lockmode);
 static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
 					 char *cmd, List **wqueue, LOCKMODE lockmode,
@@ -4068,6 +4070,10 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
 			if (subcmds == NIL)
 				continue;
 
+			/* Drop the old indexes and constraints before creating*/
+			if (pass == AT_PASS_OLD_INDEX || pass == AT_PASS_OLD_CONSTR)
+				ATPostAlterTypeCleanup2(wqueue, tab, lockmode);
+
 			/*
 			 * Appropriate lock was obtained by phase 1, needn't get it again
 			 */
@@ -4084,7 +4090,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
 			 * multiple columns of a table are altered).
 			 */
 			if (pass == AT_PASS_ALTER_TYPE)
-				ATPostAlterTypeCleanup(wqueue, tab, lockmode);
+				ATPostAlterTypeCleanup1(wqueue, tab, lockmode);
 
 			relation_close(rel, NoLock);
 		}
@@ -7233,6 +7239,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	if (constr->is_no_inherit)
 		return address;
 
+	if (is_readd)
+		return address;
+
 	/*
 	 * Propagate to children as appropriate.  Unlike most other ALTER
 	 * routines, we have to do this one level of recursion at a time; we can't
@@ -10307,21 +10316,12 @@ ATExecAlterColumnGenericOptions(Relation rel,
  * and constraints that depend on the altered columns.
  */
 static void
-ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
+ATPostAlterTypeCleanup1(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
 {
-	ObjectAddress obj;
-	ObjectAddresses *objects;
 	ListCell   *def_item;
 	ListCell   *oid_item;
 
 	/*
-	 * Collect all the constraints and indexes to drop so we can process them
-	 * in a single call.  That way we don't have to worry about dependencies
-	 * among them.
-	 */
-	objects = new_object_addresses();
-
-	/*
 	 * Re-parse the index and constraint definitions, and attach them to the
 	 * appropriate work queue entries.  We do this before dropping because in
 	 * the case of a FOREIGN KEY constraint, we might not yet have exclusive
@@ -10363,16 +10363,13 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
 		conislocal = con->conislocal;
 		ReleaseSysCache(tup);
 
-		ObjectAddressSet(obj, ConstraintRelationId, oldId);
-		add_exact_object_address(&obj, objects);
-
 		/*
 		 * If the constraint is inherited (only), we don't want to inject a
 		 * new definition here; it'll get recreated when ATAddCheckConstraint
 		 * recurses from adding the parent table's constraint.  But we had to
 		 * carry the info this far so that we can drop the constraint below.
 		 */
-		if (!conislocal)
+		if (!conislocal && contype == CONSTR_CHECK)
 			continue;
 
 		/*
@@ -10398,6 +10395,46 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
 		ATPostAlterTypeParse(oldId, relid, InvalidOid,
 							 (char *) lfirst(def_item),
 							 wqueue, lockmode, tab->rewrite);
+	}
+}
+
+/*
+ * Cleanup after we've finished all the ALTER TYPE operations for a
+ * particular relation.  We have to drop and recreate all the indexes
+ * and constraints that depend on the altered columns.
+ */
+static void
+ATPostAlterTypeCleanup2(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
+{
+	ObjectAddress obj;
+	ObjectAddresses *objects;
+	ListCell   *def_item;
+	ListCell   *oid_item;
+
+	/*
+	 * Collect all the constraints and indexes to drop so we can process them
+	 * in a single call.  That way we don't have to worry about dependencies
+	 * among them.
+	 */
+	objects = new_object_addresses();
+	forboth(oid_item, tab->changedConstraintOids,
+			def_item, tab->changedConstraintDefs)
+	{
+		Oid			oldId = lfirst_oid(oid_item);
+
+		if (!SearchSysCacheExists1(CONSTROID, oldId))
+			continue;
+
+		ObjectAddressSet(obj, ConstraintRelationId, oldId);
+		add_exact_object_address(&obj, objects);
+	}
+	forboth(oid_item, tab->changedIndexOids,
+			def_item, tab->changedIndexDefs)
+	{
+		Oid			oldId = lfirst_oid(oid_item);
+
+		if (!SearchSysCacheExists1(RELOID, oldId))
+			continue;
 
 		ObjectAddressSet(obj, RelationRelationId, oldId);
 		add_exact_object_address(&obj, objects);
@@ -10411,6 +10448,7 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
 
 	free_object_addresses(objects);
 
+	CommandCounterIncrement();
 	/*
 	 * The objects will get recreated during subsequent passes over the work
 	 * queue.