Add pg_describe_object function
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 18 Nov 2010 19:33:48 +0000 (16:33 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 18 Nov 2010 20:06:19 +0000 (17:06 -0300)
This function is useful to obtain textual descriptions of objects as
stored in pg_depend.

doc/src/sgml/func.sgml
src/backend/catalog/dependency.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index 1be9f90fe5ed4943ba92c5ff26f0dba9cef0a7e5..11dd3bc6f9b14c21a554a70f3f1d7316d4e7a48d 100644 (file)
@@ -12847,6 +12847,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <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>
@@ -12940,6 +12945,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
    <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
index bb14a438b0a3beaf3bd50bfbb45976f77b85273c..c4ccb5fb2aa21c6ac4cefe8d5976b0c6ea7bb6a0 100644 (file)
@@ -1982,6 +1982,12 @@ free_object_addresses(ObjectAddresses *addrs)
 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:
@@ -1989,111 +1995,84 @@ getObjectClass(const ObjectAddress *object)
            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;
    }
 
@@ -2807,3 +2786,27 @@ getOpFamilyDescription(StringInfo buffer, Oid opfid)
    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));
+}
index d6b6c71ba5dbccff6ebbd5713d359497e2b417b8..e168805ffdd7c25e9654d1a74b7e9ca1fc75d475 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201011151
+#define CATALOG_VERSION_NO 201011181
 
 #endif
index 8e5f50293fe6d92b44299b7db08eb6a45b31d9b1..3e17eff0bf4ec74fd43d785cd5ce5f2e76df5c38 100644 (file)
@@ -3333,6 +3333,8 @@ DESCR("view system lock information");
 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_ ));
index f4b2a962c8168b692d077c80c55dcb12a53252f8..020ce3ce2ed5da3e29e7d4349fe5471230740b87 100644 (file)
@@ -1045,6 +1045,9 @@ extern Datum window_nth_value(PG_FUNCTION_ARGS);
 /* access/transam/twophase.c */
 extern Datum pg_prepared_xact(PG_FUNCTION_ARGS);
 
+/* catalogs/dependency.c */
+extern Datum pg_describe_object(PG_FUNCTION_ARGS);
+
 /* commands/constraint.c */
 extern Datum unique_key_recheck(PG_FUNCTION_ARGS);