diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 08497f35625149e5a6e0517791c262cf6a3e12b5..fd92a57ccfa79d57ee1a8d96227a6d622a829d8e 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.87 2005/10/15 02:49:38 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.88 2006/03/02 01:18:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -201,7 +201,7 @@ flagInhTables(TableInfo *tblinfo, int numTables,
 			continue;
 
 		/* Don't bother computing anything for non-target tables, either */
-		if (!tblinfo[i].dump)
+		if (!tblinfo[i].dobj.dump)
 			continue;
 
 		/* Find all the immediate parent tables */
@@ -242,7 +242,7 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 			continue;
 
 		/* Don't bother computing anything for non-target tables, either */
-		if (!tbinfo->dump)
+		if (!tbinfo->dobj.dump)
 			continue;
 
 		numParents = tbinfo->numParents;
@@ -388,7 +388,7 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
  *		Given a newly-created dumpable object, assign a dump ID,
  *		and enter the object into the lookup table.
  *
- * The caller is expected to have filled in objType and catalogId,
+ * The caller is expected to have filled in objType and catId,
  * but not any of the other standard fields of a DumpableObject.
  */
 void
@@ -397,6 +397,7 @@ AssignDumpId(DumpableObject *dobj)
 	dobj->dumpId = ++lastDumpId;
 	dobj->name = NULL;			/* must be set later */
 	dobj->namespace = NULL;		/* may be set later */
+	dobj->dump = true;			/* default assumption */
 	dobj->dependencies = NULL;
 	dobj->nDeps = 0;
 	dobj->allocDeps = 0;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 3c5cd5d4d8b32f12181a2a32472bb4208fcfa4a0..4eb2cafc19dbc971084dc2ac112fab445c930710 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.430 2006/02/21 18:01:32 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.431 2006/03/02 01:18:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,6 +130,7 @@ static void dumpType(Archive *fout, TypeInfo *tinfo);
 static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
 static void dumpDomain(Archive *fout, TypeInfo *tinfo);
 static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
+static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
 static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
 static void dumpFunc(Archive *fout, FuncInfo *finfo);
 static void dumpCast(Archive *fout, CastInfo *cast);
@@ -734,19 +735,19 @@ selectDumpableNamespace(NamespaceInfo *nsinfo)
 	 * namespace. Otherwise, dump all non-system namespaces.
 	 */
 	if (selectTableName != NULL)
-		nsinfo->dump = false;
+		nsinfo->dobj.dump = false;
 	else if (selectSchemaName != NULL)
 	{
 		if (strcmp(nsinfo->dobj.name, selectSchemaName) == 0)
-			nsinfo->dump = true;
+			nsinfo->dobj.dump = true;
 		else
-			nsinfo->dump = false;
+			nsinfo->dobj.dump = false;
 	}
 	else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
 			 strcmp(nsinfo->dobj.name, "information_schema") == 0)
-		nsinfo->dump = false;
+		nsinfo->dobj.dump = false;
 	else
-		nsinfo->dump = true;
+		nsinfo->dobj.dump = true;
 }
 
 /*
@@ -761,20 +762,69 @@ selectDumpableTable(TableInfo *tbinfo)
 	 * tablename has been specified, dump matching table name; else, do not
 	 * dump.
 	 */
-	tbinfo->dump = false;
-	if (tbinfo->dobj.namespace->dump)
-		tbinfo->dump = true;
+	tbinfo->dobj.dump = false;
+	if (tbinfo->dobj.namespace->dobj.dump)
+		tbinfo->dobj.dump = true;
 	else if (selectTableName != NULL &&
 			 strcmp(tbinfo->dobj.name, selectTableName) == 0)
 	{
 		/* If both -s and -t specified, must match both to dump */
 		if (selectSchemaName == NULL)
-			tbinfo->dump = true;
+			tbinfo->dobj.dump = true;
 		else if (strcmp(tbinfo->dobj.namespace->dobj.name, selectSchemaName) == 0)
-			tbinfo->dump = true;
+			tbinfo->dobj.dump = true;
 	}
 }
 
+/*
+ * selectDumpableType: policy-setting subroutine
+ *		Mark a type as to be dumped or not
+ */
+static void
+selectDumpableType(TypeInfo *tinfo)
+{
+	/* Dump only types in dumpable namespaces */
+	if (!tinfo->dobj.namespace->dobj.dump)
+		tinfo->dobj.dump = false;
+
+	/* skip complex types, except for standalone composite types */
+	/* (note: this test should now be unnecessary) */
+	else if (OidIsValid(tinfo->typrelid) &&
+			 tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
+		tinfo->dobj.dump = false;
+
+	/* skip undefined placeholder types */
+	else if (!tinfo->isDefined)
+		tinfo->dobj.dump = false;
+
+	/* skip all array types that start w/ underscore */
+	else if ((tinfo->dobj.name[0] == '_') &&
+			 OidIsValid(tinfo->typelem))
+		tinfo->dobj.dump = false;
+
+	else
+		tinfo->dobj.dump = true;
+}
+
+/*
+ * selectDumpableObject: policy-setting subroutine
+ *		Mark a generic dumpable object as to be dumped or not
+ *
+ * Use this only for object types without a special-case routine above.
+ */
+static void
+selectDumpableObject(DumpableObject *dobj)
+{
+	/*
+	 * Default policy is to dump if parent namespace is dumpable,
+	 * or always for non-namespace-associated items.
+	 */
+	if (dobj->namespace)
+		dobj->dump = dobj->namespace->dobj.dump;
+	else
+		dobj->dump = true;
+}
+
 /*
  *	Dump a table's contents for loading using the COPY command
  *	- this routine is called by the Archiver when it wants the table
@@ -1130,7 +1180,7 @@ getTableData(TableInfo *tblinfo, int numTables, bool oids)
 		if (tblinfo[i].relkind == RELKIND_SEQUENCE)
 			continue;
 
-		if (tblinfo[i].dump)
+		if (tblinfo[i].dobj.dump)
 		{
 			TableDataInfo *tdinfo;
 
@@ -1749,6 +1799,7 @@ getTypes(int *numTypes)
 	int			i;
 	PQExpBuffer query = createPQExpBuffer();
 	TypeInfo   *tinfo;
+	ShellTypeInfo *stinfo;
 	int			i_tableoid;
 	int			i_oid;
 	int			i_typname;
@@ -1838,9 +1889,6 @@ getTypes(int *numTypes)
 
 	for (i = 0; i < ntups; i++)
 	{
-		Oid			typoutput;
-		FuncInfo   *funcInfo;
-
 		tinfo[i].dobj.objType = DO_TYPE;
 		tinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
 		tinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
@@ -1849,12 +1897,11 @@ getTypes(int *numTypes)
 		tinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
 												tinfo[i].dobj.catId.oid);
 		tinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
-		tinfo[i].typinput = atooid(PQgetvalue(res, i, i_typinput));
-		typoutput = atooid(PQgetvalue(res, i, i_typoutput));
 		tinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
 		tinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
 		tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
 		tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
+		tinfo[i].shellType = NULL;
 
 		/*
 		 * If it's a table's rowtype, use special type code to facilitate
@@ -1880,28 +1927,86 @@ getTypes(int *numTypes)
 		else
 			tinfo[i].isDefined = false;
 
+		/* Decide whether we want to dump it */
+		selectDumpableType(&tinfo[i]);
+
 		/*
 		 * If it's a domain, fetch info about its constraints, if any
 		 */
 		tinfo[i].nDomChecks = 0;
 		tinfo[i].domChecks = NULL;
-		if (tinfo[i].typtype == 'd')
+		if (tinfo[i].dobj.dump && tinfo[i].typtype == 'd')
 			getDomainConstraints(&(tinfo[i]));
 
 		/*
-		 * Make sure there are dependencies from the type to its input and
-		 * output functions.  (We don't worry about typsend, typreceive, or
-		 * typanalyze since those are only valid in 7.4 and later, wherein the
-		 * standard dependency mechanism will pick them up.)
+		 * If it's a base type, make a DumpableObject representing a shell
+		 * definition of the type.  We will need to dump that ahead of the
+		 * I/O functions for the type.
+		 *
+		 * Note: the shell type doesn't have a catId.  You might think it
+		 * should copy the base type's catId, but then it might capture
+		 * the pg_depend entries for the type, which we don't want.
 		 */
-		funcInfo = findFuncByOid(tinfo[i].typinput);
-		if (funcInfo)
-			addObjectDependency(&tinfo[i].dobj,
-								funcInfo->dobj.dumpId);
-		funcInfo = findFuncByOid(typoutput);
-		if (funcInfo)
-			addObjectDependency(&tinfo[i].dobj,
-								funcInfo->dobj.dumpId);
+		if (tinfo[i].dobj.dump && tinfo[i].typtype == 'b')
+		{
+			stinfo = (ShellTypeInfo *) malloc(sizeof(ShellTypeInfo));
+			stinfo->dobj.objType = DO_SHELL_TYPE;
+			stinfo->dobj.catId = nilCatalogId;
+			AssignDumpId(&stinfo->dobj);
+			stinfo->dobj.name = strdup(tinfo[i].dobj.name);
+			stinfo->dobj.namespace = tinfo[i].dobj.namespace;
+			stinfo->baseType = &(tinfo[i]);
+			tinfo[i].shellType = stinfo;
+
+			/*
+			 * Initially mark the shell type as not to be dumped.  We'll
+			 * only dump it if the I/O functions need to be dumped; this
+			 * is taken care of while sorting dependencies.
+			 */
+			stinfo->dobj.dump = false;
+
+			/*
+			 * However, if dumping from pre-7.3, there will be no dependency
+			 * info so we have to fake it here.  We only need to worry about
+			 * typinput and typoutput since the other functions only exist
+			 * post-7.3.
+			 */
+			if (g_fout->remoteVersion < 70300)
+			{
+				Oid			typinput;
+				Oid			typoutput;
+				FuncInfo   *funcInfo;
+
+				typinput = atooid(PQgetvalue(res, i, i_typinput));
+				typoutput = atooid(PQgetvalue(res, i, i_typoutput));
+
+				funcInfo = findFuncByOid(typinput);
+				if (funcInfo && funcInfo->dobj.dump)
+				{
+					/* base type depends on function */
+					addObjectDependency(&tinfo[i].dobj,
+										funcInfo->dobj.dumpId);
+					/* function depends on shell type */
+					addObjectDependency(&funcInfo->dobj,
+										stinfo->dobj.dumpId);
+					/* mark shell type as to be dumped */
+					stinfo->dobj.dump = true;
+				}
+
+				funcInfo = findFuncByOid(typoutput);
+				if (funcInfo && funcInfo->dobj.dump)
+				{
+					/* base type depends on function */
+					addObjectDependency(&tinfo[i].dobj,
+										funcInfo->dobj.dumpId);
+					/* function depends on shell type */
+					addObjectDependency(&funcInfo->dobj,
+										stinfo->dobj.dumpId);
+					/* mark shell type as to be dumped */
+					stinfo->dobj.dump = true;
+				}
+			}
+		}
 
 		if (strlen(tinfo[i].rolname) == 0 && tinfo[i].isDefined)
 			write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
@@ -2004,6 +2109,9 @@ getOperators(int *numOprs)
 		oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
 		oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
 
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(oprinfo[i].dobj));
+
 		if (strlen(oprinfo[i].rolname) == 0)
 			write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
 					  oprinfo[i].dobj.name);
@@ -2082,6 +2190,9 @@ getConversions(int *numConversions)
 		convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
 												 convinfo[i].dobj.catId.oid);
 		convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(convinfo[i].dobj));
 	}
 
 	PQclear(res);
@@ -2170,6 +2281,9 @@ getOpclasses(int *numOpclasses)
 												  opcinfo[i].dobj.catId.oid);
 		opcinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
 
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(opcinfo[i].dobj));
+
 		if (g_fout->remoteVersion >= 70300)
 		{
 			if (strlen(opcinfo[i].rolname) == 0)
@@ -2290,6 +2404,9 @@ getAggregates(int *numAggs)
 		agginfo[i].aggfn.proacl = strdup(PQgetvalue(res, i, i_aggacl));
 		agginfo[i].anybasetype = false; /* computed when it's dumped */
 		agginfo[i].fmtbasetype = NULL;	/* computed when it's dumped */
+
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(agginfo[i].aggfn.dobj));
 	}
 
 	PQclear(res);
@@ -2418,6 +2535,9 @@ getFuncs(int *numFuncs)
 						  finfo[i].argtypes, finfo[i].nargs);
 		}
 
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(finfo[i].dobj));
+
 		if (strlen(finfo[i].rolname) == 0)
 			write_msg(NULL,
 				 "WARNING: owner of function \"%s\" appears to be invalid\n",
@@ -2681,12 +2801,12 @@ getTables(int *numTables)
 		 * their owning table's dump flag to them below.
 		 */
 		if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
-			tblinfo[i].dump = false;
+			tblinfo[i].dobj.dump = false;
 		else if (OidIsValid(tblinfo[i].owning_tab))
-			tblinfo[i].dump = false;
+			tblinfo[i].dobj.dump = false;
 		else
 			selectDumpableTable(&tblinfo[i]);
-		tblinfo[i].interesting = tblinfo[i].dump;
+		tblinfo[i].interesting = tblinfo[i].dobj.dump;
 
 		/*
 		 * Read-lock target tables to make sure they aren't DROPPED or altered
@@ -2699,7 +2819,7 @@ getTables(int *numTables)
 		 * NOTE: it'd be kinda nice to lock views and sequences too, not only
 		 * plain tables, but the backend doesn't presently allow that.
 		 */
-		if (tblinfo[i].dump && tblinfo[i].relkind == RELKIND_RELATION)
+		if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
 		{
 			resetPQExpBuffer(lockquery);
 			appendPQExpBuffer(lockquery,
@@ -2832,7 +2952,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
 		if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
 			continue;
 
-		if (!tbinfo->dump)
+		/* Ignore indexes of tables not to be dumped */
+		if (!tbinfo->dobj.dump)
 			continue;
 
 		if (g_verbose)
@@ -3068,7 +3189,7 @@ getConstraints(TableInfo tblinfo[], int numTables)
 	{
 		TableInfo  *tbinfo = &tblinfo[i];
 
-		if (tbinfo->ntrig == 0 || !tbinfo->dump)
+		if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
 			continue;
 
 		if (g_verbose)
@@ -3290,6 +3411,7 @@ getRules(int *numRules)
 			exit_nicely();
 		}
 		ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
+		ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
 		ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
 		ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
 		if (ruleinfo[i].ruletable)
@@ -3361,7 +3483,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
 	{
 		TableInfo  *tbinfo = &tblinfo[i];
 
-		if (tbinfo->ntrig == 0 || !tbinfo->dump)
+		if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
 			continue;
 
 		if (g_verbose)
@@ -3987,6 +4109,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 				attrdefs[j].dobj.name = strdup(tbinfo->dobj.name);
 				attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
 
+				attrdefs[j].dobj.dump = tbinfo->dobj.dump;
+
 				/*
 				 * Defaults on a VIEW must always be dumped as separate ALTER
 				 * TABLE commands.	Defaults on regular tables are dumped as
@@ -4117,6 +4241,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 				constrs[j].coninherited = false;
 				constrs[j].separate = false;
 
+				constrs[j].dobj.dump = tbinfo->dobj.dump;
+
 				/*
 				 * Mark the constraint as needing to appear before the table
 				 * --- this is so that any other dependencies of the
@@ -4167,7 +4293,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 					 */
 					tbinfo->attisserial[j] = true;
 					seqinfo->interesting = tbinfo->interesting;
-					seqinfo->dump = tbinfo->dump;
+					seqinfo->dobj.dump = tbinfo->dobj.dump;
 					break;
 				}
 			}
@@ -4513,6 +4639,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
 		case DO_TYPE:
 			dumpType(fout, (TypeInfo *) dobj);
 			break;
+		case DO_SHELL_TYPE:
+			dumpShellType(fout, (ShellTypeInfo *) dobj);
+			break;
 		case DO_FUNC:
 			dumpFunc(fout, (FuncInfo *) dobj);
 			break;
@@ -4589,8 +4718,8 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 	PQExpBuffer delq;
 	char	   *qnspname;
 
-	/* skip if not to be dumped */
-	if (!nspinfo->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!nspinfo->dobj.dump || dataOnly)
 		return;
 
 	/* don't dump dummy namespace from pre-7.3 source */
@@ -4638,23 +4767,8 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 static void
 dumpType(Archive *fout, TypeInfo *tinfo)
 {
-	/* Dump only types in dumpable namespaces */
-	if (!tinfo->dobj.namespace->dump || dataOnly)
-		return;
-
-	/* skip complex types, except for standalone composite types */
-	/* (note: this test should now be unnecessary) */
-	if (OidIsValid(tinfo->typrelid) &&
-		tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
-		return;
-
-	/* skip undefined placeholder types */
-	if (!tinfo->isDefined)
-		return;
-
-	/* skip all array types that start w/ underscore */
-	if ((tinfo->dobj.name[0] == '_') &&
-		OidIsValid(tinfo->typelem))
+	/* Skip if not to be dumped */
+	if (!tinfo->dobj.dump || dataOnly)
 		return;
 
 	/* Dump out in proper style */
@@ -4844,7 +4958,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
 		typdefault = NULL;
 
 	/*
-	 * DROP must be fully qualified in case same name appears in pg_catalog
+	 * DROP must be fully qualified in case same name appears in pg_catalog.
+	 * The reason we include CASCADE is that the circular dependency between
+	 * the type and its I/O functions makes it impossible to drop the type
+	 * any other way.
 	 */
 	appendPQExpBuffer(delq, "DROP TYPE %s.",
 					  fmtId(tinfo->dobj.namespace->dobj.name));
@@ -5162,6 +5279,47 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 	destroyPQExpBuffer(query);
 }
 
+/*
+ * dumpShellType
+ *	  writes out to fout the queries to create a shell type
+ *
+ * We dump a shell definition in advance of the I/O functions for the type.
+ */
+static void
+dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
+{
+	PQExpBuffer q;
+
+	/* Skip if not to be dumped */
+	if (!stinfo->dobj.dump || dataOnly)
+		return;
+
+	q = createPQExpBuffer();
+
+	/*
+	 * Note the lack of a DROP command for the shell type; any required DROP
+	 * is driven off the base type entry, instead.  This interacts with
+	 * _printTocEntry()'s use of the presence of a DROP command to decide
+	 * whether an entry needs an ALTER OWNER command.  We don't want to
+	 * alter the shell type's owner immediately on creation; that should
+	 * happen only after it's filled in, otherwise the backend complains.
+	 */
+
+	appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+					  fmtId(stinfo->dobj.name));
+
+	ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
+				 stinfo->dobj.name,
+				 stinfo->dobj.namespace->dobj.name,
+				 NULL,
+				 stinfo->baseType->rolname, false,
+				 "SHELL TYPE", q->data, "", NULL,
+				 stinfo->dobj.dependencies, stinfo->dobj.nDeps,
+				 NULL, NULL);
+
+	destroyPQExpBuffer(q);
+}
+
 /*
  * Determine whether we want to dump definitions for procedural languages.
  * Since the languages themselves don't have schemas, we can't rely on
@@ -5213,13 +5371,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	 */
 
 	funcInfo = findFuncByOid(plang->lanplcallfoid);
-	if (funcInfo != NULL && !funcInfo->dobj.namespace->dump)
+	if (funcInfo != NULL && !funcInfo->dobj.dump)
 		funcInfo = NULL;		/* treat not-dumped same as not-found */
 
 	if (OidIsValid(plang->lanvalidator))
 	{
 		validatorInfo = findFuncByOid(plang->lanvalidator);
-		if (validatorInfo != NULL && !validatorInfo->dobj.namespace->dump)
+		if (validatorInfo != NULL && !validatorInfo->dobj.dump)
 			validatorInfo = NULL;
 	}
 
@@ -5434,8 +5592,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	char	  **argmodes = NULL;
 	char	  **argnames = NULL;
 
-	/* Dump only funcs in dumpable namespaces */
-	if (!finfo->dobj.namespace->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!finfo->dobj.dump || dataOnly)
 		return;
 
 	query = createPQExpBuffer();
@@ -5727,9 +5885,8 @@ dumpCast(Archive *fout, CastInfo *cast)
 	/*
 	 * As per discussion we dump casts if one or more of the underlying
 	 * objects (the conversion function and the two data types) are not
-	 * builtin AND if all of the non-builtin objects namespaces are included
-	 * in the dump. Builtin meaning, the namespace name does not start with
-	 * "pg_".
+	 * builtin AND if all of the non-builtin objects are included in the dump.
+	 * Builtin meaning, the namespace name does not start with "pg_".
 	 */
 	sourceInfo = findTypeByOid(cast->castsource);
 	targetInfo = findTypeByOid(cast->casttarget);
@@ -5747,25 +5904,25 @@ dumpCast(Archive *fout, CastInfo *cast)
 		return;
 
 	/*
-	 * Skip cast if function isn't from pg_ and that namespace is not dumped.
+	 * Skip cast if function isn't from pg_ and is not to be dumped.
 	 */
 	if (funcInfo &&
 		strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-		!funcInfo->dobj.namespace->dump)
+		!funcInfo->dobj.dump)
 		return;
 
 	/*
-	 * Same for the Source type
+	 * Same for the source type
 	 */
 	if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-		!sourceInfo->dobj.namespace->dump)
+		!sourceInfo->dobj.dump)
 		return;
 
 	/*
 	 * and the target type.
 	 */
 	if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-		!targetInfo->dobj.namespace->dump)
+		!targetInfo->dobj.dump)
 		return;
 
 	/* Make sure we are in proper schema (needed for getFormattedTypeName) */
@@ -5870,8 +6027,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
 	char	   *oprltcmpop;
 	char	   *oprgtcmpop;
 
-	/* Dump only operators in dumpable namespaces */
-	if (!oprinfo->dobj.namespace->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!oprinfo->dobj.dump || dataOnly)
 		return;
 
 	/*
@@ -6220,8 +6377,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 	bool		needComma;
 	int			i;
 
-	/* Dump only opclasses in dumpable namespaces */
-	if (!opcinfo->dobj.namespace->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!opcinfo->dobj.dump || dataOnly)
 		return;
 
 	/*
@@ -6428,8 +6585,8 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
 	const char *conproc;
 	bool		condefault;
 
-	/* Dump only conversions in dumpable namespaces */
-	if (!convinfo->dobj.namespace->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!convinfo->dobj.dump || dataOnly)
 		return;
 
 	query = createPQExpBuffer();
@@ -6582,8 +6739,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 	const char *agginitval;
 	bool		convertok;
 
-	/* Dump only aggs in dumpable namespaces */
-	if (!agginfo->aggfn.dobj.namespace->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!agginfo->aggfn.dobj.dump || dataOnly)
 		return;
 
 	query = createPQExpBuffer();
@@ -6855,7 +7012,7 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
 {
 	char	   *namecopy;
 
-	if (tbinfo->dump)
+	if (tbinfo->dobj.dump)
 	{
 		if (tbinfo->relkind == RELKIND_SEQUENCE)
 			dumpSequence(fout, tbinfo);
@@ -7178,7 +7335,7 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 	PQExpBuffer delq;
 
 	/* Only print it if "separate" mode is selected */
-	if (!tbinfo->dump || !adinfo->separate || dataOnly)
+	if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
 		return;
 
 	/* Don't print inherited or serial defaults, either */
@@ -7331,9 +7488,8 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 	PQExpBuffer q;
 	PQExpBuffer delq;
 
-	if (dataOnly)
-		return;
-	if (tbinfo && !tbinfo->dump)
+	/* Skip if not to be dumped */
+	if (!coninfo->dobj.dump || dataOnly)
 		return;
 
 	q = createPQExpBuffer();
@@ -7477,8 +7633,8 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 		/* CHECK constraint on a domain */
 		TypeInfo   *tinfo = coninfo->condomain;
 
-		/* Ignore if not to be dumped separately, or if not dumping domain */
-		if (coninfo->separate && tinfo->dobj.namespace->dump)
+		/* Ignore if not to be dumped separately */
+		if (coninfo->separate)
 		{
 			appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
 							  fmtId(tinfo->dobj.name));
@@ -7995,10 +8151,8 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 	PQExpBuffer delcmd;
 	PGresult   *res;
 
-	/*
-	 * Ignore rules for not-to-be-dumped tables
-	 */
-	if (tbinfo == NULL || !tbinfo->dump || dataOnly)
+	/* Skip if not to be dumped */
+	if (!rinfo->dobj.dump || dataOnly)
 		return;
 
 	/*
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 8e8e48f4db8083432636b6712d2891ccf2062154..004f810bc79e87b224b589f50960988f1a35ba4c 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.123 2005/12/03 21:06:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.124 2006/03/02 01:18:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,6 +62,7 @@ typedef enum
 	/* When modifying this enum, update priority tables in pg_dump_sort.c! */
 	DO_NAMESPACE,
 	DO_TYPE,
+	DO_SHELL_TYPE,
 	DO_FUNC,
 	DO_AGG,
 	DO_OPERATOR,
@@ -89,6 +90,7 @@ typedef struct _dumpableObject
 	DumpId		dumpId;			/* assigned by AssignDumpId() */
 	char	   *name;			/* object name (should never be NULL) */
 	struct _namespaceInfo *namespace;	/* containing namespace, or NULL */
+	bool		dump;			/* true if we want to dump this object */
 	DumpId	   *dependencies;	/* dumpIds of objects this one depends on */
 	int			nDeps;			/* number of valid dependencies */
 	int			allocDeps;		/* allocated size of dependencies[] */
@@ -99,7 +101,6 @@ typedef struct _namespaceInfo
 	DumpableObject dobj;
 	char	   *rolname;		/* name of owner, or empty string */
 	char	   *nspacl;
-	bool		dump;			/* true if need to dump definition */
 } NamespaceInfo;
 
 typedef struct _typeInfo
@@ -111,18 +112,26 @@ typedef struct _typeInfo
 	 * produce something different than typname
 	 */
 	char	   *rolname;		/* name of owner, or empty string */
-	Oid			typinput;
 	Oid			typelem;
 	Oid			typrelid;
 	char		typrelkind;		/* 'r', 'v', 'c', etc */
 	char		typtype;		/* 'b', 'c', etc */
 	bool		isArray;		/* true if user-defined array type */
 	bool		isDefined;		/* true if typisdefined */
+	/* If it's a dumpable base type, we create a "shell type" entry for it */
+	struct _shellTypeInfo *shellType;	/* shell-type entry, or NULL */
 	/* If it's a domain, we store links to its constraints here: */
 	int			nDomChecks;
 	struct _constraintInfo *domChecks;
 } TypeInfo;
 
+typedef struct _shellTypeInfo
+{
+	DumpableObject dobj;
+
+	TypeInfo   *baseType;		/* back link to associated base type */
+} ShellTypeInfo;
+
 typedef struct _funcInfo
 {
 	DumpableObject dobj;
@@ -181,7 +190,6 @@ typedef struct _tableInfo
 	int			owning_col;		/* attr # of column owning sequence */
 
 	bool		interesting;	/* true if need to collect more data */
-	bool		dump;			/* true if we want to dump it */
 
 	/*
 	 * These fields are computed only if we decide the table is interesting
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 9e4cd35b468ea9a0e113d1c53e8be3c9ff980858..91b2c141625f89199f25dc05f18b7d23b24161e1 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.12 2005/11/22 18:17:29 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.13 2006/03/02 01:18:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,6 +29,7 @@ static const int oldObjectTypePriority[] =
 {
 	1,							/* DO_NAMESPACE */
 	2,							/* DO_TYPE */
+	2,							/* DO_SHELL_TYPE */
 	2,							/* DO_FUNC */
 	3,							/* DO_AGG */
 	3,							/* DO_OPERATOR */
@@ -57,6 +58,7 @@ static const int newObjectTypePriority[] =
 {
 	1,							/* DO_NAMESPACE */
 	3,							/* DO_TYPE */
+	3,							/* DO_SHELL_TYPE */
 	4,							/* DO_FUNC */
 	5,							/* DO_AGG */
 	6,							/* DO_OPERATOR */
@@ -602,35 +604,25 @@ findLoop(DumpableObject *obj,
 /*
  * A user-defined datatype will have a dependency loop with each of its
  * I/O functions (since those have the datatype as input or output).
- * We want the dump ordering to be the input function, then any other
- * I/O functions, then the datatype.  So we break the circularity in
- * favor of the functions, and add a dependency from any non-input
- * function to the input function.
+ * Break the loop and make the I/O function depend on the associated
+ * shell type, instead.
  */
 static void
 repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
 {
 	TypeInfo   *typeInfo = (TypeInfo *) typeobj;
-	FuncInfo   *inputFuncInfo;
 
 	/* remove function's dependency on type */
 	removeObjectDependency(funcobj, typeobj->dumpId);
 
-	/* if this isn't the input function, make it depend on same */
-	if (funcobj->catId.oid == typeInfo->typinput)
-		return;					/* it is the input function */
-	inputFuncInfo = findFuncByOid(typeInfo->typinput);
-	if (inputFuncInfo == NULL)
-		return;
-	addObjectDependency(funcobj, inputFuncInfo->dobj.dumpId);
-
-	/*
-	 * Make sure the input function's dependency on type gets removed too; if
-	 * it hasn't been done yet, we'd end up with loops involving the type and
-	 * two or more functions, which repairDependencyLoop() is not smart enough
-	 * to handle.
-	 */
-	removeObjectDependency(&inputFuncInfo->dobj, typeobj->dumpId);
+	/* add function's dependency on shell type, instead */
+	if (typeInfo->shellType)
+	{
+		addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId);
+		/* Mark shell type as to be dumped if any I/O function is */
+		if (funcobj->dump)
+			typeInfo->shellType->dobj.dump = true;
+	}
 }
 
 /*
@@ -980,6 +972,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
 					 "TYPE %s  (ID %d OID %u)",
 					 obj->name, obj->dumpId, obj->catId.oid);
 			return;
+		case DO_SHELL_TYPE:
+			snprintf(buf, bufsize,
+					 "SHELL TYPE %s  (ID %d OID %u)",
+					 obj->name, obj->dumpId, obj->catId.oid);
+			return;
 		case DO_FUNC:
 			snprintf(buf, bufsize,
 					 "FUNCTION %s  (ID %d OID %u)",