*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 255,261 **** static void createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
  						 Oid constraintOid, Oid indexOid);
  static void ATController(Relation rel, List *cmds, bool recurse);
  static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
! 		  bool recurse, bool recursing);
  static void ATRewriteCatalogs(List **wqueue);
  static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
  		  AlterTableCmd *cmd);
--- 255,261 ----
  						 Oid constraintOid, Oid indexOid);
  static void ATController(Relation rel, List *cmds, bool recurse);
  static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
! 		  bool recurse, int expected_parents);
  static void ATRewriteCatalogs(List **wqueue);
  static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
  		  AlterTableCmd *cmd);
***************
*** 309,315 **** static void ATExecDropConstraint(Relation rel, const char *constrName,
  								 bool missing_ok);
  static void ATPrepAlterColumnType(List **wqueue,
  					  AlteredTableInfo *tab, Relation rel,
! 					  bool recurse, bool recursing,
  					  AlterTableCmd *cmd);
  static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
  					  const char *colName, TypeName *typeName);
--- 309,315 ----
  								 bool missing_ok);
  static void ATPrepAlterColumnType(List **wqueue,
  					  AlteredTableInfo *tab, Relation rel,
! 					  bool recurse, int expected_parents,
  					  AlterTableCmd *cmd);
  static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
  					  const char *colName, TypeName *typeName);
***************
*** 2388,2394 **** ATController(Relation rel, List *cmds, bool recurse)
  	{
  		AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
  
! 		ATPrepCmd(&wqueue, rel, cmd, recurse, false);
  	}
  
  	/* Close the relation, but keep lock until commit */
--- 2388,2394 ----
  	{
  		AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
  
! 		ATPrepCmd(&wqueue, rel, cmd, recurse, 0);
  	}
  
  	/* Close the relation, but keep lock until commit */
***************
*** 2412,2418 **** ATController(Relation rel, List *cmds, bool recurse)
   */
  static void
  ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
! 		  bool recurse, bool recursing)
  {
  	AlteredTableInfo *tab;
  	int			pass;
--- 2412,2418 ----
   */
  static void
  ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
! 		  bool recurse, int expected_parents)
  {
  	AlteredTableInfo *tab;
  	int			pass;
***************
*** 2523,2529 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
  		case AT_AlterColumnType:		/* ALTER COLUMN TYPE */
  			ATSimplePermissions(rel, false);
  			/* Performs own recursion */
! 			ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd);
  			pass = AT_PASS_ALTER_TYPE;
  			break;
  		case AT_ChangeOwner:	/* ALTER OWNER */
--- 2523,2530 ----
  		case AT_AlterColumnType:		/* ALTER COLUMN TYPE */
  			ATSimplePermissions(rel, false);
  			/* Performs own recursion */
! 			ATPrepAlterColumnType(wqueue, tab, rel,
! 								  recurse, expected_parents, cmd);
  			pass = AT_PASS_ALTER_TYPE;
  			break;
  		case AT_ChangeOwner:	/* ALTER OWNER */
***************
*** 2541,2547 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
  		case AT_AddOids:		/* SET WITH OIDS */
  			ATSimplePermissions(rel, false);
  			/* Performs own recursion */
! 			if (!rel->rd_rel->relhasoids || recursing)
  				ATPrepAddOids(wqueue, rel, recurse, cmd);
  			pass = AT_PASS_ADD_COL;
  			break;
--- 2542,2548 ----
  		case AT_AddOids:		/* SET WITH OIDS */
  			ATSimplePermissions(rel, false);
  			/* Performs own recursion */
! 			if (!rel->rd_rel->relhasoids || expected_parents > 0)
  				ATPrepAddOids(wqueue, rel, recurse, cmd);
  			pass = AT_PASS_ADD_COL;
  			break;
***************
*** 2555,2561 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
  				dropCmd->subtype = AT_DropColumn;
  				dropCmd->name = pstrdup("oid");
  				dropCmd->behavior = cmd->behavior;
! 				ATPrepCmd(wqueue, rel, dropCmd, recurse, false);
  			}
  			pass = AT_PASS_DROP;
  			break;
--- 2556,2562 ----
  				dropCmd->subtype = AT_DropColumn;
  				dropCmd->name = pstrdup("oid");
  				dropCmd->behavior = cmd->behavior;
! 				ATPrepCmd(wqueue, rel, dropCmd, recurse, expected_parents);
  			}
  			pass = AT_PASS_DROP;
  			break;
***************
*** 3421,3439 **** ATSimpleRecursion(List **wqueue, Relation rel,
  	if (recurse && rel->rd_rel->relkind == RELKIND_RELATION)
  	{
  		Oid			relid = RelationGetRelid(rel);
! 		ListCell   *child;
  		List	   *children;
  
! 		children = find_all_inheritors(relid, AccessExclusiveLock, NULL);
  
  		/*
  		 * find_all_inheritors does the recursive search of the inheritance
  		 * hierarchy, so all we have to do is process all of the relids in the
  		 * list that it returns.
  		 */
! 		foreach(child, children)
  		{
! 			Oid			childrelid = lfirst_oid(child);
  			Relation	childrel;
  
  			if (childrelid == relid)
--- 3422,3443 ----
  	if (recurse && rel->rd_rel->relkind == RELKIND_RELATION)
  	{
  		Oid			relid = RelationGetRelid(rel);
! 		ListCell   *lc, *lp;
  		List	   *children;
+ 		List	   *numparents;
  
! 		children = find_all_inheritors(relid, AccessExclusiveLock, &numparents);
  
  		/*
  		 * find_all_inheritors does the recursive search of the inheritance
  		 * hierarchy, so all we have to do is process all of the relids in the
  		 * list that it returns.
  		 */
! 		
! 		forboth(lc, children, lp, numparents)
  		{
! 			Oid			childrelid = lfirst_oid(lc);
! 			int			expected_parents = lfirst_int(lp);
  			Relation	childrel;
  
  			if (childrelid == relid)
***************
*** 3441,3447 **** ATSimpleRecursion(List **wqueue, Relation rel,
  			/* find_all_inheritors already got lock */
  			childrel = relation_open(childrelid, NoLock);
  			CheckTableNotInUse(childrel, "ALTER TABLE");
! 			ATPrepCmd(wqueue, childrel, cmd, false, true);
  			relation_close(childrel, NoLock);
  		}
  	}
--- 3445,3451 ----
  			/* find_all_inheritors already got lock */
  			childrel = relation_open(childrelid, NoLock);
  			CheckTableNotInUse(childrel, "ALTER TABLE");
! 			ATPrepCmd(wqueue, childrel, cmd, false, expected_parents);
  			relation_close(childrel, NoLock);
  		}
  	}
***************
*** 3473,3479 **** ATOneLevelRecursion(List **wqueue, Relation rel,
  		/* find_inheritance_children already got lock */
  		childrel = relation_open(childrelid, NoLock);
  		CheckTableNotInUse(childrel, "ALTER TABLE");
! 		ATPrepCmd(wqueue, childrel, cmd, true, true);
  		relation_close(childrel, NoLock);
  	}
  }
--- 3477,3488 ----
  		/* find_inheritance_children already got lock */
  		childrel = relation_open(childrelid, NoLock);
  		CheckTableNotInUse(childrel, "ALTER TABLE");
! 		/*
! 		 * XXX - Is it possible to assume `expected_numparents' is
! 		 * always 1 in this code path. Or, is there any reason why
! 		 * we should use find_all_inheritors() for ATAddColumn?
! 		 */
! 		ATPrepCmd(wqueue, childrel, cmd, true, 1);
  		relation_close(childrel, NoLock);
  	}
  }
***************
*** 5805,5811 **** ATExecDropConstraint(Relation rel, const char *constrName,
  static void
  ATPrepAlterColumnType(List **wqueue,
  					  AlteredTableInfo *tab, Relation rel,
! 					  bool recurse, bool recursing,
  					  AlterTableCmd *cmd)
  {
  	char	   *colName = cmd->name;
--- 5814,5820 ----
  static void
  ATPrepAlterColumnType(List **wqueue,
  					  AlteredTableInfo *tab, Relation rel,
! 					  bool recurse, int expected_parents,
  					  AlterTableCmd *cmd)
  {
  	char	   *colName = cmd->name;
***************
*** 5837,5843 **** ATPrepAlterColumnType(List **wqueue,
  						colName)));
  
  	/* Don't alter inherited columns */
! 	if (attTup->attinhcount > 0 && !recursing)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
  				 errmsg("cannot alter inherited column \"%s\"",
--- 5846,5852 ----
  						colName)));
  
  	/* Don't alter inherited columns */
! 	if (attTup->attinhcount > expected_parents)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
  				 errmsg("cannot alter inherited column \"%s\"",
***************
*** 5929,5935 **** ATPrepAlterColumnType(List **wqueue,
  	 */
  	if (recurse)
  		ATSimpleRecursion(wqueue, rel, cmd, recurse);
! 	else if (!recursing &&
  			 find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
--- 5938,5944 ----
  	 */
  	if (recurse)
  		ATSimpleRecursion(wqueue, rel, cmd, recurse);
! 	else if (expected_parents == 0 &&
  			 find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
