diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bdb32b5dccffb23c1c9e62e136170131f3dbf759..c67f7f35436827a0bfc0038976b88b66214fa6c3 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.158 2001/01/24 19:42:51 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.159 2001/02/12 20:07:21 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -68,15 +68,15 @@
 
 
 static void AddNewRelationTuple(Relation pg_class_desc,
-					Relation new_rel_desc, Oid new_rel_oid,
-					int natts,
-					char relkind, char *temp_relname);
+					Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
+					int natts, char relkind, char *temp_relname);
 static void DeleteAttributeTuples(Relation rel);
 static void DeleteRelationTuple(Relation rel);
 static void DeleteTypeTuple(Relation rel);
 static void RelationRemoveIndexes(Relation relation);
 static void RelationRemoveInheritance(Relation relation);
-static void AddNewRelationType(char *typeName, Oid new_rel_oid);
+static void AddNewRelationType(char *typeName, Oid new_rel_oid,
+							   Oid new_type_oid);
 static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
 				 bool updatePgAttribute);
 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
@@ -317,6 +317,7 @@ heap_create(char *relname,
 	strcpy(RelationGetPhysicalRelationName(rel), relname);
 	rel->rd_rel->relkind = RELKIND_UNCATALOGED;
 	rel->rd_rel->relnatts = natts;
+	rel->rd_rel->reltype = InvalidOid;
 	if (tupDesc->constr)
 		rel->rd_rel->relchecks = tupDesc->constr->num_check;
 
@@ -325,12 +326,6 @@ heap_create(char *relname,
 
 	RelationGetRelid(rel) = relid;
 
-	if (nailme)
-	{
-		/* for system relations, set the reltype field here */
-		rel->rd_rel->reltype = relid;
-	}
-
 	rel->rd_node.tblNode = tblNode;
 	rel->rd_node.relNode = relid;
 	rel->rd_rel->relfilenode = relid;
@@ -373,18 +368,17 @@ heap_storage_create(Relation rel)
  *		   performs a scan to ensure that no relation with the
  *		   same name already exists.
  *
- *		3) heap_create_with_catalog() is called to create the new relation
- *		   on disk.
+ *		3) heap_create() is called to create the new relation on disk.
  *
- *		4) TypeDefine() is called to define a new type corresponding
+ *		4) AddNewRelationTuple() is called to register the
+ *		   relation in pg_class.
+ *
+ *		5) TypeCreate() is called to define a new type corresponding
  *		   to the new relation.
  *
- *		5) AddNewAttributeTuples() is called to register the
+ *		6) AddNewAttributeTuples() is called to register the
  *		   new relation's schema in pg_attribute.
  *
- *		6) AddNewRelationTuple() is called to register the
- *		   relation itself in the catalogs.
- *
  *		7) StoreConstraints is called ()		- vadim 08/22/97
  *
  *		8) the relations are closed and the new relation's oid
@@ -656,6 +650,7 @@ static void
 AddNewRelationTuple(Relation pg_class_desc,
 					Relation new_rel_desc,
 					Oid new_rel_oid,
+					Oid new_type_oid,
 					int natts,
 					char relkind,
 					char *temp_relname)
@@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 	Relation	idescs[Num_pg_class_indices];
 
 	/* ----------------
-	 *	first we munge some of the information in our
+	 *	first we update some of the information in our
 	 *	uncataloged relation's relation descriptor.
 	 * ----------------
 	 */
@@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 	new_rel_reltup->reltuples = 1000;
 
 	new_rel_reltup->relowner = GetUserId();
+	new_rel_reltup->reltype = new_type_oid;
 	new_rel_reltup->relkind = relkind;
 	new_rel_reltup->relnatts = natts;
 
@@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc,
 	tup = heap_addheader(Natts_pg_class_fixed,
 						 CLASS_TUPLE_SIZE,
 						 (char *) new_rel_reltup);
+
+	/* force tuple to have the desired OID */
 	tup->t_data->t_oid = new_rel_oid;
 
 	/*
@@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc,
  * --------------------------------
  */
 static void
-AddNewRelationType(char *typeName, Oid new_rel_oid)
+AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
 {
-	Oid			new_type_oid;
-
 	/*
 	 * The sizes are set to oid size because it makes implementing sets
 	 * MUCH easier, and no one (we hope) uses these fields to figure out
@@ -750,23 +746,25 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
 	 * actually get is the oid of a tuple in the pg_proc catalog, so the
 	 * size of the "set" is the size of an oid. Similarly, byval being
 	 * true makes sets much easier, and it isn't used by anything else.
-	 * Note the assumption that OIDs are the same size as int4s.
-	 */
-	new_type_oid = TypeCreate(typeName, /* type name */
-							  new_rel_oid,		/* relation oid */
-							  sizeof(Oid),		/* internal size */
-							  sizeof(Oid),		/* external size */
-							  'c',		/* type-type (catalog) */
-							  ',',		/* default array delimiter */
-							  "int4in", /* input procedure */
-							  "int4out",		/* output procedure */
-							  "int4in", /* receive procedure */
-							  "int4out",		/* send procedure */
-							  NULL,		/* array element type - irrelevent */
-							  "-",		/* default type value */
-							  (bool) 1, /* passed by value */
-							  'i',		/* default alignment */
-							  'p');		/* Not TOASTable */
+	 *
+	 * XXX Note the assumption that OIDs are the same size as int4s.
+	 */
+	TypeCreate(typeName,		/* type name */
+			   new_type_oid,	/* preassigned oid for type */
+			   new_rel_oid,		/* relation oid */
+			   sizeof(Oid),		/* internal size */
+			   sizeof(Oid),		/* external size */
+			   'c',				/* type-type (catalog) */
+			   ',',				/* default array delimiter */
+			   "int4in",		/* input procedure */
+			   "int4out",		/* output procedure */
+			   "int4in",		/* receive procedure */
+			   "int4out",		/* send procedure */
+			   NULL,			/* array element type - irrelevant */
+			   "-",				/* default type value */
+			   true,			/* passed by value */
+			   'i',				/* default alignment */
+			   'p');			/* Not TOASTable */
 }
 
 /* --------------------------------
@@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname,
 	Relation	pg_class_desc;
 	Relation	new_rel_desc;
 	Oid			new_rel_oid;
+	Oid			new_type_oid;
 	int			natts = tupdesc->natts;
 	char	   *temp_relname = NULL;
 
@@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname,
 	}
 
 	/* ----------------
-	 *	RelnameFindRelid couldn't detect simultaneous
-	 *	creation. Uniqueness will be really checked by unique
-	 *	indexes of system tables but we couldn't check it here.
-	 *	We have to postpone creating the disk file for this
-	 *	relation.
-	 *	Another boolean parameter "storage_create" was added
-	 *	to heap_create() function. If the parameter is false
-	 *	heap_create() only registers an uncataloged relation
-	 *	to relation cache and heap_storage_create() should be
-	 *	called later.
-	 *	We could pull its relation oid from the newly formed
-	 *	relation descriptor.
+	 *	Tell heap_create not to create a physical file; we'll do that
+	 *	below after all our catalog updates are done.  (This isn't really
+	 *	necessary anymore, but we may as well avoid the cycles of creating
+	 *	and deleting the file in case we fail.)
 	 *
 	 *	Note: The call to heap_create() changes relname for
 	 *	temp tables; it becomes the true physical relname.
@@ -836,24 +827,18 @@ heap_create_with_catalog(char *relname,
 	new_rel_desc = heap_create(relname, tupdesc, istemp, false,
 							   allow_system_table_mods);
 
+	/* Fetch the relation OID assigned by heap_create */
 	new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
 
-	/* ----------------
-	 *	since defining a relation also defines a complex type,
-	 *	we add a new system type corresponding to the new relation.
-	 * ----------------
-	 */
-	AddNewRelationType(relname, new_rel_oid);
+	/* Assign an OID for the relation's tuple type */
+	new_type_oid = newoid();
 
 	/* ----------------
-	 *	now add tuples to pg_attribute for the attributes in
-	 *	our new relation.
-	 * ----------------
-	 */
-	AddNewAttributeTuples(new_rel_oid, tupdesc);
-
-	/* ----------------
-	 *	now update the information in pg_class.
+	 *	now create an entry in pg_class for the relation.
+	 *
+	 *	NOTE: we could get a unique-index failure here, in case someone else
+	 *	is creating the same relation name in parallel but hadn't committed
+	 *	yet when we checked for a duplicate name above.
 	 * ----------------
 	 */
 	pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
@@ -861,10 +846,28 @@ heap_create_with_catalog(char *relname,
 	AddNewRelationTuple(pg_class_desc,
 						new_rel_desc,
 						new_rel_oid,
+						new_type_oid,
 						natts,
 						relkind,
 						temp_relname);
 
+	/* ----------------
+	 *	since defining a relation also defines a complex type,
+	 *	we add a new system type corresponding to the new relation.
+	 *
+	 *	NOTE: we could get a unique-index failure here, in case the same name
+	 *	has already been used for a type.
+	 * ----------------
+	 */
+	AddNewRelationType(relname, new_rel_oid, new_type_oid);
+
+	/* ----------------
+	 *	now add tuples to pg_attribute for the attributes in
+	 *	our new relation.
+	 * ----------------
+	 */
+	AddNewAttributeTuples(new_rel_oid, tupdesc);
+
 	StoreConstraints(new_rel_desc);
 
 	if (istemp)
@@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname,
  *		attribute catalog (needed?).  (Anything else?)
  *
  *		get proper relation from relation catalog (if not arg)
- *		check if relation is vital (strcmp()/reltype?)
  *		scan attribute catalog deleting attributes of reldesc
  *				(necessary?)
  *		delete relation from relation catalog
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index f94171748553b8e28f31fa0232e5d5e2d6918764..714ea737aecb9f0866d780febd2edec8943154c1 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.58 2001/01/24 19:42:52 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
 	HeapScanDesc scan;
 	HeapTuple	tup;
 	Oid			typoid;
-
-	static ScanKeyData typeKey[1] = {
-		{0, Anum_pg_type_typname, F_NAMEEQ}
-	};
+	ScanKeyData typeKey[1];
 
 	/* ----------------
 	 *	initialize the scan key and begin a scan of pg_type
 	 * ----------------
 	 */
-	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
-	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
-	typeKey[0].sk_argument = PointerGetDatum(typeName);
+	ScanKeyEntryInitialize(typeKey,
+						   0,
+						   Anum_pg_type_typname,
+						   F_NAMEEQ,
+						   PointerGetDatum(typeName));
 
 	scan = heap_beginscan(pg_type_desc,
 						  0,
@@ -269,10 +268,16 @@ TypeShellMake(char *typeName)
  *		TypeCreate
  *
  *		This does all the necessary work needed to define a new type.
+ *
+ * NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to
+ * the new type (which, therefore, cannot already exist as a shell type).
+ * This hack is only intended for use in creating a relation's associated
+ * type, where we need to have created the relation tuple already.
  * ----------------------------------------------------------------
  */
 Oid
 TypeCreate(char *typeName,
+		   Oid assignedTypeOid,
 		   Oid relationOid,		/* only for 'c'atalog typeTypes */
 		   int16 internalSize,
 		   int16 externalSize,
@@ -292,35 +297,28 @@ TypeCreate(char *typeName,
 				j;
 	Relation	pg_type_desc;
 	HeapScanDesc pg_type_scan;
-
 	Oid			typeObjectId;
 	Oid			elementObjectId = InvalidOid;
-
 	HeapTuple	tup;
 	char		nulls[Natts_pg_type];
 	char		replaces[Natts_pg_type];
 	Datum		values[Natts_pg_type];
-
 	char	   *procname;
 	char	   *procs[4];
 	bool		defined;
 	NameData	name;
 	TupleDesc	tupDesc;
 	Oid			argList[FUNC_MAX_ARGS];
-
-	static ScanKeyData typeKey[1] = {
-		{0, Anum_pg_type_typname, F_NAMEEQ}
-	};
-
-	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
-	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
+	ScanKeyData typeKey[1];
 
 	/* ----------------
-	 *	check that the type is not already defined.
+	 *	check that the type is not already defined.  It might exist as
+	 *	a shell type, however (but only if assignedTypeOid is not given).
 	 * ----------------
 	 */
 	typeObjectId = TypeGet(typeName, &defined);
-	if (OidIsValid(typeObjectId) && defined)
+	if (OidIsValid(typeObjectId) &&
+		(defined || assignedTypeOid != InvalidOid))
 		elog(ERROR, "TypeCreate: type %s already defined", typeName);
 
 	/* ----------------
@@ -468,7 +466,12 @@ TypeCreate(char *typeName,
 	 */
 	pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
-	typeKey[0].sk_argument = PointerGetDatum(typeName);
+	ScanKeyEntryInitialize(typeKey,
+						   0,
+						   Anum_pg_type_typname,
+						   F_NAMEEQ,
+						   PointerGetDatum(typeName));
+
 	pg_type_scan = heap_beginscan(pg_type_desc,
 								  0,
 								  SnapshotSelf, /* cache? */
@@ -484,6 +487,10 @@ TypeCreate(char *typeName,
 	tup = heap_getnext(pg_type_scan, 0);
 	if (HeapTupleIsValid(tup))
 	{
+		/* should not happen given prior test? */
+		if (assignedTypeOid != InvalidOid)
+			elog(ERROR, "TypeCreate: type %s already defined", typeName);
+
 		tup = heap_modifytuple(tup,
 							   pg_type_desc,
 							   values,
@@ -502,6 +509,9 @@ TypeCreate(char *typeName,
 							 values,
 							 nulls);
 
+		/* preassign tuple Oid, if one was given */
+		tup->t_data->t_oid = assignedTypeOid;
+
 		heap_insert(pg_type_desc, tup);
 
 		typeObjectId = tup->t_data->t_oid;
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 01fd53a16a9111e3b7873ea17f4b0448634ed9f4..4f5f8a47f64edfdbccf109795fd70051b577ecda 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.51 2001/01/24 19:42:52 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters)
 	 * ----------------
 	 */
 	TypeCreate(typeName,		/* type name */
+			   InvalidOid,		/* preassigned type oid (not done here) */
 			   InvalidOid,		/* relation oid (n/a here) */
 			   internalLength,	/* internal size */
 			   externalLength,	/* external size */
@@ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters)
 			   elemName,		/* element type name */
 			   defaultValue,	/* default type value */
 			   byValue,			/* passed by value */
-			   alignment,
+			   alignment,		/* required alignment */
 			   storage);		/* TOAST strategy */
 
 	/* ----------------
@@ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters)
 	shadow_type = makeArrayTypeName(typeName);
 
 	TypeCreate(shadow_type,		/* type name */
+			   InvalidOid,		/* preassigned type oid (not done here) */
 			   InvalidOid,		/* relation oid (n/a here) */
 			   -1,				/* internal size */
 			   -1,				/* external size */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 83af133d1bbf2759968b880ad74deef2bfcf268c..e429047542f2208c5559fedce1505f720dc3e146 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.100 2001/01/24 19:43:22 momjian Exp $
+ * $Id: pg_type.h,v 1.101 2001/02/12 20:07:20 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number");
 extern Oid	TypeGet(char *typeName, bool *defined);
 extern Oid	TypeShellMake(char *typeName);
 extern Oid TypeCreate(char *typeName,
+		   Oid assignedTypeOid,
 		   Oid relationOid,
 		   int16 internalSize,
 		   int16 externalSize,
@@ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName,
 		   char *sendProcedure,
 		   char *elementTypeName,
 		   char *defaultTypeValue,
-		   bool passedByValue, char alignment,
+		   bool passedByValue,
+		   char alignment,
 		   char storage);
 extern void TypeRename(const char *oldTypeName, const char *newTypeName);
 extern char *makeArrayTypeName(char *typeName);