From: Tom Lane Date: Mon, 30 Jan 2006 16:19:12 +0000 (+0000) Subject: Fix ALTER COLUMN TYPE bug: it sometimes tried to drop UNIQUE or PRIMARY KEY X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=be02bae61fb2d577e6f346b8f5590ef08aab34e9;p=users%2Fbernd%2Fpostgres.git Fix ALTER COLUMN TYPE bug: it sometimes tried to drop UNIQUE or PRIMARY KEY constraints before FOREIGN KEY constraints that depended on them. Originally reported by Neil Conway on 29-Jun-2005. Patch by Nakano Yoshihisa. --- diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index aa716c303f..cba202d9f4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -4926,12 +4926,38 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, case OCLASS_CONSTRAINT: Assert(foundObject.objectSubId == 0); - if (!list_member_oid(tab->changedConstraintOids, foundObject.objectId)) + if (!list_member_oid(tab->changedConstraintOids, + foundObject.objectId)) { - tab->changedConstraintOids = lappend_oid(tab->changedConstraintOids, - foundObject.objectId); - tab->changedConstraintDefs = lappend(tab->changedConstraintDefs, - pg_get_constraintdef_string(foundObject.objectId)); + char *defstring = pg_get_constraintdef_string(foundObject.objectId); + + /* + * Put NORMAL dependencies at the front of the list and + * AUTO dependencies at the back. This makes sure that + * foreign-key constraints depending on this column will + * be dropped before unique or primary-key constraints of + * the column; which we must have because the FK + * constraints depend on the indexes belonging to the + * unique constraints. + */ + if (foundDep->deptype == DEPENDENCY_NORMAL) + { + tab->changedConstraintOids = + lcons_oid(foundObject.objectId, + tab->changedConstraintOids); + tab->changedConstraintDefs = + lcons(defstring, + tab->changedConstraintDefs); + } + else + { + tab->changedConstraintOids = + lappend_oid(tab->changedConstraintOids, + foundObject.objectId); + tab->changedConstraintDefs = + lappend(tab->changedConstraintDefs, + defstring); + } } break; @@ -5099,10 +5125,12 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab) ATPostAlterTypeParse((char *) lfirst(l), wqueue); /* - * Now we can drop the existing constraints and indexes --- - * constraints first, since some of them might depend on the indexes. - * It should be okay to use DROP_RESTRICT here, since nothing else - * should be depending on these objects. + * Now we can drop the existing constraints and indexes --- constraints + * first, since some of them might depend on the indexes. In fact, we + * have to delete FOREIGN KEY constraints before UNIQUE constraints, + * but we already ordered the constraint list to ensure that would happen. + * It should be okay to use DROP_RESTRICT here, since nothing else should + * be depending on these objects. */ if (tab->changedConstraintOids) obj.classId = get_system_catalog_relid(ConstraintRelationName);