diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3ad99c8108757b5d4222674306e2f818bf5630d5..718c3b9091035dcadef404db96f47d7d1f3cab34 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.268 2004/06/06 04:52:55 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.269 2004/06/06 20:30:07 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -416,10 +416,7 @@ CheckAttributeType(const char *attname, Oid atttypid)
 	 * Warn user, but don't fail, if column to be created has UNKNOWN type
 	 * (usually as a result of a 'retrieve into' - jolly)
 	 *
-	 * Refuse any attempt to create a pseudo-type column or one that uses a
-	 * non-standalone composite type.  (We could support using table rowtypes
-	 * as attributes, if we were willing to make ALTER TABLE hugely more
-	 * complex, but for now let's limit the damage ...)
+	 * Refuse any attempt to create a pseudo-type column.
 	 */
 	if (atttypid == UNKNOWNOID)
 		ereport(WARNING,
@@ -435,16 +432,6 @@ CheckAttributeType(const char *attname, Oid atttypid)
 					 errmsg("column \"%s\" has pseudo-type %s",
 							attname, format_type_be(atttypid))));
 	}
-	else if (att_typtype == 'c')
-	{
-		Oid			typrelid = get_typ_typrelid(atttypid);
-
-		if (get_rel_relkind(typrelid) != RELKIND_COMPOSITE_TYPE)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-					 errmsg("column \"%s\" has composite type %s",
-							attname, format_type_be(atttypid))));
-	}
 }
 
 /* --------------------------------
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 66c1b95135a26190e771481003659112da927bd8..3a95064442c99837b92438801c4c015c19c7b34f 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.111 2004/06/05 19:48:07 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.112 2004/06/06 20:30:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -194,6 +194,8 @@ static void ATSimpleRecursion(List **wqueue, Relation rel,
 							  AlterTableCmd *cmd, bool recurse);
 static void ATOneLevelRecursion(List **wqueue, Relation rel,
 								AlterTableCmd *cmd);
+static void find_composite_type_dependencies(Oid typeOid,
+											 const char *origTblName);
 static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
 							AlterTableCmd *cmd);
 static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
@@ -2281,6 +2283,18 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
 	else
 		newrel = NULL;
 
+	/*
+	 * If we need to rewrite the table, the operation has to be propagated
+	 * to tables that use this table's rowtype as a column type.
+	 *
+	 * (Eventually this will probably become true for scans as well, but
+	 * at the moment a composite type does not enforce any constraints,
+	 * so it's not necessary/appropriate to enforce them just during ALTER.)
+	 */
+	if (newrel)
+		find_composite_type_dependencies(oldrel->rd_rel->reltype,
+										 RelationGetRelationName(oldrel));
+
 	/*
 	 * Generate the constraint and default execution states
 	 */
@@ -2606,6 +2620,87 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
 	}
 }
 
+
+/*
+ * find_composite_type_dependencies
+ *
+ * Check to see if a table's rowtype is being used as a column in some
+ * other table (possibly nested several levels deep in composite types!).
+ * Eventually, we'd like to propagate the check or rewrite operation
+ * into other such tables, but for now, just error out if we find any.
+ *
+ * We assume that functions and views depending on the type are not reasons
+ * to reject the ALTER.  (How safe is this really?)
+ */
+static void
+find_composite_type_dependencies(Oid typeOid, const char *origTblName)
+{
+	Relation	depRel;
+	ScanKeyData key[2];
+	SysScanDesc depScan;
+	HeapTuple	depTup;
+
+	/*
+	 * We scan pg_depend to find those things that depend on the rowtype.
+	 * (We assume we can ignore refobjsubid for a rowtype.)
+	 */
+	depRel = relation_openr(DependRelationName, AccessShareLock);
+
+	ScanKeyInit(&key[0],
+				Anum_pg_depend_refclassid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelOid_pg_type));
+	ScanKeyInit(&key[1],
+				Anum_pg_depend_refobjid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(typeOid));
+
+	depScan = systable_beginscan(depRel, DependReferenceIndex, true,
+								 SnapshotNow, 2, key);
+
+	while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
+	{
+		Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
+		Relation	rel;
+		Form_pg_attribute att;
+
+		/* Ignore dependees that aren't user columns of relations */
+		/* (we assume system columns are never of rowtypes) */
+		if (pg_depend->classid != RelOid_pg_class ||
+			pg_depend->objsubid <= 0)
+			continue;
+
+		rel = relation_open(pg_depend->objid, AccessShareLock);
+		att = rel->rd_att->attrs[pg_depend->objsubid - 1];
+
+		if (rel->rd_rel->relkind == RELKIND_RELATION)
+		{
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot alter table \"%s\" because column \"%s\".\"%s\" uses its rowtype",
+							origTblName,
+							RelationGetRelationName(rel),
+							NameStr(att->attname))));
+		}
+		else if (OidIsValid(rel->rd_rel->reltype))
+		{
+			/*
+			 * A view or composite type itself isn't a problem, but we must
+			 * recursively check for indirect dependencies via its rowtype.
+			 */
+			find_composite_type_dependencies(rel->rd_rel->reltype,
+											 origTblName);
+		}
+
+		relation_close(rel, AccessShareLock);
+	}
+
+	systable_endscan(depScan);
+
+	relation_close(depRel, AccessShareLock);
+}
+
+
 /* 
  * ALTER TABLE ADD COLUMN
  *