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