MergeConstraintsIntoExisting.no-cfbot

application/octet-stream

Filename: MergeConstraintsIntoExisting.no-cfbot
Type: application/octet-stream
Part: 0
Message: Re: not null constraints, again
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 050aad0d6a..ee1edd7187 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -16280,42 +16280,59 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
 				if (strcmp(NameStr(parent_con->conname),
 						   NameStr(child_con->conname)) != 0)
 					continue;
+
+				if(!constraints_equivalent(parent_tuple, child_tuple, RelationGetDescr(constraintrel)))
+					ereport(ERROR,
+							(errcode(ERRCODE_DATATYPE_MISMATCH),
+							errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
+									RelationGetRelationName(child_rel), NameStr(parent_con->conname))));
+				/*
+				* If the CHECK child constraint is "no inherit" then cannot
+				* merge.
+				*
+				* This is not desirable for not-null constraints, mostly because
+				* it breaks our pg_upgrade strategy, but it also makes sense on
+				* its own: if a child has its own not-null constraint and then
+				* acquires a parent with the same constraint, then we start to
+				* enforce that constraint for all the descendants of that child
+				* too, if any.
+				*/
+				if (child_con->connoinherit)
+					ereport(ERROR,
+							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+							errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
+									NameStr(child_con->conname), RelationGetRelationName(child_rel))));
 			}
 			else if (child_con->contype == CONSTRAINT_NOTNULL)
 			{
 				AttrNumber	parent_attno = extractNotNullColumn(parent_tuple);
 				AttrNumber	child_attno = extractNotNullColumn(child_tuple);
 
-				if (strcmp(get_attname(parent_relid, parent_attno, false),
-						   get_attname(RelationGetRelid(child_rel), child_attno,
-									   false)) != 0)
+				Form_pg_attribute part_attr = TupleDescAttr(parent_rel->rd_att, parent_attno - 1);
+				Form_pg_attribute child_attr = TupleDescAttr(child_rel->rd_att, child_attno - 1);
+
+				if (part_attr->attisdropped || child_attr->attisdropped)
 					continue;
-			}
 
-			if (child_con->contype == CONSTRAINT_CHECK &&
-				!constraints_equivalent(parent_tuple, child_tuple, RelationGetDescr(constraintrel)))
-				ereport(ERROR,
-						(errcode(ERRCODE_DATATYPE_MISMATCH),
-						 errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
-								RelationGetRelationName(child_rel), NameStr(parent_con->conname))));
+				if(strcmp((NameStr(part_attr->attname)), (NameStr(child_attr->attname))) != 0)
+					continue;
 
-			/*
-			 * If the CHECK child constraint is "no inherit" then cannot
-			 * merge.
-			 *
-			 * This is not desirable for not-null constraints, mostly because
-			 * it breaks our pg_upgrade strategy, but it also makes sense on
-			 * its own: if a child has its own not-null constraint and then
-			 * acquires a parent with the same constraint, then we start to
-			 * enforce that constraint for all the descendants of that child
-			 * too, if any.
-			 */
-			if (child_con->contype == CONSTRAINT_CHECK &&
-				child_con->connoinherit)
-				ereport(ERROR,
-						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-						 errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
-								NameStr(child_con->conname), RelationGetRelationName(child_rel))));
+				/*
+				 * If the child has children, it's not possible to turn a NO
+				 * INHERIT constraint into an inheritable one: we would need
+				 * to recurse to create constraints in those children, but
+				 * this is not a good place to do that.
+				 */
+				if (child_con->connoinherit && child_rel->rd_rel->relhassubclass)
+					ereport(ERROR,
+							errmsg("cannot add NOT NULL constraint to column \"%s\" of relation \"%s\" with inheritance children",
+								   get_attname(RelationGetRelid(child_rel),
+											   extractNotNullColumn(child_tuple),
+											   false),
+								   RelationGetRelationName(child_rel)),
+							errdetail("Existing constraint \"%s\" is marked NO INHERIT.",
+									  NameStr(child_con->conname)));
+			}
 
 			/*
 			 * If the child constraint is "not valid" then cannot merge with a
@@ -16342,25 +16359,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
 			/* Also reset connoinherit for not-null, if the child has that */
 			if (child_con->contype == CONSTRAINT_NOTNULL &&
 				child_con->connoinherit)
-			{
-				/*
-				 * If the child has children, it's not possible to turn a NO
-				 * INHERIT constraint into an inheritable one: we would need
-				 * to recurse to create constraints in those children, but
-				 * this is not a good place to do that.
-				 */
-				if (child_rel->rd_rel->relhassubclass)
-					ereport(ERROR,
-							errmsg("cannot add NOT NULL constraint to column \"%s\" of relation \"%s\" with inheritance children",
-								   get_attname(RelationGetRelid(child_rel),
-											   extractNotNullColumn(child_tuple),
-											   false),
-								   RelationGetRelationName(child_rel)),
-							errdetail("Existing constraint \"%s\" is marked NO INHERIT.",
-									  NameStr(child_con->conname)));
-
 				child_con->connoinherit = false;
-			}
 
 			/*
 			 * In case of partitions, an inherited constraint must be