diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 53ad37bd61..67e60e1636 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.10 2002/09/11 14:48:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.11 2002/09/19 23:40:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -552,20 +552,7 @@ doDeletion(const ObjectAddress *object)
 	{
 		case OCLASS_CLASS:
 			{
-				HeapTuple	relTup;
-				char		relKind;
-
-				/*
-				 * Need the relkind to figure out how to drop.
-				 */
-				relTup = SearchSysCache(RELOID,
-									  ObjectIdGetDatum(object->objectId),
-										0, 0, 0);
-				if (!HeapTupleIsValid(relTup))
-					elog(ERROR, "doDeletion: Relation %u does not exist",
-						 object->objectId);
-				relKind = ((Form_pg_class) GETSTRUCT(relTup))->relkind;
-				ReleaseSysCache(relTup);
+				char		relKind = get_rel_relkind(object->objectId);
 
 				if (relKind == RELKIND_INDEX)
 				{
@@ -1504,6 +1491,10 @@ getRelationDescription(StringInfo buffer, Oid relid)
 			appendStringInfo(buffer, "view %s",
 							 relname);
 			break;
+		case RELKIND_COMPOSITE_TYPE:
+			appendStringInfo(buffer, "composite type %s",
+							 relname);
+			break;
 		default:
 			/* shouldn't get here */
 			appendStringInfo(buffer, "relation %s",
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 426e81d220..3b495b0108 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.228 2002/09/19 22:48:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.229 2002/09/19 23:40:56 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -384,20 +384,33 @@ CheckAttributeNames(TupleDesc tupdesc, char relkind)
 	 * 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.
+	 * Refuse any attempt to create a pseudo-type column or one that uses
+	 * a standalone composite type.  (Eventually we should probably refuse
+	 * all references to complex types, but for now there's still some
+	 * Berkeley-derived code that thinks it can do this...)
 	 */
 	for (i = 0; i < natts; i++)
 	{
 		Oid			att_type = tupdesc->attrs[i]->atttypid;
+		char		att_typtype = get_typtype(att_type);
 
 		if (att_type == UNKNOWNOID)
 			elog(WARNING, "Attribute \"%s\" has an unknown type"
 				 "\n\tProceeding with relation creation anyway",
 				 NameStr(tupdesc->attrs[i]->attname));
-		if (get_typtype(att_type) == 'p')
+		if (att_typtype == 'p')
 			elog(ERROR, "Attribute \"%s\" has pseudo-type %s",
 				 NameStr(tupdesc->attrs[i]->attname),
 				 format_type_be(att_type));
+		if (att_typtype == 'c')
+		{
+			Oid		typrelid = get_typ_typrelid(att_type);
+
+			if (get_rel_relkind(typrelid) == RELKIND_COMPOSITE_TYPE)
+				elog(ERROR, "Attribute \"%s\" has composite type %s",
+					 NameStr(tupdesc->attrs[i]->attname),
+					 format_type_be(att_type));
+		}
 	}
 }
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 9660cb61b8..88c0b5cdb6 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.88 2002/09/18 21:35:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.89 2002/09/19 23:40:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -535,21 +535,14 @@ void
 RemoveIndex(RangeVar *relation, DropBehavior behavior)
 {
 	Oid			indOid;
-	HeapTuple	tuple;
+	char		relkind;
 	ObjectAddress object;
 
 	indOid = RangeVarGetRelid(relation, false);
-	tuple = SearchSysCache(RELOID,
-						   ObjectIdGetDatum(indOid),
-						   0, 0, 0);
-	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "index \"%s\" does not exist", relation->relname);
-
-	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
+	relkind = get_rel_relkind(indOid);
+	if (relkind != RELKIND_INDEX)
 		elog(ERROR, "relation \"%s\" is of type \"%c\"",
-		 relation->relname, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-
-	ReleaseSysCache(tuple);
+			 relation->relname, relkind);
 
 	object.classId = RelOid_pg_class;
 	object.objectId = indOid;
@@ -616,7 +609,6 @@ void
 ReindexTable(RangeVar *relation, bool force)
 {
 	Oid			heapOid;
-	HeapTuple	tuple;
 	char		relkind;
 
 	/*
@@ -628,19 +620,12 @@ ReindexTable(RangeVar *relation, bool force)
 		elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
 
 	heapOid = RangeVarGetRelid(relation, false);
-	tuple = SearchSysCache(RELOID,
-						   ObjectIdGetDatum(heapOid),
-						   0, 0, 0);
-	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "table \"%s\" does not exist", relation->relname);
-	relkind = ((Form_pg_class) GETSTRUCT(tuple))->relkind;
+	relkind = get_rel_relkind(heapOid);
 
 	if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE)
 		elog(ERROR, "relation \"%s\" is of type \"%c\"",
 			 relation->relname, relkind);
 
-	ReleaseSysCache(tuple);
-
 	if (!reindex_relation(heapOid, force))
 		elog(WARNING, "table \"%s\" wasn't reindexed", relation->relname);
 }
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 47f61865fc..796eaa0506 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *				back to source text
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.123 2002/09/19 22:48:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.124 2002/09/19 23:40:56 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -2087,24 +2087,14 @@ get_rule_expr(Node *node, deparse_context *context,
 			{
 				FieldSelect *fselect = (FieldSelect *) node;
 				Oid			argType = exprType(fselect->arg);
-				HeapTuple	typetup;
-				Form_pg_type typeStruct;
 				Oid			typrelid;
 				char	   *fieldname;
 
 				/* lookup arg type and get the field name */
-				typetup = SearchSysCache(TYPEOID,
-										 ObjectIdGetDatum(argType),
-										 0, 0, 0);
-				if (!HeapTupleIsValid(typetup))
-					elog(ERROR, "cache lookup of type %u failed",
-						 argType);
-				typeStruct = (Form_pg_type) GETSTRUCT(typetup);
-				typrelid = typeStruct->typrelid;
+				typrelid = get_typ_typrelid(argType);
 				if (!OidIsValid(typrelid))
 					elog(ERROR, "Argument type %s of FieldSelect is not a tuple type",
 						 format_type_be(argType));
-				ReleaseSysCache(typetup);
 				fieldname = get_relid_attribute_name(typrelid,
 													 fselect->fieldnum);
 
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index c8a038d8a7..ae77dacd13 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.84 2002/09/18 21:35:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.85 2002/09/19 23:40:56 tgl Exp $
  *
  * NOTES
  *	  Eventually, the index information should go through here, too.
@@ -776,6 +776,33 @@ get_rel_type_id(Oid relid)
 		return InvalidOid;
 }
 
+/*
+ * get_rel_relkind
+ *
+ *		Returns the relkind associated with a given relation.
+ */
+char
+get_rel_relkind(Oid relid)
+{
+	HeapTuple	tp;
+
+	tp = SearchSysCache(RELOID,
+						ObjectIdGetDatum(relid),
+						0, 0, 0);
+	if (HeapTupleIsValid(tp))
+	{
+		Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
+		char		result;
+
+		result = reltup->relkind;
+		ReleaseSysCache(tp);
+		return result;
+	}
+	else
+		return '\0';
+}
+
+
 /*				---------- TYPE CACHE ----------						 */
 
 /*
@@ -1153,6 +1180,33 @@ get_typtype(Oid typid)
 		return '\0';
 }
 
+/*
+ * get_typ_typrelid
+ *
+ *		Given the type OID, get the typrelid (InvalidOid if not a complex
+ *		type).
+ */
+Oid
+get_typ_typrelid(Oid typid)
+{
+	HeapTuple	tp;
+
+	tp = SearchSysCache(TYPEOID,
+						ObjectIdGetDatum(typid),
+						0, 0, 0);
+	if (HeapTupleIsValid(tp))
+	{
+		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+		Oid			result;
+
+		result = typtup->typrelid;
+		ReleaseSysCache(tp);
+		return result;
+	}
+	else
+		return InvalidOid;
+}
+
 /*
  * getTypeInputInfo
  *
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 5dee7bc0cb..ff88d30e73 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.63 2002/09/18 21:35:25 tgl Exp $
+ * $Id: lsyscache.h,v 1.64 2002/09/19 23:40:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,6 +45,7 @@ extern Oid	get_system_catalog_relid(const char *catname);
 extern char *get_rel_name(Oid relid);
 extern Oid	get_rel_namespace(Oid relid);
 extern Oid	get_rel_type_id(Oid relid);
+extern char get_rel_relkind(Oid relid);
 extern bool get_typisdefined(Oid typid);
 extern int16 get_typlen(Oid typid);
 extern bool get_typbyval(Oid typid);
@@ -54,6 +55,7 @@ extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
 extern char get_typstorage(Oid typid);
 extern Node *get_typdefault(Oid typid);
 extern char get_typtype(Oid typid);
+extern Oid	get_typ_typrelid(Oid typid);
 extern void getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem);
 extern bool getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
 				  bool *typIsVarlena);