<entry><type>setof oid</type></entry>
        <entry>get the set of database OIDs that have objects in the tablespace</entry>
       </row>
+      <row>
+       <entry><literal><function>pg_describe_object(<parameter>catalog_id</parameter>, <parameter>object_id</parameter>, <parameter>object_sub_id</parameter>)</function>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get description of a database object</entry>
+      </row>
       <row>
        <entry><literal><function>pg_typeof(<parameter>any</parameter>)</function></literal></entry>
        <entry><type>regtype</type></entry>
    <structname>pg_class</> catalogs.
   </para>
 
+  <para>
+   <function>pg_describe_object</function> returns a description of a database
+   object specified by catalog OID, object OID and a (possibly zero) sub-object ID.
+   This is useful to determine the identity of an object as stored in the
+   <structname>pg_depend</structname> catalog.
+  </para>
+
   <para>
    <function>pg_typeof</function> returns the OID of the data type of the
    value that is passed to it.  This can be helpful for troubleshooting or
 
 ObjectClass
 getObjectClass(const ObjectAddress *object)
 {
+   /* only pg_class entries can have nonzero objectSubId */
+   if (object->classId != RelationRelationId &&
+       object->objectSubId != 0)
+       elog(ERROR, "invalid objectSubId 0 for object class %u",
+            object->classId);
+
    switch (object->classId)
    {
        case RelationRelationId:
            return OCLASS_CLASS;
 
        case ProcedureRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_PROC;
 
        case TypeRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TYPE;
 
        case CastRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_CAST;
 
        case ConstraintRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_CONSTRAINT;
 
        case ConversionRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_CONVERSION;
 
        case AttrDefaultRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_DEFAULT;
 
        case LanguageRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_LANGUAGE;
 
        case LargeObjectRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_LARGEOBJECT;
 
        case OperatorRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_OPERATOR;
 
        case OperatorClassRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_OPCLASS;
 
        case OperatorFamilyRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_OPFAMILY;
 
        case AccessMethodOperatorRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_AMOP;
 
        case AccessMethodProcedureRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_AMPROC;
 
        case RewriteRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_REWRITE;
 
        case TriggerRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TRIGGER;
 
        case NamespaceRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_SCHEMA;
 
        case TSParserRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TSPARSER;
 
        case TSDictionaryRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TSDICT;
 
        case TSTemplateRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TSTEMPLATE;
 
        case TSConfigRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TSCONFIG;
 
        case AuthIdRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_ROLE;
 
        case DatabaseRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_DATABASE;
 
        case TableSpaceRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_TBLSPACE;
 
        case ForeignDataWrapperRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_FDW;
 
        case ForeignServerRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_FOREIGN_SERVER;
 
        case UserMappingRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_USER_MAPPING;
 
        case DefaultAclRelationId:
-           Assert(object->objectSubId == 0);
            return OCLASS_DEFACL;
    }
 
    ReleaseSysCache(amTup);
    ReleaseSysCache(opfTup);
 }
+
+/*
+ * SQL-level callable version of getObjectDescription
+ */
+Datum
+pg_describe_object(PG_FUNCTION_ARGS)
+{
+   Oid         classid = PG_GETARG_OID(0);
+   Oid         objid = PG_GETARG_OID(1);
+   int32       subobjid = PG_GETARG_INT32(2);
+   char       *description = NULL;
+   ObjectAddress address;
+
+   /* for "pinned" items in pg_depend, return null */
+   if (!OidIsValid(classid) && !OidIsValid(objid))
+       PG_RETURN_NULL();
+
+   address.classId = classid;
+   address.objectId = objid;
+   address.objectSubId = subobjid;
+
+   description = getObjectDescription(&address);
+   PG_RETURN_TEXT_P(cstring_to_text(description));
+}
 
 DATA(insert OID = 1065 (  pg_prepared_xact PGNSP PGUID 12 1 1000 0 f f f t t v 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ pg_prepared_xact _null_ _null_ _null_ ));
 DESCR("view two-phase transactions");
 
+DATA(insert OID = 3537 (  pg_describe_object       PGNSP PGUID 12 1 0 0 f f f t f s 3 0 25 "26 26 23" _null_ _null_ _null_ _null_ pg_describe_object _null_ _null_ _null_ ));
+
 DATA(insert OID = 2079 (  pg_table_is_visible      PGNSP PGUID 12 1 0 0 f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ pg_table_is_visible _null_ _null_ _null_ ));
 DESCR("is table visible in search path?");
 DATA(insert OID = 2080 (  pg_type_is_visible       PGNSP PGUID 12 1 0 0 f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ pg_type_is_visible _null_ _null_ _null_ ));