diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 2656786d1e..83a391eed1 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -3249,8 +3249,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        (references <link linkend="catalog-pg-class"><structname>pg_class</structname></link>.<structfield>oid</structfield>)
       </para>
       <para>
-       The OID of the system catalog the dependent object is in,
-       or zero for a <symbol>DEPENDENCY_PIN</symbol> entry
+       The OID of the system catalog the dependent object is in
       </para></entry>
      </row>
 
@@ -3260,8 +3259,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        (references any OID column)
       </para>
       <para>
-       The OID of the specific dependent object,
-       or zero for a <symbol>DEPENDENCY_PIN</symbol> entry
+       The OID of the specific dependent object
       </para></entry>
      </row>
 
@@ -3464,19 +3462,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
       </para>
      </listitem>
     </varlistentry>
-
-    <varlistentry>
-     <term><symbol>DEPENDENCY_PIN</symbol> (<literal>p</literal>)</term>
-     <listitem>
-      <para>
-       There is no dependent object; this type of entry is a signal
-       that the system itself depends on the referenced object, and so
-       that object must never be deleted.  Entries of this type are
-       created only by <application>initdb</application>.  The columns for the
-       dependent object contain zeroes.
-      </para>
-     </listitem>
-    </varlistentry>
    </variablelist>
 
    Other dependency flavors might be needed in future.
@@ -6769,7 +6754,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
       <para>
        The OID of the database the dependent object is in,
        or zero for a shared object
-       or a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
       </para></entry>
      </row>
 
@@ -6779,8 +6763,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        (references <link linkend="catalog-pg-class"><structname>pg_class</structname></link>.<structfield>oid</structfield>)
       </para>
       <para>
-       The OID of the system catalog the dependent object is in,
-       or zero for a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
+       The OID of the system catalog the dependent object is in
       </para></entry>
      </row>
 
@@ -6790,8 +6773,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        (references any OID column)
       </para>
       <para>
-       The OID of the specific dependent object,
-       or zero for a <symbol>SHARED_DEPENDENCY_PIN</symbol> entry
+       The OID of the specific dependent object
       </para></entry>
      </row>
 
@@ -6879,19 +6861,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
      </listitem>
     </varlistentry>
 
-    <varlistentry>
-     <term><symbol>SHARED_DEPENDENCY_PIN</symbol> (<literal>p</literal>)</term>
-     <listitem>
-      <para>
-       There is no dependent object; this type of entry is a signal
-       that the system itself depends on the referenced object, and so
-       that object must never be deleted.  Entries of this type are
-       created only by <application>initdb</application>.  The columns for the
-       dependent object contain zeroes.
-      </para>
-     </listitem>
-    </varlistentry>
-
     <varlistentry>
      <term><symbol>SHARED_DEPENDENCY_TABLESPACE</symbol> (<literal>t</literal>)</term>
      <listitem>
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index 142da4aaff..95e8df5212 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -586,6 +586,35 @@ GetNewObjectId(void)
 	return result;
 }
 
+/*
+ * StopGeneratingPinnedObjectIds
+ *
+ * This is called once during initdb to force the OID counter up to
+ * FirstUnpinnedObjectId.  This supports letting initdb's post-bootstrap
+ * processing create some pinned objects early on.  Once it's done doing
+ * so, it calls this (via pg_stop_making_pinned_objects()) so that the
+ * remaining objects it makes will be considered un-pinned.
+ */
+void
+StopGeneratingPinnedObjectIds(void)
+{
+	/* Safety check, this is only allowable during initdb */
+	if (IsPostmasterEnvironment)
+		elog(ERROR, "cannot change object pinned-ness anymore");
+
+	/* Taking the lock is, therefore, just pro forma; but do it anyway */
+	LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
+
+	if (ShmemVariableCache->nextOid > (Oid) FirstUnpinnedObjectId)
+		elog(ERROR, "too late to change pinned-ness, %u such OIDs were already used",
+			 ShmemVariableCache->nextOid - (Oid) FirstUnpinnedObjectId);
+
+	ShmemVariableCache->nextOid = FirstUnpinnedObjectId;
+	ShmemVariableCache->oidCount = 0;
+
+	LWLockRelease(OidGenLock);
+}
+
 
 #ifdef USE_ASSERT_CHECKING
 
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 245d536372..5d0dd3f481 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -31,6 +31,7 @@
 #include "catalog/pg_authid.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_db_role_setting.h"
+#include "catalog/pg_largeobject.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_replication_origin.h"
 #include "catalog/pg_shdepend.h"
@@ -294,6 +295,64 @@ IsSharedRelation(Oid relationId)
 	return false;
 }
 
+/*
+ * IsPinnedObject
+ *		Given the class + OID identity of a database object, report whether
+ *		it is "pinned", that is not droppable because the system requires it.
+ *
+ * We used to represent this explicitly in pg_depend, but that proved to be
+ * an undesirable amount of overhead, so now we rely on an OID range test.
+ */
+bool
+IsPinnedObject(Oid classId, Oid objectId)
+{
+	/*
+	 * Objects with OIDs above FirstUnpinnedObjectId are never pinned.  Since
+	 * the OID generator skips this range when wrapping around, this check
+	 * guarantees that user-defined objects are never considered pinned.
+	 */
+	if (objectId >= FirstUnpinnedObjectId)
+		return false;
+
+	/*
+	 * Large objects are never pinned.  We need this special case because
+	 * their OIDs can be user-assigned.
+	 */
+	if (classId == LargeObjectRelationId)
+		return false;
+
+	/*
+	 * There are a few objects defined in the catalog .dat files that, as a
+	 * matter of policy, we prefer not to treat as pinned.  We used to handle
+	 * that by excluding them from pg_depend, but it's just as easy to
+	 * hard-wire their OIDs here.  (If the user does indeed drop and recreate
+	 * them, they'll have new but certainly-unpinned OIDs, so no problem.)
+	 *
+	 * Checking both classId and objectId is overkill, since OIDs below
+	 * FirstUnpinnedObjectId should be globally unique, but do it anyway for
+	 * robustness.
+	 */
+
+	/* template1 is not pinned */
+	if (classId == DatabaseRelationId &&
+		objectId == TemplateDbOid)
+		return false;
+
+	/* the public namespace is not pinned */
+	if (classId == NamespaceRelationId &&
+		objectId == PG_PUBLIC_NAMESPACE)
+		return false;
+
+	/*
+	 * All other initdb-created objects are pinned.  This is overkill (the
+	 * system doesn't really depend on having every last weird datatype, for
+	 * instance) but generating only the minimum required set of dependencies
+	 * seems hard, and enforcing an accurate list would be much more expensive
+	 * than the simple range test used here.
+	 */
+	return true;
+}
+
 
 /*
  * GetNewOidWithIndex
@@ -529,7 +588,8 @@ pg_nextoid(PG_FUNCTION_ARGS)
 	if (!superuser())
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("must be superuser to call pg_nextoid()")));
+				 errmsg("must be superuser to call %s()",
+						"pg_nextoid")));
 
 	rel = table_open(reloid, RowExclusiveLock);
 	idx = index_open(idxoid, RowExclusiveLock);
@@ -576,5 +636,29 @@ pg_nextoid(PG_FUNCTION_ARGS)
 	table_close(rel, RowExclusiveLock);
 	index_close(idx, RowExclusiveLock);
 
-	return newoid;
+	PG_RETURN_OID(newoid);
+}
+
+/*
+ * SQL callable interface for StopGeneratingPinnedObjectIds().
+ *
+ * This is only to be used by initdb, so it's intentionally not documented in
+ * the user facing docs.
+ */
+Datum
+pg_stop_making_pinned_objects(PG_FUNCTION_ARGS)
+{
+	/*
+	 * Belt-and-suspenders check, since StopGeneratingPinnedObjectIds will
+	 * fail anyway in non-single-user mode.
+	 */
+	if (!superuser())
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("must be superuser to call %s()",
+						"pg_stop_making_pinned_objects")));
+
+	StopGeneratingPinnedObjectIds();
+
+	PG_RETURN_VOID();
 }
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 8d8e926c21..5d70a6cb55 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -18,6 +18,7 @@
 #include "access/htup_details.h"
 #include "access/table.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
 #include "catalog/index.h"
@@ -599,6 +600,16 @@ findDependentObjects(const ObjectAddress *object,
 	if (object_address_present_add_flags(object, objflags, targetObjects))
 		return;
 
+	/*
+	 * If the target object is pinned, we can just error out immediately; it
+	 * won't have any objects recorded as depending on it.
+	 */
+	if (IsPinnedObject(object->classId, object->objectId))
+		ereport(ERROR,
+				(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+				 errmsg("cannot drop %s because it is required by the database system",
+						getObjectDescription(object, false))));
+
 	/*
 	 * The target object might be internally dependent on some other object
 	 * (its "owner"), and/or be a member of an extension (also considered its
@@ -862,15 +873,6 @@ findDependentObjects(const ObjectAddress *object,
 				objflags |= DEPFLAG_IS_PART;
 				break;
 
-			case DEPENDENCY_PIN:
-
-				/*
-				 * Should not happen; PIN dependencies should have zeroes in
-				 * the depender fields...
-				 */
-				elog(ERROR, "incorrect use of PIN dependency with %s",
-					 getObjectDescription(object, false));
-				break;
 			default:
 				elog(ERROR, "unrecognized dependency type '%c' for %s",
 					 foundDep->deptype, getObjectDescription(object, false));
@@ -999,18 +1001,6 @@ findDependentObjects(const ObjectAddress *object,
 			case DEPENDENCY_EXTENSION:
 				subflags = DEPFLAG_EXTENSION;
 				break;
-			case DEPENDENCY_PIN:
-
-				/*
-				 * For a PIN dependency we just ereport immediately; there
-				 * won't be any others to report.
-				 */
-				ereport(ERROR,
-						(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
-						 errmsg("cannot drop %s because it is required by the database system",
-								getObjectDescription(object, false))));
-				subflags = 0;	/* keep compiler quiet */
-				break;
 			default:
 				elog(ERROR, "unrecognized dependency type '%c' for %s",
 					 foundDep->deptype, getObjectDescription(object, false));
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 362db7fe91..c5626e4087 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -17,6 +17,7 @@
 #include "access/genam.h"
 #include "access/htup_details.h"
 #include "access/table.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_collation.h"
@@ -32,7 +33,7 @@
 #include "utils/rel.h"
 
 
-static bool isObjectPinned(const ObjectAddress *object, Relation rel);
+static bool isObjectPinned(const ObjectAddress *object);
 
 
 /*
@@ -136,7 +137,7 @@ recordMultipleDependencies(const ObjectAddress *depender,
 		 * version.  This saves lots of space in pg_depend, so it's worth the
 		 * time taken to check.
 		 */
-		if (!ignore_systempin && isObjectPinned(referenced, dependDesc))
+		if (!ignore_systempin && isObjectPinned(referenced))
 			continue;
 
 		if (slot_init_count < max_slots)
@@ -440,8 +441,6 @@ changeDependencyFor(Oid classId, Oid objectId,
 	bool		oldIsPinned;
 	bool		newIsPinned;
 
-	depRel = table_open(DependRelationId, RowExclusiveLock);
-
 	/*
 	 * Check to see if either oldRefObjectId or newRefObjectId is pinned.
 	 * Pinned objects should not have any dependency entries pointing to them,
@@ -452,16 +451,14 @@ changeDependencyFor(Oid classId, Oid objectId,
 	objAddr.objectId = oldRefObjectId;
 	objAddr.objectSubId = 0;
 
-	oldIsPinned = isObjectPinned(&objAddr, depRel);
+	oldIsPinned = isObjectPinned(&objAddr);
 
 	objAddr.objectId = newRefObjectId;
 
-	newIsPinned = isObjectPinned(&objAddr, depRel);
+	newIsPinned = isObjectPinned(&objAddr);
 
 	if (oldIsPinned)
 	{
-		table_close(depRel, RowExclusiveLock);
-
 		/*
 		 * If both are pinned, we need do nothing.  However, return 1 not 0,
 		 * else callers will think this is an error case.
@@ -481,6 +478,8 @@ changeDependencyFor(Oid classId, Oid objectId,
 		return 1;
 	}
 
+	depRel = table_open(DependRelationId, RowExclusiveLock);
+
 	/* There should be existing dependency record(s), so search. */
 	ScanKeyInit(&key[0],
 				Anum_pg_depend_classid,
@@ -615,7 +614,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
 	objAddr.objectId = oldRefObjectId;
 	objAddr.objectSubId = 0;
 
-	if (isObjectPinned(&objAddr, depRel))
+	if (isObjectPinned(&objAddr))
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot remove dependency on %s because it is a system object",
@@ -627,7 +626,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
 	 */
 	objAddr.objectId = newRefObjectId;
 
-	newIsPinned = isObjectPinned(&objAddr, depRel);
+	newIsPinned = isObjectPinned(&objAddr);
 
 	/* Now search for dependency records */
 	ScanKeyInit(&key[0],
@@ -675,50 +674,14 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
  * isObjectPinned()
  *
  * Test if an object is required for basic database functionality.
- * Caller must already have opened pg_depend.
  *
  * The passed subId, if any, is ignored; we assume that only whole objects
  * are pinned (and that this implies pinning their components).
  */
 static bool
-isObjectPinned(const ObjectAddress *object, Relation rel)
+isObjectPinned(const ObjectAddress *object)
 {
-	bool		ret = false;
-	SysScanDesc scan;
-	HeapTuple	tup;
-	ScanKeyData key[2];
-
-	ScanKeyInit(&key[0],
-				Anum_pg_depend_refclassid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(object->classId));
-
-	ScanKeyInit(&key[1],
-				Anum_pg_depend_refobjid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(object->objectId));
-
-	scan = systable_beginscan(rel, DependReferenceIndexId, true,
-							  NULL, 2, key);
-
-	/*
-	 * Since we won't generate additional pg_depend entries for pinned
-	 * objects, there can be at most one entry referencing a pinned object.
-	 * Hence, it's sufficient to look at the first returned tuple; we don't
-	 * need to loop.
-	 */
-	tup = systable_getnext(scan);
-	if (HeapTupleIsValid(tup))
-	{
-		Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
-
-		if (foundDep->deptype == DEPENDENCY_PIN)
-			ret = true;
-	}
-
-	systable_endscan(scan);
-
-	return ret;
+	return IsPinnedObject(object->classId, object->objectId);
 }
 
 
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 90b7a5de29..1df7241a52 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -101,7 +101,7 @@ static void storeObjectDescription(StringInfo descs,
 								   ObjectAddress *object,
 								   SharedDependencyType deptype,
 								   int count);
-static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel);
+static bool isSharedObjectPinned(Oid classId, Oid objectId);
 
 
 /*
@@ -140,8 +140,7 @@ recordSharedDependencyOn(ObjectAddress *depender,
 	sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
 
 	/* If the referenced object is pinned, do nothing. */
-	if (!isSharedObjectPinned(referenced->classId, referenced->objectId,
-							  sdepRel))
+	if (!isSharedObjectPinned(referenced->classId, referenced->objectId))
 	{
 		shdepAddDependency(sdepRel, depender->classId, depender->objectId,
 						   depender->objectSubId,
@@ -255,7 +254,7 @@ shdepChangeDep(Relation sdepRel,
 
 	systable_endscan(scan);
 
-	if (isSharedObjectPinned(refclassid, refobjid, sdepRel))
+	if (isSharedObjectPinned(refclassid, refobjid))
 	{
 		/* No new entry needed, so just delete existing entry if any */
 		if (oldtup)
@@ -513,7 +512,7 @@ updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
 				continue;
 
 			/* Skip pinned roles; they don't need dependency entries */
-			if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+			if (isSharedObjectPinned(AuthIdRelationId, roleid))
 				continue;
 
 			shdepAddDependency(sdepRel, classId, objectId, objsubId,
@@ -531,7 +530,7 @@ updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
 				continue;
 
 			/* Skip pinned roles */
-			if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+			if (isSharedObjectPinned(AuthIdRelationId, roleid))
 				continue;
 
 			shdepDropDependency(sdepRel, classId, objectId, objsubId,
@@ -626,8 +625,6 @@ shared_dependency_comparator(const void *a, const void *b)
  * on objects local to other databases.  We can (and do) provide descriptions
  * of the two former kinds of objects, but we can't do that for "remote"
  * objects, so we just provide a count of them.
- *
- * If we find a SHARED_DEPENDENCY_PIN entry, we can error out early.
  */
 bool
 checkSharedDependencies(Oid classId, Oid objectId,
@@ -649,6 +646,18 @@ checkSharedDependencies(Oid classId, Oid objectId,
 	StringInfoData descs;
 	StringInfoData alldescs;
 
+	/* This case can be dispatched quickly */
+	if (isSharedObjectPinned(classId, objectId))
+	{
+		object.classId = classId;
+		object.objectId = objectId;
+		object.objectSubId = 0;
+		ereport(ERROR,
+				(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+				 errmsg("cannot drop %s because it is required by the database system",
+						getObjectDescription(&object, false))));
+	}
+
 	/*
 	 * We limit the number of dependencies reported to the client to
 	 * MAX_REPORTED_DEPS, since client software may not deal well with
@@ -685,18 +694,6 @@ checkSharedDependencies(Oid classId, Oid objectId,
 	{
 		Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
 
-		/* This case can be dispatched quickly */
-		if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
-		{
-			object.classId = classId;
-			object.objectId = objectId;
-			object.objectSubId = 0;
-			ereport(ERROR,
-					(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
-					 errmsg("cannot drop %s because it is required by the database system",
-							getObjectDescription(&object, false))));
-		}
-
 		object.classId = sdepForm->classid;
 		object.objectId = sdepForm->objid;
 		object.objectSubId = sdepForm->objsubid;
@@ -1274,49 +1271,15 @@ storeObjectDescription(StringInfo descs,
 
 /*
  * isSharedObjectPinned
- *		Return whether a given shared object has a SHARED_DEPENDENCY_PIN entry.
- *
- * sdepRel must be the pg_shdepend relation, already opened and suitably
- * locked.
+ *		Return true if a shared object is pinned.
  */
 static bool
-isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
+isSharedObjectPinned(Oid classId, Oid objectId)
 {
-	bool		result = false;
-	ScanKeyData key[2];
-	SysScanDesc scan;
-	HeapTuple	tup;
-
-	ScanKeyInit(&key[0],
-				Anum_pg_shdepend_refclassid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(classId));
-	ScanKeyInit(&key[1],
-				Anum_pg_shdepend_refobjid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(objectId));
-
-	scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
-							  NULL, 2, key);
-
 	/*
-	 * Since we won't generate additional pg_shdepend entries for pinned
-	 * objects, there can be at most one entry referencing a pinned object.
-	 * Hence, it's sufficient to look at the first returned tuple; we don't
-	 * need to loop.
+	 * This is currently just the same as the normal pin test.
 	 */
-	tup = systable_getnext(scan);
-	if (HeapTupleIsValid(tup))
-	{
-		Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
-
-		if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
-			result = true;
-	}
-
-	systable_endscan(scan);
-
-	return result;
+	return IsPinnedObject(classId, objectId);
 }
 
 /*
@@ -1359,7 +1322,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 		HeapTuple	tuple;
 
 		/* Doesn't work for pinned objects */
-		if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+		if (isSharedObjectPinned(AuthIdRelationId, roleid))
 		{
 			ObjectAddress obj;
 
@@ -1402,7 +1365,6 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 			switch (sdepForm->deptype)
 			{
 					/* Shouldn't happen */
-				case SHARED_DEPENDENCY_PIN:
 				case SHARED_DEPENDENCY_INVALID:
 					elog(ERROR, "unexpected dependency type");
 					break;
@@ -1506,7 +1468,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
 		Oid			roleid = lfirst_oid(cell);
 
 		/* Refuse to work on pinned roles */
-		if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+		if (isSharedObjectPinned(AuthIdRelationId, roleid))
 		{
 			ObjectAddress obj;
 
@@ -1549,10 +1511,6 @@ shdepReassignOwned(List *roleids, Oid newrole)
 				sdepForm->dbid != InvalidOid)
 				continue;
 
-			/* Unexpected because we checked for pins above */
-			if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
-				elog(ERROR, "unexpected shared pin");
-
 			/* We leave non-owner dependencies alone */
 			if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
 				continue;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 096a6f2891..0411934480 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -11914,10 +11914,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 		Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
 		ObjectAddress foundObject;
 
-		/* We don't expect any PIN dependencies on columns */
-		if (foundDep->deptype == DEPENDENCY_PIN)
-			elog(ERROR, "cannot alter type of a pinned column");
-
 		foundObject.classId = foundDep->classid;
 		foundObject.objectId = foundDep->objid;
 		foundObject.objectSubId = foundDep->objsubid;
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 69ea155d50..0385fd6121 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -449,7 +449,6 @@ DropTableSpace(DropTableSpaceStmt *stmt)
 			ereport(NOTICE,
 					(errmsg("tablespace \"%s\" does not exist, skipping",
 							tablespacename)));
-			/* XXX I assume I need one or both of these next two calls */
 			table_endscan(scandesc);
 			table_close(rel, NoLock);
 		}
@@ -465,8 +464,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
 					   tablespacename);
 
 	/* Disallow drop of the standard tablespaces, even by superuser */
-	if (tablespaceoid == GLOBALTABLESPACE_OID ||
-		tablespaceoid == DEFAULTTABLESPACE_OID)
+	if (IsPinnedObject(TableSpaceRelationId, tablespaceoid))
 		aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE,
 					   tablespacename);
 
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 4500df6fc8..ced981b902 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1521,83 +1521,10 @@ setup_depend(FILE *cmdfd)
 	const char *const *line;
 	static const char *const pg_depend_setup[] = {
 		/*
-		 * Make PIN entries in pg_depend for all objects made so far in the
-		 * tables that the dependency code handles.  This is overkill (the
-		 * system doesn't really depend on having every last weird datatype,
-		 * for instance) but generating only the minimum required set of
-		 * dependencies seems hard.
-		 *
-		 * Catalogs that are intentionally not scanned here are:
-		 *
-		 * pg_database: it's a feature, not a bug, that template1 is not
+		 * Advance the OID counter so that subsequently-created objects aren't
 		 * pinned.
-		 *
-		 * pg_extension: a pinned extension isn't really an extension, hmm?
-		 *
-		 * pg_tablespace: tablespaces don't participate in the dependency
-		 * code, and DropTableSpace() explicitly protects the built-in
-		 * tablespaces.
-		 *
-		 * First delete any already-made entries; PINs override all else, and
-		 * must be the only entries for their objects.
-		 */
-		"DELETE FROM pg_depend;\n\n",
-		"VACUUM pg_depend;\n\n",
-		"DELETE FROM pg_shdepend;\n\n",
-		"VACUUM pg_shdepend;\n\n",
-
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_class;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_proc;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_type;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_cast;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_constraint;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_conversion;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_attrdef;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_language;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_operator;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_opclass;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_opfamily;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_am;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_amop;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_amproc;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_rewrite;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_trigger;\n\n",
-
-		/*
-		 * restriction here to avoid pinning the public namespace
 		 */
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_namespace "
-		"    WHERE nspname LIKE 'pg%';\n\n",
-
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_ts_parser;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_ts_dict;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_ts_template;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_ts_config;\n\n",
-		"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
-		" FROM pg_collation;\n\n",
-		"INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
-		" FROM pg_authid;\n\n",
+		"SELECT pg_stop_making_pinned_objects();\n\n",
 		NULL
 	};
 
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 2f7338ee82..575daaa87f 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -161,18 +161,21 @@ FullTransactionIdAdvance(FullTransactionId *dest)
  *		development purposes (such as in-progress patches and forks);
  *		they should not appear in released versions.
  *
- *		OIDs 10000-12999 are reserved for assignment by genbki.pl, for use
+ *		OIDs 10000-12499 are reserved for assignment by genbki.pl, for use
  *		when the .dat files in src/include/catalog/ do not specify an OID
  *		for a catalog entry that requires one.
  *
- *		OIDS 13000-16383 are reserved for assignment during initdb
- *		using the OID generator.  (We start the generator at 13000.)
+ *		OIDs 12500-16383 are reserved for assignment during initdb
+ *		using the OID generator.  (We start the generator at 12500.)
+ *		Of these, OIDs below 13000 are considered to be pinned, that is
+ *		not droppable after initdb.  initdb forces the OID generator up to
+ *		13000 as soon as it's made the pinned objects it's responsible for.
  *
  *		OIDs beginning at 16384 are assigned from the OID generator
  *		during normal multiuser operation.  (We force the generator up to
  *		16384 as soon as we are in normal operation.)
  *
- * The choices of 8000, 10000 and 13000 are completely arbitrary, and can be
+ * The choices of 8000/10000/12500/13000 are completely arbitrary, and can be
  * moved if we run low on OIDs in any category.  Changing the macros below,
  * and updating relevant documentation (see bki.sgml and RELEASE_CHANGES),
  * should be sufficient to do this.  Moving the 16384 boundary between
@@ -182,11 +185,13 @@ FullTransactionIdAdvance(FullTransactionId *dest)
  *
  * NOTE: if the OID generator wraps around, we skip over OIDs 0-16383
  * and resume with 16384.  This minimizes the odds of OID conflict, by not
- * reassigning OIDs that might have been assigned during initdb.
+ * reassigning OIDs that might have been assigned during initdb.  Critically,
+ * it also ensures that no user-created object will be considered pinned.
  * ----------
  */
 #define FirstGenbkiObjectId		10000
-#define FirstBootstrapObjectId	13000
+#define FirstBootstrapObjectId	12500
+#define FirstUnpinnedObjectId	13000
 #define FirstNormalObjectId		16384
 
 /*
@@ -287,6 +292,7 @@ extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
 extern void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid);
 extern bool ForceTransactionIdLimitUpdate(void);
 extern Oid	GetNewObjectId(void);
+extern void StopGeneratingPinnedObjectIds(void);
 
 #ifdef USE_ASSERT_CHECKING
 extern void AssertTransactionIdInAllowableRange(TransactionId xid);
diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h
index f247be50b4..ef2e88fe45 100644
--- a/src/include/catalog/catalog.h
+++ b/src/include/catalog/catalog.h
@@ -34,6 +34,8 @@ extern bool IsReservedName(const char *name);
 
 extern bool IsSharedRelation(Oid relationId);
 
+extern bool IsPinnedObject(Oid classId, Oid objectId);
+
 extern Oid	GetNewOidWithIndex(Relation relation, Oid indexId,
 							   AttrNumber oidcolumn);
 extern Oid	GetNewRelFileNode(Oid reltablespace, Relation pg_class,
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index f272e2c99f..83af8ff08c 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -36,8 +36,7 @@ typedef enum DependencyType
 	DEPENDENCY_PARTITION_PRI = 'P',
 	DEPENDENCY_PARTITION_SEC = 'S',
 	DEPENDENCY_EXTENSION = 'e',
-	DEPENDENCY_AUTO_EXTENSION = 'x',
-	DEPENDENCY_PIN = 'p'
+	DEPENDENCY_AUTO_EXTENSION = 'x'
 } DependencyType;
 
 /*
@@ -47,27 +46,21 @@ typedef enum DependencyType
  * unless the dependent object is dropped at the same time.  There are some
  * additional rules however:
  *
- * (a) For a SHARED_DEPENDENCY_PIN entry, there is no dependent object --
- * rather, the referenced object is an essential part of the system.  This
- * applies to the initdb-created superuser.  Entries of this type are only
- * created by initdb; objects in this category don't need further pg_shdepend
- * entries if more objects come to depend on them.
- *
- * (b) a SHARED_DEPENDENCY_OWNER entry means that the referenced object is
+ * (a) a SHARED_DEPENDENCY_OWNER entry means that the referenced object is
  * the role owning the dependent object.  The referenced object must be
  * a pg_authid entry.
  *
- * (c) a SHARED_DEPENDENCY_ACL entry means that the referenced object is
+ * (b) a SHARED_DEPENDENCY_ACL entry means that the referenced object is
  * a role mentioned in the ACL field of the dependent object.  The referenced
  * object must be a pg_authid entry.  (SHARED_DEPENDENCY_ACL entries are not
  * created for the owner of an object; hence two objects may be linked by
  * one or the other, but not both, of these dependency types.)
  *
- * (d) a SHARED_DEPENDENCY_POLICY entry means that the referenced object is
+ * (c) a SHARED_DEPENDENCY_POLICY entry means that the referenced object is
  * a role mentioned in a policy object.  The referenced object must be a
  * pg_authid entry.
  *
- * (e) a SHARED_DEPENDENCY_TABLESPACE entry means that the referenced
+ * (d) a SHARED_DEPENDENCY_TABLESPACE entry means that the referenced
  * object is a tablespace mentioned in a relation without storage.  The
  * referenced object must be a pg_tablespace entry.  (Relations that have
  * storage don't need this: they are protected by the existence of a physical
@@ -78,7 +71,6 @@ typedef enum DependencyType
  */
 typedef enum SharedDependencyType
 {
-	SHARED_DEPENDENCY_PIN = 'p',
 	SHARED_DEPENDENCY_OWNER = 'o',
 	SHARED_DEPENDENCY_ACL = 'a',
 	SHARED_DEPENDENCY_POLICY = 'r',
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
index 606a2a8e19..55edbabb78 100644
--- a/src/include/catalog/pg_depend.h
+++ b/src/include/catalog/pg_depend.h
@@ -4,8 +4,9 @@
  *	  definition of the "dependency" system catalog (pg_depend)
  *
  * pg_depend has no preloaded contents, so there is no pg_depend.dat
- * file; system-defined dependencies are loaded into it during a late stage
- * of the initdb process.
+ * file; dependencies for system-defined objects are loaded into it
+ * on-the-fly during initdb.  Most built-in objects are pinned anyway,
+ * and hence need no explicit entries in pg_depend.
  *
  * NOTE: we do not represent all possible dependency pairs in pg_depend;
  * for example, there's not much value in creating an explicit dependency
@@ -42,11 +43,9 @@ CATALOG(pg_depend,2608,DependRelationId)
 {
 	/*
 	 * Identification of the dependent (referencing) object.
-	 *
-	 * These fields are all zeroes for a DEPENDENCY_PIN entry.
 	 */
-	Oid			classid BKI_LOOKUP_OPT(pg_class);	/* OID of table containing
-													 * object */
+	Oid			classid BKI_LOOKUP(pg_class);	/* OID of table containing
+												 * object */
 	Oid			objid;			/* OID of object itself */
 	int32		objsubid;		/* column number, or 0 if not used */
 
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f4957653ae..df712af5ef 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -3296,6 +3296,10 @@
   proname => 'pg_nextoid', provolatile => 'v', proparallel => 'u',
   prorettype => 'oid', proargtypes => 'regclass name regclass',
   prosrc => 'pg_nextoid' },
+{ oid => '8922', descr => 'stop making pinned objects during initdb',
+  proname => 'pg_stop_making_pinned_objects', provolatile => 'v',
+  proparallel => 'u', prorettype => 'void', proargtypes => '',
+  prosrc => 'pg_stop_making_pinned_objects' },
 
 { oid => '1579', descr => 'I/O',
   proname => 'varbit_in', prorettype => 'varbit',
diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h
index 4faa95794d..4223717805 100644
--- a/src/include/catalog/pg_shdepend.h
+++ b/src/include/catalog/pg_shdepend.h
@@ -4,8 +4,9 @@
  *	  definition of the "shared dependency" system catalog (pg_shdepend)
  *
  * pg_shdepend has no preloaded contents, so there is no pg_shdepend.dat
- * file; system-defined dependencies are loaded into it during a late stage
- * of the initdb process.
+ * file; dependencies for system-defined objects are loaded into it
+ * on-the-fly during initdb.  Most built-in objects are pinned anyway,
+ * and hence need no explicit entries in pg_shdepend.
  *
  * NOTE: we do not represent all possible dependency pairs in pg_shdepend;
  * for example, there's not much value in creating an explicit dependency
@@ -39,13 +40,12 @@ CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION
 	/*
 	 * Identification of the dependent (referencing) object.
 	 *
-	 * These fields are all zeroes for a DEPENDENCY_PIN entry.  Also, dbid can
-	 * be zero to denote a shared object.
+	 * Note that dbid can be zero to denote a shared object.
 	 */
 	Oid			dbid BKI_LOOKUP_OPT(pg_database);	/* OID of database
 													 * containing object */
-	Oid			classid BKI_LOOKUP_OPT(pg_class);	/* OID of table containing
-													 * object */
+	Oid			classid BKI_LOOKUP(pg_class);	/* OID of table containing
+												 * object */
 	Oid			objid;			/* OID of object itself */
 	int32		objsubid;		/* column number, or 0 if not used */
 
diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out
index 9ebe28a78d..9637c0f085 100644
--- a/src/test/regress/expected/misc_sanity.out
+++ b/src/test/regress/expected/misc_sanity.out
@@ -11,75 +11,36 @@
 -- NB: run this test early, because some later tests create bogus entries.
 -- **************** pg_depend ****************
 -- Look for illegal values in pg_depend fields.
--- classid/objid can be zero, but only in 'p' entries
 SELECT *
 FROM pg_depend as d1
 WHERE refclassid = 0 OR refobjid = 0 OR
-      deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR
-      (deptype != 'p' AND (classid = 0 OR objid = 0)) OR
-      (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0));
+      classid = 0 OR objid = 0 OR
+      deptype NOT IN ('a', 'e', 'i', 'n', 'x', 'P', 'S');
+ classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion 
+---------+-------+----------+------------+----------+-------------+---------+---------------
+(0 rows)
+
+-- refobjversion should only appear in normal dependencies on collations.
+SELECT *
+FROM pg_depend as d1
+WHERE refobjversion IS NOT NULL AND
+      (refclassid != 'pg_collation'::regclass OR
+       deptype != 'n');
  classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion 
 ---------+-------+----------+------------+----------+-------------+---------+---------------
 (0 rows)
 
 -- **************** pg_shdepend ****************
 -- Look for illegal values in pg_shdepend fields.
--- classid/objid can be zero, but only in 'p' entries
 SELECT *
 FROM pg_shdepend as d1
 WHERE refclassid = 0 OR refobjid = 0 OR
-      deptype NOT IN ('a', 'o', 'p', 'r') OR
-      (deptype != 'p' AND (classid = 0 OR objid = 0)) OR
-      (deptype = 'p' AND (dbid != 0 OR classid != 0 OR objid != 0 OR objsubid != 0));
+      classid = 0 OR objid = 0 OR
+      deptype NOT IN ('a', 'o', 'r', 't');
  dbid | classid | objid | objsubid | refclassid | refobjid | deptype 
 ------+---------+-------+----------+------------+----------+---------
 (0 rows)
 
--- Check each OID-containing system catalog to see if its lowest-numbered OID
--- is pinned.  If not, and if that OID was generated during initdb, then
--- perhaps initdb forgot to scan that catalog for pinnable entries.
--- Generally, it's okay for a catalog to be listed in the output of this
--- test if that catalog is scanned by initdb.c's setup_depend() function;
--- whatever OID the test is complaining about must have been added later
--- in initdb, where it intentionally isn't pinned.  Legitimate exceptions
--- to that rule are listed in the comments in setup_depend().
--- Currently, pg_rewrite is also listed by this check, even though it is
--- covered by setup_depend().  That happens because there are no rules in
--- the pinned data, but initdb creates some intentionally-not-pinned views.
-do $$
-declare relnm text;
-  reloid oid;
-  shared bool;
-  lowoid oid;
-  pinned bool;
-begin
-for relnm, reloid, shared in
-  select relname, oid, relisshared from pg_class
-  where EXISTS(
-      SELECT * FROM pg_attribute
-      WHERE attrelid = pg_class.oid AND attname = 'oid')
-    and relkind = 'r' and oid < 16384 order by 1
-loop
-  execute 'select min(oid) from ' || relnm into lowoid;
-  continue when lowoid is null or lowoid >= 16384;
-  if shared then
-    pinned := exists(select 1 from pg_shdepend
-                     where refclassid = reloid and refobjid = lowoid
-                     and deptype = 'p');
-  else
-    pinned := exists(select 1 from pg_depend
-                     where refclassid = reloid and refobjid = lowoid
-                     and deptype = 'p');
-  end if;
-  if not pinned then
-    raise notice '% contains unpinned initdb-created object(s)', relnm;
-  end if;
-end loop;
-end$$;
-NOTICE:  pg_database contains unpinned initdb-created object(s)
-NOTICE:  pg_extension contains unpinned initdb-created object(s)
-NOTICE:  pg_rewrite contains unpinned initdb-created object(s)
-NOTICE:  pg_tablespace contains unpinned initdb-created object(s)
 -- **************** pg_class ****************
 -- Look for system tables with varlena columns but no toast table. All
 -- system tables with toastable columns should have toast tables, with
diff --git a/src/test/regress/sql/misc_sanity.sql b/src/test/regress/sql/misc_sanity.sql
index 9699f5cc3b..6f55c9ef10 100644
--- a/src/test/regress/sql/misc_sanity.sql
+++ b/src/test/regress/sql/misc_sanity.sql
@@ -14,70 +14,32 @@
 -- **************** pg_depend ****************
 
 -- Look for illegal values in pg_depend fields.
--- classid/objid can be zero, but only in 'p' entries
 
 SELECT *
 FROM pg_depend as d1
 WHERE refclassid = 0 OR refobjid = 0 OR
-      deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR
-      (deptype != 'p' AND (classid = 0 OR objid = 0)) OR
-      (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0));
+      classid = 0 OR objid = 0 OR
+      deptype NOT IN ('a', 'e', 'i', 'n', 'x', 'P', 'S');
+
+-- refobjversion should only appear in normal dependencies on collations.
+
+SELECT *
+FROM pg_depend as d1
+WHERE refobjversion IS NOT NULL AND
+      (refclassid != 'pg_collation'::regclass OR
+       deptype != 'n');
+
 
 -- **************** pg_shdepend ****************
 
 -- Look for illegal values in pg_shdepend fields.
--- classid/objid can be zero, but only in 'p' entries
 
 SELECT *
 FROM pg_shdepend as d1
 WHERE refclassid = 0 OR refobjid = 0 OR
-      deptype NOT IN ('a', 'o', 'p', 'r') OR
-      (deptype != 'p' AND (classid = 0 OR objid = 0)) OR
-      (deptype = 'p' AND (dbid != 0 OR classid != 0 OR objid != 0 OR objsubid != 0));
-
-
--- Check each OID-containing system catalog to see if its lowest-numbered OID
--- is pinned.  If not, and if that OID was generated during initdb, then
--- perhaps initdb forgot to scan that catalog for pinnable entries.
--- Generally, it's okay for a catalog to be listed in the output of this
--- test if that catalog is scanned by initdb.c's setup_depend() function;
--- whatever OID the test is complaining about must have been added later
--- in initdb, where it intentionally isn't pinned.  Legitimate exceptions
--- to that rule are listed in the comments in setup_depend().
--- Currently, pg_rewrite is also listed by this check, even though it is
--- covered by setup_depend().  That happens because there are no rules in
--- the pinned data, but initdb creates some intentionally-not-pinned views.
-
-do $$
-declare relnm text;
-  reloid oid;
-  shared bool;
-  lowoid oid;
-  pinned bool;
-begin
-for relnm, reloid, shared in
-  select relname, oid, relisshared from pg_class
-  where EXISTS(
-      SELECT * FROM pg_attribute
-      WHERE attrelid = pg_class.oid AND attname = 'oid')
-    and relkind = 'r' and oid < 16384 order by 1
-loop
-  execute 'select min(oid) from ' || relnm into lowoid;
-  continue when lowoid is null or lowoid >= 16384;
-  if shared then
-    pinned := exists(select 1 from pg_shdepend
-                     where refclassid = reloid and refobjid = lowoid
-                     and deptype = 'p');
-  else
-    pinned := exists(select 1 from pg_depend
-                     where refclassid = reloid and refobjid = lowoid
-                     and deptype = 'p');
-  end if;
-  if not pinned then
-    raise notice '% contains unpinned initdb-created object(s)', relnm;
-  end if;
-end loop;
-end$$;
+      classid = 0 OR objid = 0 OR
+      deptype NOT IN ('a', 'o', 'r', 't');
+
 
 -- **************** pg_class ****************
 
