LCOV - code coverage report
Current view: top level - src/backend/catalog - objectaddress.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 1485 1785 83.2 %
Date: 2017-09-29 13:40:31 Functions: 44 46 95.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * objectaddress.c
       4             :  *    functions for working with ObjectAddresses
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/catalog/objectaddress.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include "access/htup_details.h"
      19             : #include "access/sysattr.h"
      20             : #include "catalog/catalog.h"
      21             : #include "catalog/indexing.h"
      22             : #include "catalog/objectaddress.h"
      23             : #include "catalog/pg_am.h"
      24             : #include "catalog/pg_amop.h"
      25             : #include "catalog/pg_amproc.h"
      26             : #include "catalog/pg_attrdef.h"
      27             : #include "catalog/pg_authid.h"
      28             : #include "catalog/pg_cast.h"
      29             : #include "catalog/pg_default_acl.h"
      30             : #include "catalog/pg_event_trigger.h"
      31             : #include "catalog/pg_collation.h"
      32             : #include "catalog/pg_constraint.h"
      33             : #include "catalog/pg_constraint_fn.h"
      34             : #include "catalog/pg_conversion.h"
      35             : #include "catalog/pg_database.h"
      36             : #include "catalog/pg_extension.h"
      37             : #include "catalog/pg_foreign_data_wrapper.h"
      38             : #include "catalog/pg_foreign_server.h"
      39             : #include "catalog/pg_language.h"
      40             : #include "catalog/pg_largeobject.h"
      41             : #include "catalog/pg_largeobject_metadata.h"
      42             : #include "catalog/pg_namespace.h"
      43             : #include "catalog/pg_opclass.h"
      44             : #include "catalog/pg_opfamily.h"
      45             : #include "catalog/pg_operator.h"
      46             : #include "catalog/pg_proc.h"
      47             : #include "catalog/pg_policy.h"
      48             : #include "catalog/pg_publication.h"
      49             : #include "catalog/pg_publication_rel.h"
      50             : #include "catalog/pg_rewrite.h"
      51             : #include "catalog/pg_statistic_ext.h"
      52             : #include "catalog/pg_subscription.h"
      53             : #include "catalog/pg_tablespace.h"
      54             : #include "catalog/pg_transform.h"
      55             : #include "catalog/pg_trigger.h"
      56             : #include "catalog/pg_ts_config.h"
      57             : #include "catalog/pg_ts_dict.h"
      58             : #include "catalog/pg_ts_parser.h"
      59             : #include "catalog/pg_ts_template.h"
      60             : #include "catalog/pg_type.h"
      61             : #include "catalog/pg_user_mapping.h"
      62             : #include "commands/dbcommands.h"
      63             : #include "commands/defrem.h"
      64             : #include "commands/event_trigger.h"
      65             : #include "commands/extension.h"
      66             : #include "commands/policy.h"
      67             : #include "commands/proclang.h"
      68             : #include "commands/tablespace.h"
      69             : #include "commands/trigger.h"
      70             : #include "foreign/foreign.h"
      71             : #include "funcapi.h"
      72             : #include "libpq/be-fsstubs.h"
      73             : #include "miscadmin.h"
      74             : #include "nodes/makefuncs.h"
      75             : #include "parser/parse_func.h"
      76             : #include "parser/parse_oper.h"
      77             : #include "parser/parse_type.h"
      78             : #include "rewrite/rewriteSupport.h"
      79             : #include "storage/lmgr.h"
      80             : #include "storage/sinval.h"
      81             : #include "utils/builtins.h"
      82             : #include "utils/fmgroids.h"
      83             : #include "utils/lsyscache.h"
      84             : #include "utils/memutils.h"
      85             : #include "utils/regproc.h"
      86             : #include "utils/syscache.h"
      87             : #include "utils/tqual.h"
      88             : 
      89             : /*
      90             :  * ObjectProperty
      91             :  *
      92             :  * This array provides a common part of system object structure; to help
      93             :  * consolidate routines to handle various kind of object classes.
      94             :  */
      95             : typedef struct
      96             : {
      97             :     Oid         class_oid;      /* oid of catalog */
      98             :     Oid         oid_index_oid;  /* oid of index on system oid column */
      99             :     int         oid_catcache_id;    /* id of catcache on system oid column  */
     100             :     int         name_catcache_id;   /* id of catcache on (name,namespace), or
     101             :                                      * (name) if the object does not live in a
     102             :                                      * namespace */
     103             :     AttrNumber  attnum_name;    /* attnum of name field */
     104             :     AttrNumber  attnum_namespace;   /* attnum of namespace field */
     105             :     AttrNumber  attnum_owner;   /* attnum of owner field */
     106             :     AttrNumber  attnum_acl;     /* attnum of acl field */
     107             :     AclObjectKind acl_kind;     /* ACL_KIND_* of this object type */
     108             :     bool        is_nsp_name_unique; /* can the nsp/name combination (or name
     109             :                                      * alone, if there's no namespace) be
     110             :                                      * considered a unique identifier for an
     111             :                                      * object of this class? */
     112             : } ObjectPropertyType;
     113             : 
     114             : static const ObjectPropertyType ObjectProperty[] =
     115             : {
     116             :     {
     117             :         AccessMethodRelationId,
     118             :         AmOidIndexId,
     119             :         AMOID,
     120             :         AMNAME,
     121             :         Anum_pg_am_amname,
     122             :         InvalidAttrNumber,
     123             :         InvalidAttrNumber,
     124             :         InvalidAttrNumber,
     125             :         -1,
     126             :         true
     127             :     },
     128             :     {
     129             :         CastRelationId,
     130             :         CastOidIndexId,
     131             :         -1,
     132             :         -1,
     133             :         InvalidAttrNumber,
     134             :         InvalidAttrNumber,
     135             :         InvalidAttrNumber,
     136             :         InvalidAttrNumber,
     137             :         -1,
     138             :         false
     139             :     },
     140             :     {
     141             :         CollationRelationId,
     142             :         CollationOidIndexId,
     143             :         COLLOID,
     144             :         -1,                     /* COLLNAMEENCNSP also takes encoding */
     145             :         Anum_pg_collation_collname,
     146             :         Anum_pg_collation_collnamespace,
     147             :         Anum_pg_collation_collowner,
     148             :         InvalidAttrNumber,
     149             :         ACL_KIND_COLLATION,
     150             :         true
     151             :     },
     152             :     {
     153             :         ConstraintRelationId,
     154             :         ConstraintOidIndexId,
     155             :         CONSTROID,
     156             :         -1,
     157             :         Anum_pg_constraint_conname,
     158             :         Anum_pg_constraint_connamespace,
     159             :         InvalidAttrNumber,
     160             :         InvalidAttrNumber,
     161             :         -1,
     162             :         false
     163             :     },
     164             :     {
     165             :         ConversionRelationId,
     166             :         ConversionOidIndexId,
     167             :         CONVOID,
     168             :         CONNAMENSP,
     169             :         Anum_pg_conversion_conname,
     170             :         Anum_pg_conversion_connamespace,
     171             :         Anum_pg_conversion_conowner,
     172             :         InvalidAttrNumber,
     173             :         ACL_KIND_CONVERSION,
     174             :         true
     175             :     },
     176             :     {
     177             :         DatabaseRelationId,
     178             :         DatabaseOidIndexId,
     179             :         DATABASEOID,
     180             :         -1,
     181             :         Anum_pg_database_datname,
     182             :         InvalidAttrNumber,
     183             :         Anum_pg_database_datdba,
     184             :         Anum_pg_database_datacl,
     185             :         ACL_KIND_DATABASE,
     186             :         true
     187             :     },
     188             :     {
     189             :         ExtensionRelationId,
     190             :         ExtensionOidIndexId,
     191             :         -1,
     192             :         -1,
     193             :         Anum_pg_extension_extname,
     194             :         InvalidAttrNumber,      /* extension doesn't belong to extnamespace */
     195             :         Anum_pg_extension_extowner,
     196             :         InvalidAttrNumber,
     197             :         ACL_KIND_EXTENSION,
     198             :         true
     199             :     },
     200             :     {
     201             :         ForeignDataWrapperRelationId,
     202             :         ForeignDataWrapperOidIndexId,
     203             :         FOREIGNDATAWRAPPEROID,
     204             :         FOREIGNDATAWRAPPERNAME,
     205             :         Anum_pg_foreign_data_wrapper_fdwname,
     206             :         InvalidAttrNumber,
     207             :         Anum_pg_foreign_data_wrapper_fdwowner,
     208             :         Anum_pg_foreign_data_wrapper_fdwacl,
     209             :         ACL_KIND_FDW,
     210             :         true
     211             :     },
     212             :     {
     213             :         ForeignServerRelationId,
     214             :         ForeignServerOidIndexId,
     215             :         FOREIGNSERVEROID,
     216             :         FOREIGNSERVERNAME,
     217             :         Anum_pg_foreign_server_srvname,
     218             :         InvalidAttrNumber,
     219             :         Anum_pg_foreign_server_srvowner,
     220             :         Anum_pg_foreign_server_srvacl,
     221             :         ACL_KIND_FOREIGN_SERVER,
     222             :         true
     223             :     },
     224             :     {
     225             :         ProcedureRelationId,
     226             :         ProcedureOidIndexId,
     227             :         PROCOID,
     228             :         -1,                     /* PROCNAMEARGSNSP also takes argument types */
     229             :         Anum_pg_proc_proname,
     230             :         Anum_pg_proc_pronamespace,
     231             :         Anum_pg_proc_proowner,
     232             :         Anum_pg_proc_proacl,
     233             :         ACL_KIND_PROC,
     234             :         false
     235             :     },
     236             :     {
     237             :         LanguageRelationId,
     238             :         LanguageOidIndexId,
     239             :         LANGOID,
     240             :         LANGNAME,
     241             :         Anum_pg_language_lanname,
     242             :         InvalidAttrNumber,
     243             :         Anum_pg_language_lanowner,
     244             :         Anum_pg_language_lanacl,
     245             :         ACL_KIND_LANGUAGE,
     246             :         true
     247             :     },
     248             :     {
     249             :         LargeObjectMetadataRelationId,
     250             :         LargeObjectMetadataOidIndexId,
     251             :         -1,
     252             :         -1,
     253             :         InvalidAttrNumber,
     254             :         InvalidAttrNumber,
     255             :         Anum_pg_largeobject_metadata_lomowner,
     256             :         Anum_pg_largeobject_metadata_lomacl,
     257             :         ACL_KIND_LARGEOBJECT,
     258             :         false
     259             :     },
     260             :     {
     261             :         OperatorClassRelationId,
     262             :         OpclassOidIndexId,
     263             :         CLAOID,
     264             :         -1,                     /* CLAAMNAMENSP also takes opcmethod */
     265             :         Anum_pg_opclass_opcname,
     266             :         Anum_pg_opclass_opcnamespace,
     267             :         Anum_pg_opclass_opcowner,
     268             :         InvalidAttrNumber,
     269             :         ACL_KIND_OPCLASS,
     270             :         true
     271             :     },
     272             :     {
     273             :         OperatorRelationId,
     274             :         OperatorOidIndexId,
     275             :         OPEROID,
     276             :         -1,                     /* OPERNAMENSP also takes left and right type */
     277             :         Anum_pg_operator_oprname,
     278             :         Anum_pg_operator_oprnamespace,
     279             :         Anum_pg_operator_oprowner,
     280             :         InvalidAttrNumber,
     281             :         ACL_KIND_OPER,
     282             :         false
     283             :     },
     284             :     {
     285             :         OperatorFamilyRelationId,
     286             :         OpfamilyOidIndexId,
     287             :         OPFAMILYOID,
     288             :         -1,                     /* OPFAMILYAMNAMENSP also takes opfmethod */
     289             :         Anum_pg_opfamily_opfname,
     290             :         Anum_pg_opfamily_opfnamespace,
     291             :         Anum_pg_opfamily_opfowner,
     292             :         InvalidAttrNumber,
     293             :         ACL_KIND_OPFAMILY,
     294             :         true
     295             :     },
     296             :     {
     297             :         AuthIdRelationId,
     298             :         AuthIdOidIndexId,
     299             :         AUTHOID,
     300             :         AUTHNAME,
     301             :         Anum_pg_authid_rolname,
     302             :         InvalidAttrNumber,
     303             :         InvalidAttrNumber,
     304             :         InvalidAttrNumber,
     305             :         -1,
     306             :         true
     307             :     },
     308             :     {
     309             :         RewriteRelationId,
     310             :         RewriteOidIndexId,
     311             :         -1,
     312             :         -1,
     313             :         Anum_pg_rewrite_rulename,
     314             :         InvalidAttrNumber,
     315             :         InvalidAttrNumber,
     316             :         InvalidAttrNumber,
     317             :         -1,
     318             :         false
     319             :     },
     320             :     {
     321             :         NamespaceRelationId,
     322             :         NamespaceOidIndexId,
     323             :         NAMESPACEOID,
     324             :         NAMESPACENAME,
     325             :         Anum_pg_namespace_nspname,
     326             :         InvalidAttrNumber,
     327             :         Anum_pg_namespace_nspowner,
     328             :         Anum_pg_namespace_nspacl,
     329             :         ACL_KIND_NAMESPACE,
     330             :         true
     331             :     },
     332             :     {
     333             :         RelationRelationId,
     334             :         ClassOidIndexId,
     335             :         RELOID,
     336             :         RELNAMENSP,
     337             :         Anum_pg_class_relname,
     338             :         Anum_pg_class_relnamespace,
     339             :         Anum_pg_class_relowner,
     340             :         Anum_pg_class_relacl,
     341             :         ACL_KIND_CLASS,
     342             :         true
     343             :     },
     344             :     {
     345             :         TableSpaceRelationId,
     346             :         TablespaceOidIndexId,
     347             :         TABLESPACEOID,
     348             :         -1,
     349             :         Anum_pg_tablespace_spcname,
     350             :         InvalidAttrNumber,
     351             :         Anum_pg_tablespace_spcowner,
     352             :         Anum_pg_tablespace_spcacl,
     353             :         ACL_KIND_TABLESPACE,
     354             :         true
     355             :     },
     356             :     {
     357             :         TransformRelationId,
     358             :         TransformOidIndexId,
     359             :         TRFOID,
     360             :         InvalidAttrNumber
     361             :     },
     362             :     {
     363             :         TriggerRelationId,
     364             :         TriggerOidIndexId,
     365             :         -1,
     366             :         -1,
     367             :         Anum_pg_trigger_tgname,
     368             :         InvalidAttrNumber,
     369             :         InvalidAttrNumber,
     370             :         InvalidAttrNumber,
     371             :         -1,
     372             :         false
     373             :     },
     374             :     {
     375             :         PolicyRelationId,
     376             :         PolicyOidIndexId,
     377             :         -1,
     378             :         -1,
     379             :         Anum_pg_policy_polname,
     380             :         InvalidAttrNumber,
     381             :         InvalidAttrNumber,
     382             :         InvalidAttrNumber,
     383             :         -1,
     384             :         false
     385             :     },
     386             :     {
     387             :         EventTriggerRelationId,
     388             :         EventTriggerOidIndexId,
     389             :         EVENTTRIGGEROID,
     390             :         EVENTTRIGGERNAME,
     391             :         Anum_pg_event_trigger_evtname,
     392             :         InvalidAttrNumber,
     393             :         Anum_pg_event_trigger_evtowner,
     394             :         InvalidAttrNumber,
     395             :         ACL_KIND_EVENT_TRIGGER,
     396             :         true
     397             :     },
     398             :     {
     399             :         TSConfigRelationId,
     400             :         TSConfigOidIndexId,
     401             :         TSCONFIGOID,
     402             :         TSCONFIGNAMENSP,
     403             :         Anum_pg_ts_config_cfgname,
     404             :         Anum_pg_ts_config_cfgnamespace,
     405             :         Anum_pg_ts_config_cfgowner,
     406             :         InvalidAttrNumber,
     407             :         ACL_KIND_TSCONFIGURATION,
     408             :         true
     409             :     },
     410             :     {
     411             :         TSDictionaryRelationId,
     412             :         TSDictionaryOidIndexId,
     413             :         TSDICTOID,
     414             :         TSDICTNAMENSP,
     415             :         Anum_pg_ts_dict_dictname,
     416             :         Anum_pg_ts_dict_dictnamespace,
     417             :         Anum_pg_ts_dict_dictowner,
     418             :         InvalidAttrNumber,
     419             :         ACL_KIND_TSDICTIONARY,
     420             :         true
     421             :     },
     422             :     {
     423             :         TSParserRelationId,
     424             :         TSParserOidIndexId,
     425             :         TSPARSEROID,
     426             :         TSPARSERNAMENSP,
     427             :         Anum_pg_ts_parser_prsname,
     428             :         Anum_pg_ts_parser_prsnamespace,
     429             :         InvalidAttrNumber,
     430             :         InvalidAttrNumber,
     431             :         -1,
     432             :         true
     433             :     },
     434             :     {
     435             :         TSTemplateRelationId,
     436             :         TSTemplateOidIndexId,
     437             :         TSTEMPLATEOID,
     438             :         TSTEMPLATENAMENSP,
     439             :         Anum_pg_ts_template_tmplname,
     440             :         Anum_pg_ts_template_tmplnamespace,
     441             :         InvalidAttrNumber,
     442             :         InvalidAttrNumber,
     443             :         -1,
     444             :         true,
     445             :     },
     446             :     {
     447             :         TypeRelationId,
     448             :         TypeOidIndexId,
     449             :         TYPEOID,
     450             :         TYPENAMENSP,
     451             :         Anum_pg_type_typname,
     452             :         Anum_pg_type_typnamespace,
     453             :         Anum_pg_type_typowner,
     454             :         Anum_pg_type_typacl,
     455             :         ACL_KIND_TYPE,
     456             :         true
     457             :     },
     458             :     {
     459             :         PublicationRelationId,
     460             :         PublicationObjectIndexId,
     461             :         PUBLICATIONOID,
     462             :         PUBLICATIONNAME,
     463             :         Anum_pg_publication_pubname,
     464             :         InvalidAttrNumber,
     465             :         Anum_pg_publication_pubowner,
     466             :         InvalidAttrNumber,
     467             :         ACL_KIND_PUBLICATION,
     468             :         true
     469             :     },
     470             :     {
     471             :         SubscriptionRelationId,
     472             :         SubscriptionObjectIndexId,
     473             :         SUBSCRIPTIONOID,
     474             :         SUBSCRIPTIONNAME,
     475             :         Anum_pg_subscription_subname,
     476             :         InvalidAttrNumber,
     477             :         Anum_pg_subscription_subowner,
     478             :         InvalidAttrNumber,
     479             :         ACL_KIND_SUBSCRIPTION,
     480             :         true
     481             :     },
     482             :     {
     483             :         StatisticExtRelationId,
     484             :         StatisticExtOidIndexId,
     485             :         STATEXTOID,
     486             :         STATEXTNAMENSP,
     487             :         Anum_pg_statistic_ext_stxname,
     488             :         Anum_pg_statistic_ext_stxnamespace,
     489             :         Anum_pg_statistic_ext_stxowner,
     490             :         InvalidAttrNumber,      /* no ACL (same as relation) */
     491             :         ACL_KIND_STATISTICS,
     492             :         true
     493             :     }
     494             : };
     495             : 
     496             : /*
     497             :  * This struct maps the string object types as returned by
     498             :  * getObjectTypeDescription into ObjType enum values.  Note that some enum
     499             :  * values can be obtained by different names, and that some string object types
     500             :  * do not have corresponding values in the output enum.  The user of this map
     501             :  * must be careful to test for invalid values being returned.
     502             :  *
     503             :  * To ease maintenance, this follows the order of getObjectTypeDescription.
     504             :  */
     505             : static const struct object_type_map
     506             : {
     507             :     const char *tm_name;
     508             :     ObjectType  tm_type;
     509             : }
     510             : 
     511             :             ObjectTypeMap[] =
     512             : {
     513             :     /* OCLASS_CLASS, all kinds of relations */
     514             :     {
     515             :         "table", OBJECT_TABLE
     516             :     },
     517             :     {
     518             :         "index", OBJECT_INDEX
     519             :     },
     520             :     {
     521             :         "sequence", OBJECT_SEQUENCE
     522             :     },
     523             :     {
     524             :         "toast table", -1
     525             :     },                          /* unmapped */
     526             :     {
     527             :         "view", OBJECT_VIEW
     528             :     },
     529             :     {
     530             :         "materialized view", OBJECT_MATVIEW
     531             :     },
     532             :     {
     533             :         "composite type", -1
     534             :     },                          /* unmapped */
     535             :     {
     536             :         "foreign table", OBJECT_FOREIGN_TABLE
     537             :     },
     538             :     {
     539             :         "table column", OBJECT_COLUMN
     540             :     },
     541             :     {
     542             :         "index column", -1
     543             :     },                          /* unmapped */
     544             :     {
     545             :         "sequence column", -1
     546             :     },                          /* unmapped */
     547             :     {
     548             :         "toast table column", -1
     549             :     },                          /* unmapped */
     550             :     {
     551             :         "view column", -1
     552             :     },                          /* unmapped */
     553             :     {
     554             :         "materialized view column", -1
     555             :     },                          /* unmapped */
     556             :     {
     557             :         "composite type column", -1
     558             :     },                          /* unmapped */
     559             :     {
     560             :         "foreign table column", OBJECT_COLUMN
     561             :     },
     562             :     /* OCLASS_PROC */
     563             :     {
     564             :         "aggregate", OBJECT_AGGREGATE
     565             :     },
     566             :     {
     567             :         "function", OBJECT_FUNCTION
     568             :     },
     569             :     /* OCLASS_TYPE */
     570             :     {
     571             :         "type", OBJECT_TYPE
     572             :     },
     573             :     /* OCLASS_CAST */
     574             :     {
     575             :         "cast", OBJECT_CAST
     576             :     },
     577             :     /* OCLASS_COLLATION */
     578             :     {
     579             :         "collation", OBJECT_COLLATION
     580             :     },
     581             :     /* OCLASS_CONSTRAINT */
     582             :     {
     583             :         "table constraint", OBJECT_TABCONSTRAINT
     584             :     },
     585             :     {
     586             :         "domain constraint", OBJECT_DOMCONSTRAINT
     587             :     },
     588             :     /* OCLASS_CONVERSION */
     589             :     {
     590             :         "conversion", OBJECT_CONVERSION
     591             :     },
     592             :     /* OCLASS_DEFAULT */
     593             :     {
     594             :         "default value", OBJECT_DEFAULT
     595             :     },
     596             :     /* OCLASS_LANGUAGE */
     597             :     {
     598             :         "language", OBJECT_LANGUAGE
     599             :     },
     600             :     /* OCLASS_LARGEOBJECT */
     601             :     {
     602             :         "large object", OBJECT_LARGEOBJECT
     603             :     },
     604             :     /* OCLASS_OPERATOR */
     605             :     {
     606             :         "operator", OBJECT_OPERATOR
     607             :     },
     608             :     /* OCLASS_OPCLASS */
     609             :     {
     610             :         "operator class", OBJECT_OPCLASS
     611             :     },
     612             :     /* OCLASS_OPFAMILY */
     613             :     {
     614             :         "operator family", OBJECT_OPFAMILY
     615             :     },
     616             :     /* OCLASS_AM */
     617             :     {
     618             :         "access method", OBJECT_ACCESS_METHOD
     619             :     },
     620             :     /* OCLASS_AMOP */
     621             :     {
     622             :         "operator of access method", OBJECT_AMOP
     623             :     },
     624             :     /* OCLASS_AMPROC */
     625             :     {
     626             :         "function of access method", OBJECT_AMPROC
     627             :     },
     628             :     /* OCLASS_REWRITE */
     629             :     {
     630             :         "rule", OBJECT_RULE
     631             :     },
     632             :     /* OCLASS_TRIGGER */
     633             :     {
     634             :         "trigger", OBJECT_TRIGGER
     635             :     },
     636             :     /* OCLASS_SCHEMA */
     637             :     {
     638             :         "schema", OBJECT_SCHEMA
     639             :     },
     640             :     /* OCLASS_TSPARSER */
     641             :     {
     642             :         "text search parser", OBJECT_TSPARSER
     643             :     },
     644             :     /* OCLASS_TSDICT */
     645             :     {
     646             :         "text search dictionary", OBJECT_TSDICTIONARY
     647             :     },
     648             :     /* OCLASS_TSTEMPLATE */
     649             :     {
     650             :         "text search template", OBJECT_TSTEMPLATE
     651             :     },
     652             :     /* OCLASS_TSCONFIG */
     653             :     {
     654             :         "text search configuration", OBJECT_TSCONFIGURATION
     655             :     },
     656             :     /* OCLASS_ROLE */
     657             :     {
     658             :         "role", OBJECT_ROLE
     659             :     },
     660             :     /* OCLASS_DATABASE */
     661             :     {
     662             :         "database", OBJECT_DATABASE
     663             :     },
     664             :     /* OCLASS_TBLSPACE */
     665             :     {
     666             :         "tablespace", OBJECT_TABLESPACE
     667             :     },
     668             :     /* OCLASS_FDW */
     669             :     {
     670             :         "foreign-data wrapper", OBJECT_FDW
     671             :     },
     672             :     /* OCLASS_FOREIGN_SERVER */
     673             :     {
     674             :         "server", OBJECT_FOREIGN_SERVER
     675             :     },
     676             :     /* OCLASS_USER_MAPPING */
     677             :     {
     678             :         "user mapping", OBJECT_USER_MAPPING
     679             :     },
     680             :     /* OCLASS_DEFACL */
     681             :     {
     682             :         "default acl", OBJECT_DEFACL
     683             :     },
     684             :     /* OCLASS_EXTENSION */
     685             :     {
     686             :         "extension", OBJECT_EXTENSION
     687             :     },
     688             :     /* OCLASS_EVENT_TRIGGER */
     689             :     {
     690             :         "event trigger", OBJECT_EVENT_TRIGGER
     691             :     },
     692             :     /* OCLASS_POLICY */
     693             :     {
     694             :         "policy", OBJECT_POLICY
     695             :     },
     696             :     /* OCLASS_PUBLICATION */
     697             :     {
     698             :         "publication", OBJECT_PUBLICATION
     699             :     },
     700             :     /* OCLASS_PUBLICATION_REL */
     701             :     {
     702             :         "publication relation", OBJECT_PUBLICATION_REL
     703             :     },
     704             :     /* OCLASS_SUBSCRIPTION */
     705             :     {
     706             :         "subscription", OBJECT_SUBSCRIPTION
     707             :     },
     708             :     /* OCLASS_TRANSFORM */
     709             :     {
     710             :         "transform", OBJECT_TRANSFORM
     711             :     },
     712             :     /* OBJECT_STATISTIC_EXT */
     713             :     {
     714             :         "statistics object", OBJECT_STATISTIC_EXT
     715             :     }
     716             : };
     717             : 
     718             : const ObjectAddress InvalidObjectAddress =
     719             : {
     720             :     InvalidOid,
     721             :     InvalidOid,
     722             :     0
     723             : };
     724             : 
     725             : static ObjectAddress get_object_address_unqualified(ObjectType objtype,
     726             :                                Value *strval, bool missing_ok);
     727             : static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
     728             :                                List *object, Relation *relp,
     729             :                                LOCKMODE lockmode, bool missing_ok);
     730             : static ObjectAddress get_object_address_relobject(ObjectType objtype,
     731             :                              List *object, Relation *relp, bool missing_ok);
     732             : static ObjectAddress get_object_address_attribute(ObjectType objtype,
     733             :                              List *object, Relation *relp,
     734             :                              LOCKMODE lockmode, bool missing_ok);
     735             : static ObjectAddress get_object_address_attrdef(ObjectType objtype,
     736             :                            List *object, Relation *relp, LOCKMODE lockmode,
     737             :                            bool missing_ok);
     738             : static ObjectAddress get_object_address_type(ObjectType objtype,
     739             :                         TypeName *typename, bool missing_ok);
     740             : static ObjectAddress get_object_address_opcf(ObjectType objtype, List *object,
     741             :                         bool missing_ok);
     742             : static ObjectAddress get_object_address_opf_member(ObjectType objtype,
     743             :                               List *object, bool missing_ok);
     744             : 
     745             : static ObjectAddress get_object_address_usermapping(List *object,
     746             :                                bool missing_ok);
     747             : static ObjectAddress get_object_address_publication_rel(List *object,
     748             :                                    Relation *relp,
     749             :                                    bool missing_ok);
     750             : static ObjectAddress get_object_address_defacl(List *object,
     751             :                           bool missing_ok);
     752             : static const ObjectPropertyType *get_object_property_data(Oid class_id);
     753             : 
     754             : static void getRelationDescription(StringInfo buffer, Oid relid);
     755             : static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
     756             : static void getRelationTypeDescription(StringInfo buffer, Oid relid,
     757             :                            int32 objectSubId);
     758             : static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
     759             : static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
     760             : static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object);
     761             : static void getRelationIdentity(StringInfo buffer, Oid relid, List **object);
     762             : 
     763             : /*
     764             :  * Translate an object name and arguments (as passed by the parser) to an
     765             :  * ObjectAddress.
     766             :  *
     767             :  * The returned object will be locked using the specified lockmode.  If a
     768             :  * sub-object is looked up, the parent object will be locked instead.
     769             :  *
     770             :  * If the object is a relation or a child object of a relation (e.g. an
     771             :  * attribute or constraint), the relation is also opened and *relp receives
     772             :  * the open relcache entry pointer; otherwise, *relp is set to NULL.  This
     773             :  * is a bit grotty but it makes life simpler, since the caller will
     774             :  * typically need the relcache entry too.  Caller must close the relcache
     775             :  * entry when done with it.  The relation is locked with the specified lockmode
     776             :  * if the target object is the relation itself or an attribute, but for other
     777             :  * child objects, only AccessShareLock is acquired on the relation.
     778             :  *
     779             :  * If the object is not found, an error is thrown, unless missing_ok is
     780             :  * true.  In this case, no lock is acquired, relp is set to NULL, and the
     781             :  * returned address has objectId set to InvalidOid.
     782             :  *
     783             :  * We don't currently provide a function to release the locks acquired here;
     784             :  * typically, the lock must be held until commit to guard against a concurrent
     785             :  * drop operation.
     786             :  *
     787             :  * Note: If the object is not found, we don't give any indication of the
     788             :  * reason.  (It might have been a missing schema if the name was qualified, or
     789             :  * a nonexistent type name in case of a cast, function or operator; etc).
     790             :  * Currently there is only one caller that might be interested in such info, so
     791             :  * we don't spend much effort here.  If more callers start to care, it might be
     792             :  * better to add some support for that in this function.
     793             :  */
     794             : ObjectAddress
     795        1414 : get_object_address(ObjectType objtype, Node *object,
     796             :                    Relation *relp, LOCKMODE lockmode, bool missing_ok)
     797             : {
     798             :     ObjectAddress address;
     799        1414 :     ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
     800        1414 :     Relation    relation = NULL;
     801             :     uint64      inval_count;
     802             : 
     803             :     /* Some kind of lock must be taken. */
     804        1414 :     Assert(lockmode != NoLock);
     805             : 
     806             :     for (;;)
     807             :     {
     808             :         /*
     809             :          * Remember this value, so that, after looking up the object name and
     810             :          * locking it, we can check whether any invalidation messages have
     811             :          * been processed that might require a do-over.
     812             :          */
     813        1429 :         inval_count = SharedInvalidMessageCounter;
     814             : 
     815             :         /* Look up object address. */
     816        1429 :         switch (objtype)
     817             :         {
     818             :             case OBJECT_INDEX:
     819             :             case OBJECT_SEQUENCE:
     820             :             case OBJECT_TABLE:
     821             :             case OBJECT_VIEW:
     822             :             case OBJECT_MATVIEW:
     823             :             case OBJECT_FOREIGN_TABLE:
     824          70 :                 address =
     825          70 :                     get_relation_by_qualified_name(objtype, castNode(List, object),
     826             :                                                    &relation, lockmode,
     827             :                                                    missing_ok);
     828          30 :                 break;
     829             :             case OBJECT_COLUMN:
     830          41 :                 address =
     831          41 :                     get_object_address_attribute(objtype, castNode(List, object),
     832             :                                                  &relation, lockmode,
     833             :                                                  missing_ok);
     834          26 :                 break;
     835             :             case OBJECT_DEFAULT:
     836           8 :                 address =
     837           8 :                     get_object_address_attrdef(objtype, castNode(List, object),
     838             :                                                &relation, lockmode,
     839             :                                                missing_ok);
     840           2 :                 break;
     841             :             case OBJECT_RULE:
     842             :             case OBJECT_TRIGGER:
     843             :             case OBJECT_TABCONSTRAINT:
     844             :             case OBJECT_POLICY:
     845         162 :                 address = get_object_address_relobject(objtype, castNode(List, object),
     846             :                                                        &relation, missing_ok);
     847         125 :                 break;
     848             :             case OBJECT_DOMCONSTRAINT:
     849             :                 {
     850             :                     List       *objlist;
     851             :                     ObjectAddress domaddr;
     852             :                     char       *constrname;
     853             : 
     854           7 :                     objlist = castNode(List, object);
     855          14 :                     domaddr = get_object_address_type(OBJECT_DOMAIN,
     856           7 :                                                       linitial_node(TypeName, objlist),
     857             :                                                       missing_ok);
     858           5 :                     constrname = strVal(lsecond(objlist));
     859             : 
     860           5 :                     address.classId = ConstraintRelationId;
     861           5 :                     address.objectId = get_domain_constraint_oid(domaddr.objectId,
     862             :                                                                  constrname, missing_ok);
     863           4 :                     address.objectSubId = 0;
     864             : 
     865             :                 }
     866           4 :                 break;
     867             :             case OBJECT_DATABASE:
     868             :             case OBJECT_EXTENSION:
     869             :             case OBJECT_TABLESPACE:
     870             :             case OBJECT_ROLE:
     871             :             case OBJECT_SCHEMA:
     872             :             case OBJECT_LANGUAGE:
     873             :             case OBJECT_FDW:
     874             :             case OBJECT_FOREIGN_SERVER:
     875             :             case OBJECT_EVENT_TRIGGER:
     876             :             case OBJECT_ACCESS_METHOD:
     877             :             case OBJECT_PUBLICATION:
     878             :             case OBJECT_SUBSCRIPTION:
     879         173 :                 address = get_object_address_unqualified(objtype,
     880             :                                                          (Value *) object, missing_ok);
     881         151 :                 break;
     882             :             case OBJECT_TYPE:
     883             :             case OBJECT_DOMAIN:
     884         108 :                 address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
     885          97 :                 break;
     886             :             case OBJECT_AGGREGATE:
     887          48 :                 address.classId = ProcedureRelationId;
     888          48 :                 address.objectId = LookupAggWithArgs(castNode(ObjectWithArgs, object), missing_ok);
     889          32 :                 address.objectSubId = 0;
     890          32 :                 break;
     891             :             case OBJECT_FUNCTION:
     892         379 :                 address.classId = ProcedureRelationId;
     893         379 :                 address.objectId = LookupFuncWithArgs(castNode(ObjectWithArgs, object), missing_ok);
     894         364 :                 address.objectSubId = 0;
     895         364 :                 break;
     896             :             case OBJECT_OPERATOR:
     897          26 :                 address.classId = OperatorRelationId;
     898          26 :                 address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
     899          21 :                 address.objectSubId = 0;
     900          21 :                 break;
     901             :             case OBJECT_COLLATION:
     902           6 :                 address.classId = CollationRelationId;
     903           6 :                 address.objectId = get_collation_oid(castNode(List, object), missing_ok);
     904           6 :                 address.objectSubId = 0;
     905           6 :                 break;
     906             :             case OBJECT_CONVERSION:
     907         163 :                 address.classId = ConversionRelationId;
     908         163 :                 address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
     909         155 :                 address.objectSubId = 0;
     910         155 :                 break;
     911             :             case OBJECT_OPCLASS:
     912             :             case OBJECT_OPFAMILY:
     913          64 :                 address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
     914          50 :                 break;
     915             :             case OBJECT_AMOP:
     916             :             case OBJECT_AMPROC:
     917           8 :                 address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
     918           4 :                 break;
     919             :             case OBJECT_LARGEOBJECT:
     920           5 :                 address.classId = LargeObjectRelationId;
     921           5 :                 address.objectId = oidparse(object);
     922           4 :                 address.objectSubId = 0;
     923           4 :                 if (!LargeObjectExists(address.objectId))
     924             :                 {
     925           1 :                     if (!missing_ok)
     926           1 :                         ereport(ERROR,
     927             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
     928             :                                  errmsg("large object %u does not exist",
     929             :                                         address.objectId)));
     930             :                 }
     931           3 :                 break;
     932             :             case OBJECT_CAST:
     933             :                 {
     934          12 :                     TypeName   *sourcetype = linitial_node(TypeName, castNode(List, object));
     935          12 :                     TypeName   *targettype = lsecond_node(TypeName, castNode(List, object));
     936             :                     Oid         sourcetypeid;
     937             :                     Oid         targettypeid;
     938             : 
     939          12 :                     sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
     940          11 :                     targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
     941          11 :                     address.classId = CastRelationId;
     942          10 :                     address.objectId =
     943          11 :                         get_cast_oid(sourcetypeid, targettypeid, missing_ok);
     944          10 :                     address.objectSubId = 0;
     945             :                 }
     946          10 :                 break;
     947             :             case OBJECT_TRANSFORM:
     948             :                 {
     949           3 :                     TypeName   *typename = linitial_node(TypeName, castNode(List, object));
     950           3 :                     char       *langname = strVal(lsecond(castNode(List, object)));
     951           3 :                     Oid         type_id = LookupTypeNameOid(NULL, typename, missing_ok);
     952           2 :                     Oid         lang_id = get_language_oid(langname, missing_ok);
     953             : 
     954           2 :                     address.classId = TransformRelationId;
     955           2 :                     address.objectId =
     956           2 :                         get_transform_oid(type_id, lang_id, missing_ok);
     957           2 :                     address.objectSubId = 0;
     958             :                 }
     959           2 :                 break;
     960             :             case OBJECT_TSPARSER:
     961          16 :                 address.classId = TSParserRelationId;
     962          16 :                 address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
     963           9 :                 address.objectSubId = 0;
     964           9 :                 break;
     965             :             case OBJECT_TSDICTIONARY:
     966          39 :                 address.classId = TSDictionaryRelationId;
     967          39 :                 address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
     968          32 :                 address.objectSubId = 0;
     969          32 :                 break;
     970             :             case OBJECT_TSTEMPLATE:
     971          18 :                 address.classId = TSTemplateRelationId;
     972          18 :                 address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
     973          11 :                 address.objectSubId = 0;
     974          11 :                 break;
     975             :             case OBJECT_TSCONFIGURATION:
     976          39 :                 address.classId = TSConfigRelationId;
     977          39 :                 address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
     978          32 :                 address.objectSubId = 0;
     979          32 :                 break;
     980             :             case OBJECT_USER_MAPPING:
     981           5 :                 address = get_object_address_usermapping(castNode(List, object),
     982             :                                                          missing_ok);
     983           2 :                 break;
     984             :             case OBJECT_PUBLICATION_REL:
     985           5 :                 address = get_object_address_publication_rel(castNode(List, object),
     986             :                                                              &relation,
     987             :                                                              missing_ok);
     988           2 :                 break;
     989             :             case OBJECT_DEFACL:
     990           7 :                 address = get_object_address_defacl(castNode(List, object),
     991             :                                                     missing_ok);
     992           4 :                 break;
     993             :             case OBJECT_STATISTIC_EXT:
     994          17 :                 address.classId = StatisticExtRelationId;
     995          17 :                 address.objectId = get_statistics_object_oid(castNode(List, object),
     996             :                                                              missing_ok);
     997          17 :                 address.objectSubId = 0;
     998          17 :                 break;
     999             :             default:
    1000           0 :                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1001             :                 /* placate compiler, in case it thinks elog might return */
    1002             :                 address.classId = InvalidOid;
    1003             :                 address.objectId = InvalidOid;
    1004             :                 address.objectSubId = 0;
    1005             :         }
    1006             : 
    1007             :         /*
    1008             :          * If we could not find the supplied object, return without locking.
    1009             :          */
    1010        1191 :         if (!OidIsValid(address.objectId))
    1011             :         {
    1012          58 :             Assert(missing_ok);
    1013          58 :             return address;
    1014             :         }
    1015             : 
    1016             :         /*
    1017             :          * If we're retrying, see if we got the same answer as last time.  If
    1018             :          * so, we're done; if not, we locked the wrong thing, so give up our
    1019             :          * lock.
    1020             :          */
    1021        1133 :         if (OidIsValid(old_address.classId))
    1022             :         {
    1023          15 :             if (old_address.classId == address.classId
    1024          15 :                 && old_address.objectId == address.objectId
    1025          15 :                 && old_address.objectSubId == address.objectSubId)
    1026          15 :                 break;
    1027           0 :             if (old_address.classId != RelationRelationId)
    1028             :             {
    1029           0 :                 if (IsSharedRelation(old_address.classId))
    1030           0 :                     UnlockSharedObject(old_address.classId,
    1031             :                                        old_address.objectId,
    1032             :                                        0, lockmode);
    1033             :                 else
    1034           0 :                     UnlockDatabaseObject(old_address.classId,
    1035             :                                          old_address.objectId,
    1036             :                                          0, lockmode);
    1037             :             }
    1038             :         }
    1039             : 
    1040             :         /*
    1041             :          * If we're dealing with a relation or attribute, then the relation is
    1042             :          * already locked.  Otherwise, we lock it now.
    1043             :          */
    1044        1118 :         if (address.classId != RelationRelationId)
    1045             :         {
    1046        1062 :             if (IsSharedRelation(address.classId))
    1047          11 :                 LockSharedObject(address.classId, address.objectId, 0,
    1048             :                                  lockmode);
    1049             :             else
    1050        1051 :                 LockDatabaseObject(address.classId, address.objectId, 0,
    1051             :                                    lockmode);
    1052             :         }
    1053             : 
    1054             :         /*
    1055             :          * At this point, we've resolved the name to an OID and locked the
    1056             :          * corresponding database object.  However, it's possible that by the
    1057             :          * time we acquire the lock on the object, concurrent DDL has modified
    1058             :          * the database in such a way that the name we originally looked up no
    1059             :          * longer resolves to that OID.
    1060             :          *
    1061             :          * We can be certain that this isn't an issue if (a) no shared
    1062             :          * invalidation messages have been processed or (b) we've locked a
    1063             :          * relation somewhere along the line.  All the relation name lookups
    1064             :          * in this module ultimately use RangeVarGetRelid() to acquire a
    1065             :          * relation lock, and that function protects against the same kinds of
    1066             :          * races we're worried about here.  Even when operating on a
    1067             :          * constraint, rule, or trigger, we still acquire AccessShareLock on
    1068             :          * the relation, which is enough to freeze out any concurrent DDL.
    1069             :          *
    1070             :          * In all other cases, however, it's possible that the name we looked
    1071             :          * up no longer refers to the object we locked, so we retry the lookup
    1072             :          * and see whether we get the same answer.
    1073             :          */
    1074        1118 :         if (inval_count == SharedInvalidMessageCounter || relation != NULL)
    1075             :             break;
    1076          15 :         old_address = address;
    1077          15 :     }
    1078             : 
    1079             :     /* Return the object address and the relation. */
    1080        1118 :     *relp = relation;
    1081        1118 :     return address;
    1082             : }
    1083             : 
    1084             : /*
    1085             :  * Return an ObjectAddress based on a RangeVar and an object name. The
    1086             :  * name of the relation identified by the RangeVar is prepended to the
    1087             :  * (possibly empty) list passed in as object. This is useful to find
    1088             :  * the ObjectAddress of objects that depend on a relation. All other
    1089             :  * considerations are exactly as for get_object_address above.
    1090             :  */
    1091             : ObjectAddress
    1092           0 : get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object,
    1093             :                       Relation *relp, LOCKMODE lockmode,
    1094             :                       bool missing_ok)
    1095             : {
    1096           0 :     if (rel)
    1097             :     {
    1098           0 :         object = lcons(makeString(rel->relname), object);
    1099           0 :         if (rel->schemaname)
    1100           0 :             object = lcons(makeString(rel->schemaname), object);
    1101           0 :         if (rel->catalogname)
    1102           0 :             object = lcons(makeString(rel->catalogname), object);
    1103             :     }
    1104             : 
    1105           0 :     return get_object_address(objtype, (Node *) object,
    1106             :                               relp, lockmode, missing_ok);
    1107             : }
    1108             : 
    1109             : /*
    1110             :  * Find an ObjectAddress for a type of object that is identified by an
    1111             :  * unqualified name.
    1112             :  */
    1113             : static ObjectAddress
    1114         173 : get_object_address_unqualified(ObjectType objtype,
    1115             :                                Value *strval, bool missing_ok)
    1116             : {
    1117             :     const char *name;
    1118             :     ObjectAddress address;
    1119             : 
    1120         173 :     name = strVal(strval);
    1121             : 
    1122             :     /* Translate name to OID. */
    1123         173 :     switch (objtype)
    1124             :     {
    1125             :         case OBJECT_ACCESS_METHOD:
    1126           7 :             address.classId = AccessMethodRelationId;
    1127           7 :             address.objectId = get_am_oid(name, missing_ok);
    1128           5 :             address.objectSubId = 0;
    1129           5 :             break;
    1130             :         case OBJECT_DATABASE:
    1131           3 :             address.classId = DatabaseRelationId;
    1132           3 :             address.objectId = get_database_oid(name, missing_ok);
    1133           2 :             address.objectSubId = 0;
    1134           2 :             break;
    1135             :         case OBJECT_EXTENSION:
    1136           3 :             address.classId = ExtensionRelationId;
    1137           3 :             address.objectId = get_extension_oid(name, missing_ok);
    1138           1 :             address.objectSubId = 0;
    1139           1 :             break;
    1140             :         case OBJECT_TABLESPACE:
    1141           2 :             address.classId = TableSpaceRelationId;
    1142           2 :             address.objectId = get_tablespace_oid(name, missing_ok);
    1143           1 :             address.objectSubId = 0;
    1144           1 :             break;
    1145             :         case OBJECT_ROLE:
    1146           3 :             address.classId = AuthIdRelationId;
    1147           3 :             address.objectId = get_role_oid(name, missing_ok);
    1148           2 :             address.objectSubId = 0;
    1149           2 :             break;
    1150             :         case OBJECT_SCHEMA:
    1151          46 :             address.classId = NamespaceRelationId;
    1152          46 :             address.objectId = get_namespace_oid(name, missing_ok);
    1153          43 :             address.objectSubId = 0;
    1154          43 :             break;
    1155             :         case OBJECT_LANGUAGE:
    1156          16 :             address.classId = LanguageRelationId;
    1157          16 :             address.objectId = get_language_oid(name, missing_ok);
    1158          14 :             address.objectSubId = 0;
    1159          14 :             break;
    1160             :         case OBJECT_FDW:
    1161          29 :             address.classId = ForeignDataWrapperRelationId;
    1162          29 :             address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
    1163          26 :             address.objectSubId = 0;
    1164          26 :             break;
    1165             :         case OBJECT_FOREIGN_SERVER:
    1166          25 :             address.classId = ForeignServerRelationId;
    1167          25 :             address.objectId = get_foreign_server_oid(name, missing_ok);
    1168          22 :             address.objectSubId = 0;
    1169          22 :             break;
    1170             :         case OBJECT_EVENT_TRIGGER:
    1171          16 :             address.classId = EventTriggerRelationId;
    1172          16 :             address.objectId = get_event_trigger_oid(name, missing_ok);
    1173          14 :             address.objectSubId = 0;
    1174          14 :             break;
    1175             :         case OBJECT_PUBLICATION:
    1176          16 :             address.classId = PublicationRelationId;
    1177          16 :             address.objectId = get_publication_oid(name, missing_ok);
    1178          15 :             address.objectSubId = 0;
    1179          15 :             break;
    1180             :         case OBJECT_SUBSCRIPTION:
    1181           7 :             address.classId = SubscriptionRelationId;
    1182           7 :             address.objectId = get_subscription_oid(name, missing_ok);
    1183           6 :             address.objectSubId = 0;
    1184           6 :             break;
    1185             :         default:
    1186           0 :             elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1187             :             /* placate compiler, which doesn't know elog won't return */
    1188             :             address.classId = InvalidOid;
    1189             :             address.objectId = InvalidOid;
    1190             :             address.objectSubId = 0;
    1191             :     }
    1192             : 
    1193         151 :     return address;
    1194             : }
    1195             : 
    1196             : /*
    1197             :  * Locate a relation by qualified name.
    1198             :  */
    1199             : static ObjectAddress
    1200          70 : get_relation_by_qualified_name(ObjectType objtype, List *object,
    1201             :                                Relation *relp, LOCKMODE lockmode,
    1202             :                                bool missing_ok)
    1203             : {
    1204             :     Relation    relation;
    1205             :     ObjectAddress address;
    1206             : 
    1207          70 :     address.classId = RelationRelationId;
    1208          70 :     address.objectId = InvalidOid;
    1209          70 :     address.objectSubId = 0;
    1210             : 
    1211          70 :     relation = relation_openrv_extended(makeRangeVarFromNameList(object),
    1212             :                                         lockmode, missing_ok);
    1213          30 :     if (!relation)
    1214           0 :         return address;
    1215             : 
    1216          30 :     switch (objtype)
    1217             :     {
    1218             :         case OBJECT_INDEX:
    1219           9 :             if (relation->rd_rel->relkind != RELKIND_INDEX)
    1220           0 :                 ereport(ERROR,
    1221             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1222             :                          errmsg("\"%s\" is not an index",
    1223             :                                 RelationGetRelationName(relation))));
    1224           9 :             break;
    1225             :         case OBJECT_SEQUENCE:
    1226           4 :             if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
    1227           0 :                 ereport(ERROR,
    1228             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1229             :                          errmsg("\"%s\" is not a sequence",
    1230             :                                 RelationGetRelationName(relation))));
    1231           4 :             break;
    1232             :         case OBJECT_TABLE:
    1233           7 :             if (relation->rd_rel->relkind != RELKIND_RELATION &&
    1234           1 :                 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    1235           0 :                 ereport(ERROR,
    1236             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1237             :                          errmsg("\"%s\" is not a table",
    1238             :                                 RelationGetRelationName(relation))));
    1239           6 :             break;
    1240             :         case OBJECT_VIEW:
    1241           4 :             if (relation->rd_rel->relkind != RELKIND_VIEW)
    1242           0 :                 ereport(ERROR,
    1243             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1244             :                          errmsg("\"%s\" is not a view",
    1245             :                                 RelationGetRelationName(relation))));
    1246           4 :             break;
    1247             :         case OBJECT_MATVIEW:
    1248           2 :             if (relation->rd_rel->relkind != RELKIND_MATVIEW)
    1249           0 :                 ereport(ERROR,
    1250             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1251             :                          errmsg("\"%s\" is not a materialized view",
    1252             :                                 RelationGetRelationName(relation))));
    1253           2 :             break;
    1254             :         case OBJECT_FOREIGN_TABLE:
    1255           5 :             if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
    1256           0 :                 ereport(ERROR,
    1257             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1258             :                          errmsg("\"%s\" is not a foreign table",
    1259             :                                 RelationGetRelationName(relation))));
    1260           5 :             break;
    1261             :         default:
    1262           0 :             elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1263             :             break;
    1264             :     }
    1265             : 
    1266             :     /* Done. */
    1267          30 :     address.objectId = RelationGetRelid(relation);
    1268          30 :     *relp = relation;
    1269             : 
    1270          30 :     return address;
    1271             : }
    1272             : 
    1273             : /*
    1274             :  * Find object address for an object that is attached to a relation.
    1275             :  *
    1276             :  * Note that we take only an AccessShareLock on the relation.  We need not
    1277             :  * pass down the LOCKMODE from get_object_address(), because that is the lock
    1278             :  * mode for the object itself, not the relation to which it is attached.
    1279             :  */
    1280             : static ObjectAddress
    1281         162 : get_object_address_relobject(ObjectType objtype, List *object,
    1282             :                              Relation *relp, bool missing_ok)
    1283             : {
    1284             :     ObjectAddress address;
    1285         162 :     Relation    relation = NULL;
    1286             :     int         nnames;
    1287             :     const char *depname;
    1288             :     List       *relname;
    1289             :     Oid         reloid;
    1290             : 
    1291             :     /* Extract name of dependent object. */
    1292         162 :     depname = strVal(llast(object));
    1293             : 
    1294             :     /* Separate relation name from dependent object name. */
    1295         162 :     nnames = list_length(object);
    1296         162 :     if (nnames < 2)
    1297           8 :         ereport(ERROR,
    1298             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1299             :                  errmsg("must specify relation and object name")));
    1300             : 
    1301             :     /* Extract relation name and open relation. */
    1302         154 :     relname = list_truncate(list_copy(object), nnames - 1);
    1303         154 :     relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
    1304             :                                     AccessShareLock,
    1305             :                                     missing_ok);
    1306             : 
    1307         132 :     reloid = relation ? RelationGetRelid(relation) : InvalidOid;
    1308             : 
    1309         132 :     switch (objtype)
    1310             :     {
    1311             :         case OBJECT_RULE:
    1312          33 :             address.classId = RewriteRelationId;
    1313          31 :             address.objectId = relation ?
    1314          33 :                 get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
    1315          31 :             address.objectSubId = 0;
    1316          31 :             break;
    1317             :         case OBJECT_TRIGGER:
    1318          57 :             address.classId = TriggerRelationId;
    1319          55 :             address.objectId = relation ?
    1320          57 :                 get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
    1321          55 :             address.objectSubId = 0;
    1322          55 :             break;
    1323             :         case OBJECT_TABCONSTRAINT:
    1324          23 :             address.classId = ConstraintRelationId;
    1325          21 :             address.objectId = relation ?
    1326          23 :                 get_relation_constraint_oid(reloid, depname, missing_ok) :
    1327             :                 InvalidOid;
    1328          21 :             address.objectSubId = 0;
    1329          21 :             break;
    1330             :         case OBJECT_POLICY:
    1331          19 :             address.classId = PolicyRelationId;
    1332          18 :             address.objectId = relation ?
    1333          19 :                 get_relation_policy_oid(reloid, depname, missing_ok) :
    1334             :                 InvalidOid;
    1335          18 :             address.objectSubId = 0;
    1336          18 :             break;
    1337             :         default:
    1338           0 :             elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1339             :     }
    1340             : 
    1341             :     /* Avoid relcache leak when object not found. */
    1342         125 :     if (!OidIsValid(address.objectId))
    1343             :     {
    1344           8 :         if (relation != NULL)
    1345           2 :             heap_close(relation, AccessShareLock);
    1346             : 
    1347           8 :         relation = NULL;        /* department of accident prevention */
    1348           8 :         return address;
    1349             :     }
    1350             : 
    1351             :     /* Done. */
    1352         117 :     *relp = relation;
    1353         117 :     return address;
    1354             : }
    1355             : 
    1356             : /*
    1357             :  * Find the ObjectAddress for an attribute.
    1358             :  */
    1359             : static ObjectAddress
    1360          41 : get_object_address_attribute(ObjectType objtype, List *object,
    1361             :                              Relation *relp, LOCKMODE lockmode,
    1362             :                              bool missing_ok)
    1363             : {
    1364             :     ObjectAddress address;
    1365             :     List       *relname;
    1366             :     Oid         reloid;
    1367             :     Relation    relation;
    1368             :     const char *attname;
    1369             :     AttrNumber  attnum;
    1370             : 
    1371             :     /* Extract relation name and open relation. */
    1372          41 :     if (list_length(object) < 2)
    1373           4 :         ereport(ERROR,
    1374             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1375             :                  errmsg("column name must be qualified")));
    1376          37 :     attname = strVal(lfirst(list_tail(object)));
    1377          37 :     relname = list_truncate(list_copy(object), list_length(object) - 1);
    1378             :     /* XXX no missing_ok support here */
    1379          37 :     relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
    1380          29 :     reloid = RelationGetRelid(relation);
    1381             : 
    1382             :     /* Look up attribute and construct return value. */
    1383          29 :     attnum = get_attnum(reloid, attname);
    1384          29 :     if (attnum == InvalidAttrNumber)
    1385             :     {
    1386           3 :         if (!missing_ok)
    1387           3 :             ereport(ERROR,
    1388             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1389             :                      errmsg("column \"%s\" of relation \"%s\" does not exist",
    1390             :                             attname, NameListToString(relname))));
    1391             : 
    1392           0 :         address.classId = RelationRelationId;
    1393           0 :         address.objectId = InvalidOid;
    1394           0 :         address.objectSubId = InvalidAttrNumber;
    1395           0 :         relation_close(relation, lockmode);
    1396           0 :         return address;
    1397             :     }
    1398             : 
    1399          26 :     address.classId = RelationRelationId;
    1400          26 :     address.objectId = reloid;
    1401          26 :     address.objectSubId = attnum;
    1402             : 
    1403          26 :     *relp = relation;
    1404          26 :     return address;
    1405             : }
    1406             : 
    1407             : /*
    1408             :  * Find the ObjectAddress for an attribute's default value.
    1409             :  */
    1410             : static ObjectAddress
    1411           8 : get_object_address_attrdef(ObjectType objtype, List *object,
    1412             :                            Relation *relp, LOCKMODE lockmode,
    1413             :                            bool missing_ok)
    1414             : {
    1415             :     ObjectAddress address;
    1416             :     List       *relname;
    1417             :     Oid         reloid;
    1418             :     Relation    relation;
    1419             :     const char *attname;
    1420             :     AttrNumber  attnum;
    1421             :     TupleDesc   tupdesc;
    1422             :     Oid         defoid;
    1423             : 
    1424             :     /* Extract relation name and open relation. */
    1425           8 :     if (list_length(object) < 2)
    1426           2 :         ereport(ERROR,
    1427             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1428             :                  errmsg("column name must be qualified")));
    1429           6 :     attname = strVal(llast(object));
    1430           6 :     relname = list_truncate(list_copy(object), list_length(object) - 1);
    1431             :     /* XXX no missing_ok support here */
    1432           6 :     relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
    1433           2 :     reloid = RelationGetRelid(relation);
    1434             : 
    1435           2 :     tupdesc = RelationGetDescr(relation);
    1436             : 
    1437             :     /* Look up attribute number and scan pg_attrdef to find its tuple */
    1438           2 :     attnum = get_attnum(reloid, attname);
    1439           2 :     defoid = InvalidOid;
    1440           2 :     if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
    1441             :     {
    1442             :         Relation    attrdef;
    1443             :         ScanKeyData keys[2];
    1444             :         SysScanDesc scan;
    1445             :         HeapTuple   tup;
    1446             : 
    1447           2 :         attrdef = relation_open(AttrDefaultRelationId, AccessShareLock);
    1448           2 :         ScanKeyInit(&keys[0],
    1449             :                     Anum_pg_attrdef_adrelid,
    1450             :                     BTEqualStrategyNumber,
    1451             :                     F_OIDEQ,
    1452             :                     ObjectIdGetDatum(reloid));
    1453           2 :         ScanKeyInit(&keys[1],
    1454             :                     Anum_pg_attrdef_adnum,
    1455             :                     BTEqualStrategyNumber,
    1456             :                     F_INT2EQ,
    1457           2 :                     Int16GetDatum(attnum));
    1458           2 :         scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
    1459             :                                   NULL, 2, keys);
    1460           2 :         if (HeapTupleIsValid(tup = systable_getnext(scan)))
    1461           2 :             defoid = HeapTupleGetOid(tup);
    1462             : 
    1463           2 :         systable_endscan(scan);
    1464           2 :         relation_close(attrdef, AccessShareLock);
    1465             :     }
    1466           2 :     if (!OidIsValid(defoid))
    1467             :     {
    1468           0 :         if (!missing_ok)
    1469           0 :             ereport(ERROR,
    1470             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1471             :                      errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
    1472             :                             attname, NameListToString(relname))));
    1473             : 
    1474           0 :         address.classId = AttrDefaultRelationId;
    1475           0 :         address.objectId = InvalidOid;
    1476           0 :         address.objectSubId = InvalidAttrNumber;
    1477           0 :         relation_close(relation, lockmode);
    1478           0 :         return address;
    1479             :     }
    1480             : 
    1481           2 :     address.classId = AttrDefaultRelationId;
    1482           2 :     address.objectId = defoid;
    1483           2 :     address.objectSubId = 0;
    1484             : 
    1485           2 :     *relp = relation;
    1486           2 :     return address;
    1487             : }
    1488             : 
    1489             : /*
    1490             :  * Find the ObjectAddress for a type or domain
    1491             :  */
    1492             : static ObjectAddress
    1493         131 : get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
    1494             : {
    1495             :     ObjectAddress address;
    1496             :     Type        tup;
    1497             : 
    1498         131 :     address.classId = TypeRelationId;
    1499         131 :     address.objectId = InvalidOid;
    1500         131 :     address.objectSubId = 0;
    1501             : 
    1502         131 :     tup = LookupTypeName(NULL, typename, NULL, missing_ok);
    1503         131 :     if (!HeapTupleIsValid(tup))
    1504             :     {
    1505          17 :         if (!missing_ok)
    1506          13 :             ereport(ERROR,
    1507             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1508             :                      errmsg("type \"%s\" does not exist",
    1509             :                             TypeNameToString(typename))));
    1510           4 :         return address;
    1511             :     }
    1512         114 :     address.objectId = typeTypeId(tup);
    1513             : 
    1514         114 :     if (objtype == OBJECT_DOMAIN)
    1515             :     {
    1516          51 :         if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
    1517           0 :             ereport(ERROR,
    1518             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1519             :                      errmsg("\"%s\" is not a domain",
    1520             :                             TypeNameToString(typename))));
    1521             :     }
    1522             : 
    1523         114 :     ReleaseSysCache(tup);
    1524             : 
    1525         114 :     return address;
    1526             : }
    1527             : 
    1528             : /*
    1529             :  * Find the ObjectAddress for an opclass or opfamily.
    1530             :  */
    1531             : static ObjectAddress
    1532          72 : get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
    1533             : {
    1534             :     Oid         amoid;
    1535             :     ObjectAddress address;
    1536             : 
    1537             :     /* XXX no missing_ok support here */
    1538          72 :     amoid = get_index_am_oid(strVal(linitial(object)), false);
    1539          60 :     object = list_copy_tail(object, 1);
    1540             : 
    1541          60 :     switch (objtype)
    1542             :     {
    1543             :         case OBJECT_OPCLASS:
    1544          21 :             address.classId = OperatorClassRelationId;
    1545          21 :             address.objectId = get_opclass_oid(amoid, object, missing_ok);
    1546          20 :             address.objectSubId = 0;
    1547          20 :             break;
    1548             :         case OBJECT_OPFAMILY:
    1549          39 :             address.classId = OperatorFamilyRelationId;
    1550          39 :             address.objectId = get_opfamily_oid(amoid, object, missing_ok);
    1551          38 :             address.objectSubId = 0;
    1552          38 :             break;
    1553             :         default:
    1554           0 :             elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1555             :             /* placate compiler, which doesn't know elog won't return */
    1556             :             address.classId = InvalidOid;
    1557             :             address.objectId = InvalidOid;
    1558             :             address.objectSubId = 0;
    1559             :     }
    1560             : 
    1561          58 :     return address;
    1562             : }
    1563             : 
    1564             : /*
    1565             :  * Find the ObjectAddress for an opclass/opfamily member.
    1566             :  *
    1567             :  * (The returned address corresponds to a pg_amop/pg_amproc object).
    1568             :  */
    1569             : static ObjectAddress
    1570           8 : get_object_address_opf_member(ObjectType objtype,
    1571             :                               List *object, bool missing_ok)
    1572             : {
    1573             :     ObjectAddress famaddr;
    1574             :     ObjectAddress address;
    1575             :     ListCell   *cell;
    1576             :     List       *copy;
    1577             :     TypeName   *typenames[2];
    1578             :     Oid         typeoids[2];
    1579             :     int         membernum;
    1580             :     int         i;
    1581             : 
    1582             :     /*
    1583             :      * The last element of the object list contains the strategy or procedure
    1584             :      * number.  We need to strip that out before getting the opclass/family
    1585             :      * address.  The rest can be used directly by get_object_address_opcf().
    1586             :      */
    1587           8 :     membernum = atoi(strVal(llast(linitial(object))));
    1588           8 :     copy = list_truncate(list_copy(linitial(object)), list_length(linitial(object)) - 1);
    1589             : 
    1590             :     /* no missing_ok support here */
    1591           8 :     famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
    1592             : 
    1593             :     /* find out left/right type names and OIDs */
    1594           8 :     i = 0;
    1595          16 :     foreach(cell, lsecond(object))
    1596             :     {
    1597             :         ObjectAddress typaddr;
    1598             : 
    1599          16 :         typenames[i] = lfirst_node(TypeName, cell);
    1600          16 :         typaddr = get_object_address_type(OBJECT_TYPE, typenames[i], missing_ok);
    1601          16 :         typeoids[i] = typaddr.objectId;
    1602          16 :         if (++i >= 2)
    1603           8 :             break;
    1604             :     }
    1605             : 
    1606           8 :     switch (objtype)
    1607             :     {
    1608             :         case OBJECT_AMOP:
    1609             :             {
    1610             :                 HeapTuple   tp;
    1611             : 
    1612           4 :                 ObjectAddressSet(address, AccessMethodOperatorRelationId,
    1613             :                                  InvalidOid);
    1614             : 
    1615           4 :                 tp = SearchSysCache4(AMOPSTRATEGY,
    1616             :                                      ObjectIdGetDatum(famaddr.objectId),
    1617             :                                      ObjectIdGetDatum(typeoids[0]),
    1618             :                                      ObjectIdGetDatum(typeoids[1]),
    1619             :                                      Int16GetDatum(membernum));
    1620           4 :                 if (!HeapTupleIsValid(tp))
    1621             :                 {
    1622           2 :                     if (!missing_ok)
    1623           2 :                         ereport(ERROR,
    1624             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    1625             :                                  errmsg("operator %d (%s, %s) of %s does not exist",
    1626             :                                         membernum,
    1627             :                                         TypeNameToString(typenames[0]),
    1628             :                                         TypeNameToString(typenames[1]),
    1629             :                                         getObjectDescription(&famaddr))));
    1630             :                 }
    1631             :                 else
    1632             :                 {
    1633           2 :                     address.objectId = HeapTupleGetOid(tp);
    1634           2 :                     ReleaseSysCache(tp);
    1635             :                 }
    1636             :             }
    1637           2 :             break;
    1638             : 
    1639             :         case OBJECT_AMPROC:
    1640             :             {
    1641             :                 HeapTuple   tp;
    1642             : 
    1643           4 :                 ObjectAddressSet(address, AccessMethodProcedureRelationId,
    1644             :                                  InvalidOid);
    1645             : 
    1646           4 :                 tp = SearchSysCache4(AMPROCNUM,
    1647             :                                      ObjectIdGetDatum(famaddr.objectId),
    1648             :                                      ObjectIdGetDatum(typeoids[0]),
    1649             :                                      ObjectIdGetDatum(typeoids[1]),
    1650             :                                      Int16GetDatum(membernum));
    1651           4 :                 if (!HeapTupleIsValid(tp))
    1652             :                 {
    1653           2 :                     if (!missing_ok)
    1654           2 :                         ereport(ERROR,
    1655             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    1656             :                                  errmsg("function %d (%s, %s) of %s does not exist",
    1657             :                                         membernum,
    1658             :                                         TypeNameToString(typenames[0]),
    1659             :                                         TypeNameToString(typenames[1]),
    1660             :                                         getObjectDescription(&famaddr))));
    1661             :                 }
    1662             :                 else
    1663             :                 {
    1664           2 :                     address.objectId = HeapTupleGetOid(tp);
    1665           2 :                     ReleaseSysCache(tp);
    1666             :                 }
    1667             :             }
    1668           2 :             break;
    1669             :         default:
    1670           0 :             elog(ERROR, "unrecognized objtype: %d", (int) objtype);
    1671             :     }
    1672             : 
    1673           4 :     return address;
    1674             : }
    1675             : 
    1676             : /*
    1677             :  * Find the ObjectAddress for a user mapping.
    1678             :  */
    1679             : static ObjectAddress
    1680           5 : get_object_address_usermapping(List *object, bool missing_ok)
    1681             : {
    1682             :     ObjectAddress address;
    1683             :     Oid         userid;
    1684             :     char       *username;
    1685             :     char       *servername;
    1686             :     ForeignServer *server;
    1687             :     HeapTuple   tp;
    1688             : 
    1689           5 :     ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
    1690             : 
    1691             :     /* fetch string names from input lists, for error messages */
    1692           5 :     username = strVal(linitial(object));
    1693           5 :     servername = strVal(lsecond(object));
    1694             : 
    1695             :     /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
    1696           5 :     if (strcmp(username, "public") == 0)
    1697           0 :         userid = InvalidOid;
    1698             :     else
    1699             :     {
    1700           5 :         tp = SearchSysCache1(AUTHNAME,
    1701             :                              CStringGetDatum(username));
    1702           5 :         if (!HeapTupleIsValid(tp))
    1703             :         {
    1704           3 :             if (!missing_ok)
    1705           3 :                 ereport(ERROR,
    1706             :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
    1707             :                          errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
    1708             :                                 username, servername)));
    1709           0 :             return address;
    1710             :         }
    1711           2 :         userid = HeapTupleGetOid(tp);
    1712           2 :         ReleaseSysCache(tp);
    1713             :     }
    1714             : 
    1715             :     /* Now look up the pg_user_mapping tuple */
    1716           2 :     server = GetForeignServerByName(servername, true);
    1717           2 :     if (!server)
    1718             :     {
    1719           0 :         if (!missing_ok)
    1720           0 :             ereport(ERROR,
    1721             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1722             :                      errmsg("server \"%s\" does not exist", servername)));
    1723           0 :         return address;
    1724             :     }
    1725           2 :     tp = SearchSysCache2(USERMAPPINGUSERSERVER,
    1726             :                          ObjectIdGetDatum(userid),
    1727             :                          ObjectIdGetDatum(server->serverid));
    1728           2 :     if (!HeapTupleIsValid(tp))
    1729             :     {
    1730           0 :         if (!missing_ok)
    1731           0 :             ereport(ERROR,
    1732             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1733             :                      errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
    1734             :                             username, servername)));
    1735           0 :         return address;
    1736             :     }
    1737             : 
    1738           2 :     address.objectId = HeapTupleGetOid(tp);
    1739             : 
    1740           2 :     ReleaseSysCache(tp);
    1741             : 
    1742           2 :     return address;
    1743             : }
    1744             : 
    1745             : /*
    1746             :  * Find the ObjectAddress for a publication relation.  The first element of
    1747             :  * the object parameter is the relation name, the second is the
    1748             :  * publication name.
    1749             :  */
    1750             : static ObjectAddress
    1751           5 : get_object_address_publication_rel(List *object,
    1752             :                                    Relation *relp, bool missing_ok)
    1753             : {
    1754             :     ObjectAddress address;
    1755             :     Relation    relation;
    1756             :     List       *relname;
    1757             :     char       *pubname;
    1758             :     Publication *pub;
    1759             : 
    1760           5 :     ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
    1761             : 
    1762           5 :     relname = linitial(object);
    1763           5 :     relation = relation_openrv_extended(makeRangeVarFromNameList(relname),
    1764             :                                         AccessShareLock, missing_ok);
    1765           2 :     if (!relation)
    1766           0 :         return address;
    1767             : 
    1768             :     /* fetch publication name from input list */
    1769           2 :     pubname = strVal(lsecond(object));
    1770             : 
    1771             :     /* Now look up the pg_publication tuple */
    1772           2 :     pub = GetPublicationByName(pubname, missing_ok);
    1773           2 :     if (!pub)
    1774             :     {
    1775           0 :         relation_close(relation, AccessShareLock);
    1776           0 :         return address;
    1777             :     }
    1778             : 
    1779             :     /* Find the publication relation mapping in syscache. */
    1780           2 :     address.objectId =
    1781           2 :         GetSysCacheOid2(PUBLICATIONRELMAP,
    1782             :                         ObjectIdGetDatum(RelationGetRelid(relation)),
    1783             :                         ObjectIdGetDatum(pub->oid));
    1784           2 :     if (!OidIsValid(address.objectId))
    1785             :     {
    1786           0 :         if (!missing_ok)
    1787           0 :             ereport(ERROR,
    1788             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1789             :                      errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
    1790             :                             RelationGetRelationName(relation), pubname)));
    1791           0 :         relation_close(relation, AccessShareLock);
    1792           0 :         return address;
    1793             :     }
    1794             : 
    1795           2 :     *relp = relation;
    1796           2 :     return address;
    1797             : }
    1798             : 
    1799             : /*
    1800             :  * Find the ObjectAddress for a default ACL.
    1801             :  */
    1802             : static ObjectAddress
    1803           7 : get_object_address_defacl(List *object, bool missing_ok)
    1804             : {
    1805             :     HeapTuple   tp;
    1806             :     Oid         userid;
    1807             :     Oid         schemaid;
    1808             :     char       *username;
    1809             :     char       *schema;
    1810             :     char        objtype;
    1811             :     char       *objtype_str;
    1812             :     ObjectAddress address;
    1813             : 
    1814           7 :     ObjectAddressSet(address, DefaultAclRelationId, InvalidOid);
    1815             : 
    1816             :     /*
    1817             :      * First figure out the textual attributes so that they can be used for
    1818             :      * error reporting.
    1819             :      */
    1820           7 :     username = strVal(lsecond(object));
    1821           7 :     if (list_length(object) >= 3)
    1822           4 :         schema = (char *) strVal(lthird(object));
    1823             :     else
    1824           3 :         schema = NULL;
    1825             : 
    1826             :     /*
    1827             :      * Decode defaclobjtype.  Only first char is considered; the rest of the
    1828             :      * string, if any, is blissfully ignored.
    1829             :      */
    1830           7 :     objtype = ((char *) strVal(linitial(object)))[0];
    1831           7 :     switch (objtype)
    1832             :     {
    1833             :         case DEFACLOBJ_RELATION:
    1834           4 :             objtype_str = "tables";
    1835           4 :             break;
    1836             :         case DEFACLOBJ_SEQUENCE:
    1837           0 :             objtype_str = "sequences";
    1838           0 :             break;
    1839             :         case DEFACLOBJ_FUNCTION:
    1840           0 :             objtype_str = "functions";
    1841           0 :             break;
    1842             :         case DEFACLOBJ_TYPE:
    1843           0 :             objtype_str = "types";
    1844           0 :             break;
    1845             :         case DEFACLOBJ_NAMESPACE:
    1846           0 :             objtype_str = "schemas";
    1847           0 :             break;
    1848             :         default:
    1849           3 :             ereport(ERROR,
    1850             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1851             :                      errmsg("unrecognized default ACL object type \"%c\"", objtype),
    1852             :                      errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
    1853             :                              DEFACLOBJ_RELATION,
    1854             :                              DEFACLOBJ_SEQUENCE,
    1855             :                              DEFACLOBJ_FUNCTION,
    1856             :                              DEFACLOBJ_TYPE,
    1857             :                              DEFACLOBJ_NAMESPACE)));
    1858             :     }
    1859             : 
    1860             :     /*
    1861             :      * Look up user ID.  Behave as "default ACL not found" if the user doesn't
    1862             :      * exist.
    1863             :      */
    1864           4 :     tp = SearchSysCache1(AUTHNAME,
    1865             :                          CStringGetDatum(username));
    1866           4 :     if (!HeapTupleIsValid(tp))
    1867           0 :         goto not_found;
    1868           4 :     userid = HeapTupleGetOid(tp);
    1869           4 :     ReleaseSysCache(tp);
    1870             : 
    1871             :     /*
    1872             :      * If a schema name was given, look up its OID.  If it doesn't exist,
    1873             :      * behave as "default ACL not found".
    1874             :      */
    1875           4 :     if (schema)
    1876             :     {
    1877           2 :         schemaid = get_namespace_oid(schema, true);
    1878           2 :         if (schemaid == InvalidOid)
    1879           0 :             goto not_found;
    1880             :     }
    1881             :     else
    1882           2 :         schemaid = InvalidOid;
    1883             : 
    1884             :     /* Finally, look up the pg_default_acl object */
    1885           4 :     tp = SearchSysCache3(DEFACLROLENSPOBJ,
    1886             :                          ObjectIdGetDatum(userid),
    1887             :                          ObjectIdGetDatum(schemaid),
    1888             :                          CharGetDatum(objtype));
    1889           4 :     if (!HeapTupleIsValid(tp))
    1890           0 :         goto not_found;
    1891             : 
    1892           4 :     address.objectId = HeapTupleGetOid(tp);
    1893           4 :     ReleaseSysCache(tp);
    1894             : 
    1895           4 :     return address;
    1896             : 
    1897             : not_found:
    1898           0 :     if (!missing_ok)
    1899             :     {
    1900           0 :         if (schema)
    1901           0 :             ereport(ERROR,
    1902             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1903             :                      errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
    1904             :                             username, schema, objtype_str)));
    1905             :         else
    1906           0 :             ereport(ERROR,
    1907             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    1908             :                      errmsg("default ACL for user \"%s\" on %s does not exist",
    1909             :                             username, objtype_str)));
    1910             :     }
    1911           0 :     return address;
    1912             : }
    1913             : 
    1914             : /*
    1915             :  * Convert an array of TEXT into a List of string Values, as emitted by the
    1916             :  * parser, which is what get_object_address uses as input.
    1917             :  */
    1918             : static List *
    1919         526 : textarray_to_strvaluelist(ArrayType *arr)
    1920             : {
    1921             :     Datum      *elems;
    1922             :     bool       *nulls;
    1923             :     int         nelems;
    1924         526 :     List       *list = NIL;
    1925             :     int         i;
    1926             : 
    1927         526 :     deconstruct_array(arr, TEXTOID, -1, false, 'i',
    1928             :                       &elems, &nulls, &nelems);
    1929             : 
    1930        1146 :     for (i = 0; i < nelems; i++)
    1931             :     {
    1932         621 :         if (nulls[i])
    1933           1 :             ereport(ERROR,
    1934             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1935             :                      errmsg("name or argument lists may not contain nulls")));
    1936         620 :         list = lappend(list, makeString(TextDatumGetCString(elems[i])));
    1937             :     }
    1938             : 
    1939         525 :     return list;
    1940             : }
    1941             : 
    1942             : /*
    1943             :  * SQL-callable version of get_object_address
    1944             :  */
    1945             : Datum
    1946         324 : pg_get_object_address(PG_FUNCTION_ARGS)
    1947             : {
    1948         324 :     char       *ttype = TextDatumGetCString(PG_GETARG_DATUM(0));
    1949         324 :     ArrayType  *namearr = PG_GETARG_ARRAYTYPE_P(1);
    1950         324 :     ArrayType  *argsarr = PG_GETARG_ARRAYTYPE_P(2);
    1951             :     int         itype;
    1952             :     ObjectType  type;
    1953         324 :     List       *name = NIL;
    1954         324 :     TypeName   *typename = NULL;
    1955         324 :     List       *args = NIL;
    1956         324 :     Node       *objnode = NULL;
    1957             :     ObjectAddress addr;
    1958             :     TupleDesc   tupdesc;
    1959             :     Datum       values[3];
    1960             :     bool        nulls[3];
    1961             :     HeapTuple   htup;
    1962             :     Relation    relation;
    1963             : 
    1964             :     /* Decode object type, raise error if unknown */
    1965         324 :     itype = read_objtype_from_string(ttype);
    1966         323 :     if (itype < 0)
    1967           6 :         ereport(ERROR,
    1968             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1969             :                  errmsg("unsupported object type \"%s\"", ttype)));
    1970         317 :     type = (ObjectType) itype;
    1971             : 
    1972             :     /*
    1973             :      * Convert the text array to the representation appropriate for the given
    1974             :      * object type.  Most use a simple string Values list, but there are some
    1975             :      * exceptions.
    1976             :      */
    1977         317 :     if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
    1978         287 :         type == OBJECT_TRANSFORM || type == OBJECT_DOMCONSTRAINT)
    1979          22 :     {
    1980             :         Datum      *elems;
    1981             :         bool       *nulls;
    1982             :         int         nelems;
    1983             : 
    1984          38 :         deconstruct_array(namearr, TEXTOID, -1, false, 'i',
    1985             :                           &elems, &nulls, &nelems);
    1986          38 :         if (nelems != 1)
    1987          16 :             ereport(ERROR,
    1988             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1989             :                      errmsg("name list length must be exactly %d", 1)));
    1990          22 :         if (nulls[0])
    1991           0 :             ereport(ERROR,
    1992             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1993             :                      errmsg("name or argument lists may not contain nulls")));
    1994          22 :         typename = typeStringToTypeName(TextDatumGetCString(elems[0]));
    1995             :     }
    1996         279 :     else if (type == OBJECT_LARGEOBJECT)
    1997             :     {
    1998             :         Datum      *elems;
    1999             :         bool       *nulls;
    2000             :         int         nelems;
    2001             : 
    2002           3 :         deconstruct_array(namearr, TEXTOID, -1, false, 'i',
    2003             :                           &elems, &nulls, &nelems);
    2004           3 :         if (nelems != 1)
    2005           1 :             ereport(ERROR,
    2006             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2007             :                      errmsg("name list length must be exactly %d", 1)));
    2008           2 :         if (nulls[0])
    2009           0 :             ereport(ERROR,
    2010             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2011             :                      errmsg("large object OID may not be null")));
    2012           2 :         objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
    2013             :     }
    2014             :     else
    2015             :     {
    2016         276 :         name = textarray_to_strvaluelist(namearr);
    2017         275 :         if (list_length(name) < 1)
    2018           1 :             ereport(ERROR,
    2019             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2020             :                      errmsg("name list length must be at least %d", 1)));
    2021             :     }
    2022             : 
    2023             :     /*
    2024             :      * If args are given, decode them according to the object type.
    2025             :      */
    2026         298 :     if (type == OBJECT_AGGREGATE ||
    2027         282 :         type == OBJECT_FUNCTION ||
    2028         274 :         type == OBJECT_OPERATOR ||
    2029         270 :         type == OBJECT_CAST ||
    2030         260 :         type == OBJECT_AMOP ||
    2031             :         type == OBJECT_AMPROC)
    2032          48 :     {
    2033             :         /* in these cases, the args list must be of TypeName */
    2034             :         Datum      *elems;
    2035             :         bool       *nulls;
    2036             :         int         nelems;
    2037             :         int         i;
    2038             : 
    2039          48 :         deconstruct_array(argsarr, TEXTOID, -1, false, 'i',
    2040             :                           &elems, &nulls, &nelems);
    2041             : 
    2042          48 :         args = NIL;
    2043          94 :         for (i = 0; i < nelems; i++)
    2044             :         {
    2045          46 :             if (nulls[i])
    2046           0 :                 ereport(ERROR,
    2047             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2048             :                          errmsg("name or argument lists may not contain nulls")));
    2049          46 :             args = lappend(args,
    2050          46 :                            typeStringToTypeName(TextDatumGetCString(elems[i])));
    2051             :         }
    2052             :     }
    2053             :     else
    2054             :     {
    2055             :         /* For all other object types, use string Values */
    2056         250 :         args = textarray_to_strvaluelist(argsarr);
    2057             :     }
    2058             : 
    2059             :     /*
    2060             :      * get_object_address is pretty sensitive to the length its input lists;
    2061             :      * check that they're what it wants.
    2062             :      */
    2063         298 :     switch (type)
    2064             :     {
    2065             :         case OBJECT_DOMCONSTRAINT:
    2066             :         case OBJECT_CAST:
    2067             :         case OBJECT_USER_MAPPING:
    2068             :         case OBJECT_PUBLICATION_REL:
    2069             :         case OBJECT_DEFACL:
    2070             :         case OBJECT_TRANSFORM:
    2071          38 :             if (list_length(args) != 1)
    2072          12 :                 ereport(ERROR,
    2073             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2074             :                          errmsg("argument list length must be exactly %d", 1)));
    2075          26 :             break;
    2076             :         case OBJECT_OPFAMILY:
    2077             :         case OBJECT_OPCLASS:
    2078          16 :             if (list_length(name) < 2)
    2079           4 :                 ereport(ERROR,
    2080             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2081             :                          errmsg("name list length must be at least %d", 2)));
    2082          12 :             break;
    2083             :         case OBJECT_AMOP:
    2084             :         case OBJECT_AMPROC:
    2085          20 :             if (list_length(name) < 3)
    2086           8 :                 ereport(ERROR,
    2087             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2088             :                          errmsg("name list length must be at least %d", 3)));
    2089             :             /* fall through to check args length */
    2090             :         case OBJECT_OPERATOR:
    2091          20 :             if (list_length(args) != 2)
    2092          10 :                 ereport(ERROR,
    2093             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2094             :                          errmsg("argument list length must be exactly %d", 2)));
    2095          10 :             break;
    2096             :         default:
    2097         216 :             break;
    2098             :     }
    2099             : 
    2100             :     /*
    2101             :      * Now build the Node type that get_object_address() expects for the given
    2102             :      * type.
    2103             :      */
    2104         264 :     switch (type)
    2105             :     {
    2106             :         case OBJECT_TABLE:
    2107             :         case OBJECT_SEQUENCE:
    2108             :         case OBJECT_VIEW:
    2109             :         case OBJECT_MATVIEW:
    2110             :         case OBJECT_INDEX:
    2111             :         case OBJECT_FOREIGN_TABLE:
    2112             :         case OBJECT_COLUMN:
    2113             :         case OBJECT_ATTRIBUTE:
    2114             :         case OBJECT_COLLATION:
    2115             :         case OBJECT_CONVERSION:
    2116             :         case OBJECT_STATISTIC_EXT:
    2117             :         case OBJECT_TSPARSER:
    2118             :         case OBJECT_TSDICTIONARY:
    2119             :         case OBJECT_TSTEMPLATE:
    2120             :         case OBJECT_TSCONFIGURATION:
    2121             :         case OBJECT_DEFAULT:
    2122             :         case OBJECT_POLICY:
    2123             :         case OBJECT_RULE:
    2124             :         case OBJECT_TRIGGER:
    2125             :         case OBJECT_TABCONSTRAINT:
    2126             :         case OBJECT_OPCLASS:
    2127             :         case OBJECT_OPFAMILY:
    2128         160 :             objnode = (Node *) name;
    2129         160 :             break;
    2130             :         case OBJECT_ACCESS_METHOD:
    2131             :         case OBJECT_DATABASE:
    2132             :         case OBJECT_EVENT_TRIGGER:
    2133             :         case OBJECT_EXTENSION:
    2134             :         case OBJECT_FDW:
    2135             :         case OBJECT_FOREIGN_SERVER:
    2136             :         case OBJECT_LANGUAGE:
    2137             :         case OBJECT_PUBLICATION:
    2138             :         case OBJECT_ROLE:
    2139             :         case OBJECT_SCHEMA:
    2140             :         case OBJECT_SUBSCRIPTION:
    2141             :         case OBJECT_TABLESPACE:
    2142          40 :             if (list_length(name) != 1)
    2143          12 :                 ereport(ERROR,
    2144             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2145             :                          errmsg("name list length must be exactly %d", 1)));
    2146          28 :             objnode = linitial(name);
    2147          28 :             break;
    2148             :         case OBJECT_TYPE:
    2149             :         case OBJECT_DOMAIN:
    2150          10 :             objnode = (Node *) typename;
    2151          10 :             break;
    2152             :         case OBJECT_CAST:
    2153             :         case OBJECT_DOMCONSTRAINT:
    2154             :         case OBJECT_TRANSFORM:
    2155           9 :             objnode = (Node *) list_make2(typename, linitial(args));
    2156           9 :             break;
    2157             :         case OBJECT_PUBLICATION_REL:
    2158           5 :             objnode = (Node *) list_make2(name, linitial(args));
    2159           5 :             break;
    2160             :         case OBJECT_USER_MAPPING:
    2161           5 :             objnode = (Node *) list_make2(linitial(name), linitial(args));
    2162           5 :             break;
    2163             :         case OBJECT_DEFACL:
    2164           7 :             objnode = (Node *) lcons(linitial(args), name);
    2165           7 :             break;
    2166             :         case OBJECT_AMOP:
    2167             :         case OBJECT_AMPROC:
    2168           8 :             objnode = (Node *) list_make2(name, args);
    2169           8 :             break;
    2170             :         case OBJECT_FUNCTION:
    2171             :         case OBJECT_AGGREGATE:
    2172             :         case OBJECT_OPERATOR:
    2173             :             {
    2174          18 :                 ObjectWithArgs *owa = makeNode(ObjectWithArgs);
    2175             : 
    2176          18 :                 owa->objname = name;
    2177          18 :                 owa->objargs = args;
    2178          18 :                 objnode = (Node *) owa;
    2179          18 :                 break;
    2180             :             }
    2181             :         case OBJECT_LARGEOBJECT:
    2182             :             /* already handled above */
    2183           2 :             break;
    2184             :             /* no default, to let compiler warn about missing case */
    2185             :     }
    2186             : 
    2187         252 :     if (objnode == NULL)
    2188           0 :         elog(ERROR, "unrecognized object type: %d", type);
    2189             : 
    2190         252 :     addr = get_object_address(type, objnode,
    2191             :                               &relation, AccessShareLock, false);
    2192             : 
    2193             :     /* We don't need the relcache entry, thank you very much */
    2194          92 :     if (relation)
    2195          28 :         relation_close(relation, AccessShareLock);
    2196             : 
    2197          92 :     tupdesc = CreateTemplateTupleDesc(3, false);
    2198          92 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "classid",
    2199             :                        OIDOID, -1, 0);
    2200          92 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "objid",
    2201             :                        OIDOID, -1, 0);
    2202          92 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "objsubid",
    2203             :                        INT4OID, -1, 0);
    2204          92 :     tupdesc = BlessTupleDesc(tupdesc);
    2205             : 
    2206          92 :     values[0] = ObjectIdGetDatum(addr.classId);
    2207          92 :     values[1] = ObjectIdGetDatum(addr.objectId);
    2208          92 :     values[2] = Int32GetDatum(addr.objectSubId);
    2209          92 :     nulls[0] = false;
    2210          92 :     nulls[1] = false;
    2211          92 :     nulls[2] = false;
    2212             : 
    2213          92 :     htup = heap_form_tuple(tupdesc, values, nulls);
    2214             : 
    2215          92 :     PG_RETURN_DATUM(HeapTupleGetDatum(htup));
    2216             : }
    2217             : 
    2218             : /*
    2219             :  * Check ownership of an object previously identified by get_object_address.
    2220             :  */
    2221             : void
    2222         573 : check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
    2223             :                        Node *object, Relation relation)
    2224             : {
    2225         573 :     switch (objtype)
    2226             :     {
    2227             :         case OBJECT_INDEX:
    2228             :         case OBJECT_SEQUENCE:
    2229             :         case OBJECT_TABLE:
    2230             :         case OBJECT_VIEW:
    2231             :         case OBJECT_MATVIEW:
    2232             :         case OBJECT_FOREIGN_TABLE:
    2233             :         case OBJECT_COLUMN:
    2234             :         case OBJECT_RULE:
    2235             :         case OBJECT_TRIGGER:
    2236             :         case OBJECT_POLICY:
    2237             :         case OBJECT_TABCONSTRAINT:
    2238         149 :             if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
    2239           2 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
    2240           2 :                                RelationGetRelationName(relation));
    2241         147 :             break;
    2242             :         case OBJECT_DATABASE:
    2243           2 :             if (!pg_database_ownercheck(address.objectId, roleid))
    2244           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
    2245           0 :                                strVal((Value *) object));
    2246           2 :             break;
    2247             :         case OBJECT_TYPE:
    2248             :         case OBJECT_DOMAIN:
    2249             :         case OBJECT_ATTRIBUTE:
    2250             :         case OBJECT_DOMCONSTRAINT:
    2251           8 :             if (!pg_type_ownercheck(address.objectId, roleid))
    2252           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
    2253           8 :             break;
    2254             :         case OBJECT_AGGREGATE:
    2255             :         case OBJECT_FUNCTION:
    2256         147 :             if (!pg_proc_ownercheck(address.objectId, roleid))
    2257           1 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
    2258           1 :                                NameListToString((castNode(ObjectWithArgs, object))->objname));
    2259         146 :             break;
    2260             :         case OBJECT_OPERATOR:
    2261           0 :             if (!pg_oper_ownercheck(address.objectId, roleid))
    2262           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
    2263           0 :                                NameListToString((castNode(ObjectWithArgs, object))->objname));
    2264           0 :             break;
    2265             :         case OBJECT_SCHEMA:
    2266          38 :             if (!pg_namespace_ownercheck(address.objectId, roleid))
    2267           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
    2268           0 :                                strVal((Value *) object));
    2269          38 :             break;
    2270             :         case OBJECT_COLLATION:
    2271           0 :             if (!pg_collation_ownercheck(address.objectId, roleid))
    2272           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
    2273           0 :                                NameListToString(castNode(List, object)));
    2274           0 :             break;
    2275             :         case OBJECT_CONVERSION:
    2276         136 :             if (!pg_conversion_ownercheck(address.objectId, roleid))
    2277           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
    2278           0 :                                NameListToString(castNode(List, object)));
    2279         136 :             break;
    2280             :         case OBJECT_EXTENSION:
    2281           0 :             if (!pg_extension_ownercheck(address.objectId, roleid))
    2282           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
    2283           0 :                                strVal((Value *) object));
    2284           0 :             break;
    2285             :         case OBJECT_FDW:
    2286          17 :             if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
    2287           3 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
    2288           3 :                                strVal((Value *) object));
    2289          14 :             break;
    2290             :         case OBJECT_FOREIGN_SERVER:
    2291          14 :             if (!pg_foreign_server_ownercheck(address.objectId, roleid))
    2292           4 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
    2293           4 :                                strVal((Value *) object));
    2294          10 :             break;
    2295             :         case OBJECT_EVENT_TRIGGER:
    2296          11 :             if (!pg_event_trigger_ownercheck(address.objectId, roleid))
    2297           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
    2298           0 :                                strVal((Value *) object));
    2299          11 :             break;
    2300             :         case OBJECT_LANGUAGE:
    2301           3 :             if (!pg_language_ownercheck(address.objectId, roleid))
    2302           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
    2303           0 :                                strVal((Value *) object));
    2304           3 :             break;
    2305             :         case OBJECT_OPCLASS:
    2306           0 :             if (!pg_opclass_ownercheck(address.objectId, roleid))
    2307           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
    2308           0 :                                NameListToString(castNode(List, object)));
    2309           0 :             break;
    2310             :         case OBJECT_OPFAMILY:
    2311           0 :             if (!pg_opfamily_ownercheck(address.objectId, roleid))
    2312           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
    2313           0 :                                NameListToString(castNode(List, object)));
    2314           0 :             break;
    2315             :         case OBJECT_LARGEOBJECT:
    2316           4 :             if (!lo_compat_privileges &&
    2317           2 :                 !pg_largeobject_ownercheck(address.objectId, roleid))
    2318           0 :                 ereport(ERROR,
    2319             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2320             :                          errmsg("must be owner of large object %u",
    2321             :                                 address.objectId)));
    2322           2 :             break;
    2323             :         case OBJECT_CAST:
    2324             :             {
    2325             :                 /* We can only check permissions on the source/target types */
    2326           3 :                 TypeName   *sourcetype = linitial_node(TypeName, castNode(List, object));
    2327           3 :                 TypeName   *targettype = lsecond_node(TypeName, castNode(List, object));
    2328           3 :                 Oid         sourcetypeid = typenameTypeId(NULL, sourcetype);
    2329           3 :                 Oid         targettypeid = typenameTypeId(NULL, targettype);
    2330             : 
    2331           3 :                 if (!pg_type_ownercheck(sourcetypeid, roleid)
    2332           0 :                     && !pg_type_ownercheck(targettypeid, roleid))
    2333           0 :                     ereport(ERROR,
    2334             :                             (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2335             :                              errmsg("must be owner of type %s or type %s",
    2336             :                                     format_type_be(sourcetypeid),
    2337             :                                     format_type_be(targettypeid))));
    2338             :             }
    2339           3 :             break;
    2340             :         case OBJECT_PUBLICATION:
    2341           9 :             if (!pg_publication_ownercheck(address.objectId, roleid))
    2342           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PUBLICATION,
    2343           0 :                                strVal((Value *) object));
    2344           9 :             break;
    2345             :         case OBJECT_SUBSCRIPTION:
    2346           1 :             if (!pg_subscription_ownercheck(address.objectId, roleid))
    2347           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_SUBSCRIPTION,
    2348           0 :                                strVal((Value *) object));
    2349           1 :             break;
    2350             :         case OBJECT_TRANSFORM:
    2351             :             {
    2352           0 :                 TypeName   *typename = linitial_node(TypeName, castNode(List, object));
    2353           0 :                 Oid         typeid = typenameTypeId(NULL, typename);
    2354             : 
    2355           0 :                 if (!pg_type_ownercheck(typeid, roleid))
    2356           0 :                     aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid);
    2357             :             }
    2358           0 :             break;
    2359             :         case OBJECT_TABLESPACE:
    2360           0 :             if (!pg_tablespace_ownercheck(address.objectId, roleid))
    2361           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
    2362           0 :                                strVal((Value *) object));
    2363           0 :             break;
    2364             :         case OBJECT_TSDICTIONARY:
    2365          15 :             if (!pg_ts_dict_ownercheck(address.objectId, roleid))
    2366           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
    2367           0 :                                NameListToString(castNode(List, object)));
    2368          15 :             break;
    2369             :         case OBJECT_TSCONFIGURATION:
    2370          15 :             if (!pg_ts_config_ownercheck(address.objectId, roleid))
    2371           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
    2372           0 :                                NameListToString(castNode(List, object)));
    2373          15 :             break;
    2374             :         case OBJECT_ROLE:
    2375             : 
    2376             :             /*
    2377             :              * We treat roles as being "owned" by those with CREATEROLE priv,
    2378             :              * except that superusers are only owned by superusers.
    2379             :              */
    2380           0 :             if (superuser_arg(address.objectId))
    2381             :             {
    2382           0 :                 if (!superuser_arg(roleid))
    2383           0 :                     ereport(ERROR,
    2384             :                             (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2385             :                              errmsg("must be superuser")));
    2386             :             }
    2387             :             else
    2388             :             {
    2389           0 :                 if (!has_createrole_privilege(roleid))
    2390           0 :                     ereport(ERROR,
    2391             :                             (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2392             :                              errmsg("must have CREATEROLE privilege")));
    2393             :             }
    2394           0 :             break;
    2395             :         case OBJECT_TSPARSER:
    2396             :         case OBJECT_TSTEMPLATE:
    2397             :         case OBJECT_ACCESS_METHOD:
    2398             :             /* We treat these object types as being owned by superusers */
    2399           3 :             if (!superuser_arg(roleid))
    2400           0 :                 ereport(ERROR,
    2401             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2402             :                          errmsg("must be superuser")));
    2403           3 :             break;
    2404             :         case OBJECT_STATISTIC_EXT:
    2405           0 :             if (!pg_statistics_object_ownercheck(address.objectId, roleid))
    2406           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
    2407           0 :             break;
    2408             :         default:
    2409           0 :             elog(ERROR, "unrecognized object type: %d",
    2410             :                  (int) objtype);
    2411             :     }
    2412         563 : }
    2413             : 
    2414             : /*
    2415             :  * get_object_namespace
    2416             :  *
    2417             :  * Find the schema containing the specified object.  For non-schema objects,
    2418             :  * this function returns InvalidOid.
    2419             :  */
    2420             : Oid
    2421         487 : get_object_namespace(const ObjectAddress *address)
    2422             : {
    2423             :     int         cache;
    2424             :     HeapTuple   tuple;
    2425             :     bool        isnull;
    2426             :     Oid         oid;
    2427             :     const ObjectPropertyType *property;
    2428             : 
    2429             :     /* If not owned by a namespace, just return InvalidOid. */
    2430         487 :     property = get_object_property_data(address->classId);
    2431         487 :     if (property->attnum_namespace == InvalidAttrNumber)
    2432         178 :         return InvalidOid;
    2433             : 
    2434             :     /* Currently, we can only handle object types with system caches. */
    2435         309 :     cache = property->oid_catcache_id;
    2436         309 :     Assert(cache != -1);
    2437             : 
    2438             :     /* Fetch tuple from syscache and extract namespace attribute. */
    2439         309 :     tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
    2440         309 :     if (!HeapTupleIsValid(tuple))
    2441           0 :         elog(ERROR, "cache lookup failed for cache %d oid %u",
    2442             :              cache, address->objectId);
    2443         309 :     oid = DatumGetObjectId(SysCacheGetAttr(cache,
    2444             :                                            tuple,
    2445             :                                            property->attnum_namespace,
    2446             :                                            &isnull));
    2447         309 :     Assert(!isnull);
    2448         309 :     ReleaseSysCache(tuple);
    2449             : 
    2450         309 :     return oid;
    2451             : }
    2452             : 
    2453             : /*
    2454             :  * Return ObjectType for the given object type as given by
    2455             :  * getObjectTypeDescription; if no valid ObjectType code exists, but it's a
    2456             :  * possible output type from getObjectTypeDescription, return -1.
    2457             :  * Otherwise, an error is thrown.
    2458             :  */
    2459             : int
    2460         324 : read_objtype_from_string(const char *objtype)
    2461             : {
    2462             :     int         i;
    2463             : 
    2464        9101 :     for (i = 0; i < lengthof(ObjectTypeMap); i++)
    2465             :     {
    2466        9100 :         if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
    2467         323 :             return ObjectTypeMap[i].tm_type;
    2468             :     }
    2469           1 :     ereport(ERROR,
    2470             :             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2471             :              errmsg("unrecognized object type \"%s\"", objtype)));
    2472             : 
    2473             :     return -1;                  /* keep compiler quiet */
    2474             : }
    2475             : 
    2476             : /*
    2477             :  * Interfaces to reference fields of ObjectPropertyType
    2478             :  */
    2479             : Oid
    2480          63 : get_object_oid_index(Oid class_id)
    2481             : {
    2482          63 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2483             : 
    2484          63 :     return prop->oid_index_oid;
    2485             : }
    2486             : 
    2487             : int
    2488         577 : get_object_catcache_oid(Oid class_id)
    2489             : {
    2490         577 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2491             : 
    2492         577 :     return prop->oid_catcache_id;
    2493             : }
    2494             : 
    2495             : int
    2496          98 : get_object_catcache_name(Oid class_id)
    2497             : {
    2498          98 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2499             : 
    2500          98 :     return prop->name_catcache_id;
    2501             : }
    2502             : 
    2503             : AttrNumber
    2504         442 : get_object_attnum_name(Oid class_id)
    2505             : {
    2506         442 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2507             : 
    2508         442 :     return prop->attnum_name;
    2509             : }
    2510             : 
    2511             : AttrNumber
    2512         519 : get_object_attnum_namespace(Oid class_id)
    2513             : {
    2514         519 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2515             : 
    2516         519 :     return prop->attnum_namespace;
    2517             : }
    2518             : 
    2519             : AttrNumber
    2520         157 : get_object_attnum_owner(Oid class_id)
    2521             : {
    2522         157 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2523             : 
    2524         157 :     return prop->attnum_owner;
    2525             : }
    2526             : 
    2527             : AttrNumber
    2528          59 : get_object_attnum_acl(Oid class_id)
    2529             : {
    2530          59 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2531             : 
    2532          59 :     return prop->attnum_acl;
    2533             : }
    2534             : 
    2535             : AclObjectKind
    2536         137 : get_object_aclkind(Oid class_id)
    2537             : {
    2538         137 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2539             : 
    2540         137 :     return prop->acl_kind;
    2541             : }
    2542             : 
    2543             : bool
    2544         362 : get_object_namensp_unique(Oid class_id)
    2545             : {
    2546         362 :     const ObjectPropertyType *prop = get_object_property_data(class_id);
    2547             : 
    2548         362 :     return prop->is_nsp_name_unique;
    2549             : }
    2550             : 
    2551             : /*
    2552             :  * Return whether we have useful data for the given object class in the
    2553             :  * ObjectProperty table.
    2554             :  */
    2555             : bool
    2556         412 : is_objectclass_supported(Oid class_id)
    2557             : {
    2558             :     int         index;
    2559             : 
    2560        8714 :     for (index = 0; index < lengthof(ObjectProperty); index++)
    2561             :     {
    2562        8664 :         if (ObjectProperty[index].class_oid == class_id)
    2563         362 :             return true;
    2564             :     }
    2565             : 
    2566          50 :     return false;
    2567             : }
    2568             : 
    2569             : /*
    2570             :  * Find ObjectProperty structure by class_id.
    2571             :  */
    2572             : static const ObjectPropertyType *
    2573        2901 : get_object_property_data(Oid class_id)
    2574             : {
    2575             :     static const ObjectPropertyType *prop_last = NULL;
    2576             :     int         index;
    2577             : 
    2578             :     /*
    2579             :      * A shortcut to speed up multiple consecutive lookups of a particular
    2580             :      * object class.
    2581             :      */
    2582        2901 :     if (prop_last && prop_last->class_oid == class_id)
    2583        2593 :         return prop_last;
    2584             : 
    2585        5662 :     for (index = 0; index < lengthof(ObjectProperty); index++)
    2586             :     {
    2587        5662 :         if (ObjectProperty[index].class_oid == class_id)
    2588             :         {
    2589         308 :             prop_last = &ObjectProperty[index];
    2590         308 :             return &ObjectProperty[index];
    2591             :         }
    2592             :     }
    2593             : 
    2594           0 :     ereport(ERROR,
    2595             :             (errmsg_internal("unrecognized class ID: %u", class_id)));
    2596             : 
    2597             :     return NULL;                /* keep MSC compiler happy */
    2598             : }
    2599             : 
    2600             : /*
    2601             :  * Return a copy of the tuple for the object with the given object OID, from
    2602             :  * the given catalog (which must have been opened by the caller and suitably
    2603             :  * locked).  NULL is returned if the OID is not found.
    2604             :  *
    2605             :  * We try a syscache first, if available.
    2606             :  */
    2607             : HeapTuple
    2608         479 : get_catalog_object_by_oid(Relation catalog, Oid objectId)
    2609             : {
    2610             :     HeapTuple   tuple;
    2611         479 :     Oid         classId = RelationGetRelid(catalog);
    2612         479 :     int         oidCacheId = get_object_catcache_oid(classId);
    2613             : 
    2614         479 :     if (oidCacheId > 0)
    2615             :     {
    2616         416 :         tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
    2617         416 :         if (!HeapTupleIsValid(tuple))   /* should not happen */
    2618           0 :             return NULL;
    2619             :     }
    2620             :     else
    2621             :     {
    2622          63 :         Oid         oidIndexId = get_object_oid_index(classId);
    2623             :         SysScanDesc scan;
    2624             :         ScanKeyData skey;
    2625             : 
    2626          63 :         Assert(OidIsValid(oidIndexId));
    2627             : 
    2628          63 :         ScanKeyInit(&skey,
    2629             :                     ObjectIdAttributeNumber,
    2630             :                     BTEqualStrategyNumber, F_OIDEQ,
    2631             :                     ObjectIdGetDatum(objectId));
    2632             : 
    2633          63 :         scan = systable_beginscan(catalog, oidIndexId, true,
    2634             :                                   NULL, 1, &skey);
    2635          63 :         tuple = systable_getnext(scan);
    2636          63 :         if (!HeapTupleIsValid(tuple))
    2637             :         {
    2638           0 :             systable_endscan(scan);
    2639           0 :             return NULL;
    2640             :         }
    2641          63 :         tuple = heap_copytuple(tuple);
    2642             : 
    2643          63 :         systable_endscan(scan);
    2644             :     }
    2645             : 
    2646         479 :     return tuple;
    2647             : }
    2648             : 
    2649             : /*
    2650             :  * getObjectDescription: build an object description for messages
    2651             :  *
    2652             :  * The result is a palloc'd string.
    2653             :  */
    2654             : char *
    2655        6754 : getObjectDescription(const ObjectAddress *object)
    2656             : {
    2657             :     StringInfoData buffer;
    2658             : 
    2659        6754 :     initStringInfo(&buffer);
    2660             : 
    2661        6754 :     switch (getObjectClass(object))
    2662             :     {
    2663             :         case OCLASS_CLASS:
    2664        1927 :             getRelationDescription(&buffer, object->objectId);
    2665        1927 :             if (object->objectSubId != 0)
    2666         137 :                 appendStringInfo(&buffer, _(" column %s"),
    2667             :                                  get_relid_attribute_name(object->objectId,
    2668         137 :                                                           object->objectSubId));
    2669        1927 :             break;
    2670             : 
    2671             :         case OCLASS_PROC:
    2672          74 :             appendStringInfo(&buffer, _("function %s"),
    2673             :                              format_procedure(object->objectId));
    2674          74 :             break;
    2675             : 
    2676             :         case OCLASS_TYPE:
    2677        3326 :             appendStringInfo(&buffer, _("type %s"),
    2678             :                              format_type_be(object->objectId));
    2679        3326 :             break;
    2680             : 
    2681             :         case OCLASS_CAST:
    2682             :             {
    2683             :                 Relation    castDesc;
    2684             :                 ScanKeyData skey[1];
    2685             :                 SysScanDesc rcscan;
    2686             :                 HeapTuple   tup;
    2687             :                 Form_pg_cast castForm;
    2688             : 
    2689           1 :                 castDesc = heap_open(CastRelationId, AccessShareLock);
    2690             : 
    2691           1 :                 ScanKeyInit(&skey[0],
    2692             :                             ObjectIdAttributeNumber,
    2693             :                             BTEqualStrategyNumber, F_OIDEQ,
    2694           1 :                             ObjectIdGetDatum(object->objectId));
    2695             : 
    2696           1 :                 rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
    2697             :                                             NULL, 1, skey);
    2698             : 
    2699           1 :                 tup = systable_getnext(rcscan);
    2700             : 
    2701           1 :                 if (!HeapTupleIsValid(tup))
    2702           0 :                     elog(ERROR, "could not find tuple for cast %u",
    2703             :                          object->objectId);
    2704             : 
    2705           1 :                 castForm = (Form_pg_cast) GETSTRUCT(tup);
    2706             : 
    2707           1 :                 appendStringInfo(&buffer, _("cast from %s to %s"),
    2708             :                                  format_type_be(castForm->castsource),
    2709             :                                  format_type_be(castForm->casttarget));
    2710             : 
    2711           1 :                 systable_endscan(rcscan);
    2712           1 :                 heap_close(castDesc, AccessShareLock);
    2713           1 :                 break;
    2714             :             }
    2715             : 
    2716             :         case OCLASS_COLLATION:
    2717             :             {
    2718             :                 HeapTuple   collTup;
    2719             :                 Form_pg_collation coll;
    2720             : 
    2721           3 :                 collTup = SearchSysCache1(COLLOID,
    2722             :                                           ObjectIdGetDatum(object->objectId));
    2723           3 :                 if (!HeapTupleIsValid(collTup))
    2724           0 :                     elog(ERROR, "cache lookup failed for collation %u",
    2725             :                          object->objectId);
    2726           3 :                 coll = (Form_pg_collation) GETSTRUCT(collTup);
    2727           3 :                 appendStringInfo(&buffer, _("collation %s"),
    2728           3 :                                  NameStr(coll->collname));
    2729           3 :                 ReleaseSysCache(collTup);
    2730           3 :                 break;
    2731             :             }
    2732             : 
    2733             :         case OCLASS_CONSTRAINT:
    2734             :             {
    2735             :                 HeapTuple   conTup;
    2736             :                 Form_pg_constraint con;
    2737             : 
    2738         401 :                 conTup = SearchSysCache1(CONSTROID,
    2739             :                                          ObjectIdGetDatum(object->objectId));
    2740         401 :                 if (!HeapTupleIsValid(conTup))
    2741           0 :                     elog(ERROR, "cache lookup failed for constraint %u",
    2742             :                          object->objectId);
    2743         401 :                 con = (Form_pg_constraint) GETSTRUCT(conTup);
    2744             : 
    2745         401 :                 if (OidIsValid(con->conrelid))
    2746             :                 {
    2747             :                     StringInfoData rel;
    2748             : 
    2749         383 :                     initStringInfo(&rel);
    2750         383 :                     getRelationDescription(&rel, con->conrelid);
    2751         766 :                     appendStringInfo(&buffer, _("constraint %s on %s"),
    2752         383 :                                      NameStr(con->conname), rel.data);
    2753         383 :                     pfree(rel.data);
    2754             :                 }
    2755             :                 else
    2756             :                 {
    2757          18 :                     appendStringInfo(&buffer, _("constraint %s"),
    2758          18 :                                      NameStr(con->conname));
    2759             :                 }
    2760             : 
    2761         401 :                 ReleaseSysCache(conTup);
    2762         401 :                 break;
    2763             :             }
    2764             : 
    2765             :         case OCLASS_CONVERSION:
    2766             :             {
    2767             :                 HeapTuple   conTup;
    2768             : 
    2769           5 :                 conTup = SearchSysCache1(CONVOID,
    2770             :                                          ObjectIdGetDatum(object->objectId));
    2771           5 :                 if (!HeapTupleIsValid(conTup))
    2772           0 :                     elog(ERROR, "cache lookup failed for conversion %u",
    2773             :                          object->objectId);
    2774           5 :                 appendStringInfo(&buffer, _("conversion %s"),
    2775           5 :                                  NameStr(((Form_pg_conversion) GETSTRUCT(conTup))->conname));
    2776           5 :                 ReleaseSysCache(conTup);
    2777           5 :                 break;
    2778             :             }
    2779             : 
    2780             :         case OCLASS_DEFAULT:
    2781             :             {
    2782             :                 Relation    attrdefDesc;
    2783             :                 ScanKeyData skey[1];
    2784             :                 SysScanDesc adscan;
    2785             :                 HeapTuple   tup;
    2786             :                 Form_pg_attrdef attrdef;
    2787             :                 ObjectAddress colobject;
    2788             : 
    2789         129 :                 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
    2790             : 
    2791         129 :                 ScanKeyInit(&skey[0],
    2792             :                             ObjectIdAttributeNumber,
    2793             :                             BTEqualStrategyNumber, F_OIDEQ,
    2794         129 :                             ObjectIdGetDatum(object->objectId));
    2795             : 
    2796         129 :                 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
    2797             :                                             true, NULL, 1, skey);
    2798             : 
    2799         129 :                 tup = systable_getnext(adscan);
    2800             : 
    2801         129 :                 if (!HeapTupleIsValid(tup))
    2802           0 :                     elog(ERROR, "could not find tuple for attrdef %u",
    2803             :                          object->objectId);
    2804             : 
    2805         129 :                 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
    2806             : 
    2807         129 :                 colobject.classId = RelationRelationId;
    2808         129 :                 colobject.objectId = attrdef->adrelid;
    2809         129 :                 colobject.objectSubId = attrdef->adnum;
    2810             : 
    2811         129 :                 appendStringInfo(&buffer, _("default for %s"),
    2812             :                                  getObjectDescription(&colobject));
    2813             : 
    2814         129 :                 systable_endscan(adscan);
    2815         129 :                 heap_close(attrdefDesc, AccessShareLock);
    2816         129 :                 break;
    2817             :             }
    2818             : 
    2819             :         case OCLASS_LANGUAGE:
    2820           0 :             appendStringInfo(&buffer, _("language %s"),
    2821             :                              get_language_name(object->objectId, false));
    2822           0 :             break;
    2823             : 
    2824             :         case OCLASS_LARGEOBJECT:
    2825           0 :             appendStringInfo(&buffer, _("large object %u"),
    2826             :                              object->objectId);
    2827           0 :             break;
    2828             : 
    2829             :         case OCLASS_OPERATOR:
    2830           5 :             appendStringInfo(&buffer, _("operator %s"),
    2831             :                              format_operator(object->objectId));
    2832           5 :             break;
    2833             : 
    2834             :         case OCLASS_OPCLASS:
    2835             :             {
    2836             :                 HeapTuple   opcTup;
    2837             :                 Form_pg_opclass opcForm;
    2838             :                 HeapTuple   amTup;
    2839             :                 Form_pg_am  amForm;
    2840             :                 char       *nspname;
    2841             : 
    2842           8 :                 opcTup = SearchSysCache1(CLAOID,
    2843             :                                          ObjectIdGetDatum(object->objectId));
    2844           8 :                 if (!HeapTupleIsValid(opcTup))
    2845           0 :                     elog(ERROR, "cache lookup failed for opclass %u",
    2846             :                          object->objectId);
    2847           8 :                 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
    2848             : 
    2849           8 :                 amTup = SearchSysCache1(AMOID,
    2850             :                                         ObjectIdGetDatum(opcForm->opcmethod));
    2851           8 :                 if (!HeapTupleIsValid(amTup))
    2852           0 :                     elog(ERROR, "cache lookup failed for access method %u",
    2853             :                          opcForm->opcmethod);
    2854           8 :                 amForm = (Form_pg_am) GETSTRUCT(amTup);
    2855             : 
    2856             :                 /* Qualify the name if not visible in search path */
    2857           8 :                 if (OpclassIsVisible(object->objectId))
    2858           6 :                     nspname = NULL;
    2859             :                 else
    2860           2 :                     nspname = get_namespace_name(opcForm->opcnamespace);
    2861             : 
    2862           8 :                 appendStringInfo(&buffer, _("operator class %s for access method %s"),
    2863             :                                  quote_qualified_identifier(nspname,
    2864           8 :                                                             NameStr(opcForm->opcname)),
    2865           8 :                                  NameStr(amForm->amname));
    2866             : 
    2867           8 :                 ReleaseSysCache(amTup);
    2868           8 :                 ReleaseSysCache(opcTup);
    2869           8 :                 break;
    2870             :             }
    2871             : 
    2872             :         case OCLASS_OPFAMILY:
    2873          13 :             getOpFamilyDescription(&buffer, object->objectId);
    2874          13 :             break;
    2875             : 
    2876             :         case OCLASS_AM:
    2877             :             {
    2878             :                 HeapTuple   tup;
    2879             : 
    2880           1 :                 tup = SearchSysCache1(AMOID,
    2881             :                                       ObjectIdGetDatum(object->objectId));
    2882           1 :                 if (!HeapTupleIsValid(tup))
    2883           0 :                     elog(ERROR, "cache lookup failed for access method %u",
    2884             :                          object->objectId);
    2885           1 :                 appendStringInfo(&buffer, _("access method %s"),
    2886           1 :                                  NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
    2887           1 :                 ReleaseSysCache(tup);
    2888           1 :                 break;
    2889             :             }
    2890             : 
    2891             :         case OCLASS_AMOP:
    2892             :             {
    2893             :                 Relation    amopDesc;
    2894             :                 HeapTuple   tup;
    2895             :                 ScanKeyData skey[1];
    2896             :                 SysScanDesc amscan;
    2897             :                 Form_pg_amop amopForm;
    2898             :                 StringInfoData opfam;
    2899             : 
    2900          43 :                 amopDesc = heap_open(AccessMethodOperatorRelationId,
    2901             :                                      AccessShareLock);
    2902             : 
    2903          43 :                 ScanKeyInit(&skey[0],
    2904             :                             ObjectIdAttributeNumber,
    2905             :                             BTEqualStrategyNumber, F_OIDEQ,
    2906          43 :                             ObjectIdGetDatum(object->objectId));
    2907             : 
    2908          43 :                 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
    2909             :                                             NULL, 1, skey);
    2910             : 
    2911          43 :                 tup = systable_getnext(amscan);
    2912             : 
    2913          43 :                 if (!HeapTupleIsValid(tup))
    2914           0 :                     elog(ERROR, "could not find tuple for amop entry %u",
    2915             :                          object->objectId);
    2916             : 
    2917          43 :                 amopForm = (Form_pg_amop) GETSTRUCT(tup);
    2918             : 
    2919          43 :                 initStringInfo(&opfam);
    2920          43 :                 getOpFamilyDescription(&opfam, amopForm->amopfamily);
    2921             : 
    2922             :                 /*------
    2923             :                    translator: %d is the operator strategy (a number), the
    2924             :                    first two %s's are data type names, the third %s is the
    2925             :                    description of the operator family, and the last %s is the
    2926             :                    textual form of the operator with arguments.  */
    2927          86 :                 appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
    2928          43 :                                  amopForm->amopstrategy,
    2929             :                                  format_type_be(amopForm->amoplefttype),
    2930             :                                  format_type_be(amopForm->amoprighttype),
    2931             :                                  opfam.data,
    2932             :                                  format_operator(amopForm->amopopr));
    2933             : 
    2934          43 :                 pfree(opfam.data);
    2935             : 
    2936          43 :                 systable_endscan(amscan);
    2937          43 :                 heap_close(amopDesc, AccessShareLock);
    2938          43 :                 break;
    2939             :             }
    2940             : 
    2941             :         case OCLASS_AMPROC:
    2942             :             {
    2943             :                 Relation    amprocDesc;
    2944             :                 ScanKeyData skey[1];
    2945             :                 SysScanDesc amscan;
    2946             :                 HeapTuple   tup;
    2947             :                 Form_pg_amproc amprocForm;
    2948             :                 StringInfoData opfam;
    2949             : 
    2950          18 :                 amprocDesc = heap_open(AccessMethodProcedureRelationId,
    2951             :                                        AccessShareLock);
    2952             : 
    2953          18 :                 ScanKeyInit(&skey[0],
    2954             :                             ObjectIdAttributeNumber,
    2955             :                             BTEqualStrategyNumber, F_OIDEQ,
    2956          18 :                             ObjectIdGetDatum(object->objectId));
    2957             : 
    2958          18 :                 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
    2959             :                                             NULL, 1, skey);
    2960             : 
    2961          18 :                 tup = systable_getnext(amscan);
    2962             : 
    2963          18 :                 if (!HeapTupleIsValid(tup))
    2964           0 :                     elog(ERROR, "could not find tuple for amproc entry %u",
    2965             :                          object->objectId);
    2966             : 
    2967          18 :                 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
    2968             : 
    2969          18 :                 initStringInfo(&opfam);
    2970          18 :                 getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
    2971             : 
    2972             :                 /*------
    2973             :                    translator: %d is the function number, the first two %s's
    2974             :                    are data type names, the third %s is the description of the
    2975             :                    operator family, and the last %s is the textual form of the
    2976             :                    function with arguments.  */
    2977          36 :                 appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
    2978          18 :                                  amprocForm->amprocnum,
    2979             :                                  format_type_be(amprocForm->amproclefttype),
    2980             :                                  format_type_be(amprocForm->amprocrighttype),
    2981             :                                  opfam.data,
    2982             :                                  format_procedure(amprocForm->amproc));
    2983             : 
    2984          18 :                 pfree(opfam.data);
    2985             : 
    2986          18 :                 systable_endscan(amscan);
    2987          18 :                 heap_close(amprocDesc, AccessShareLock);
    2988          18 :                 break;
    2989             :             }
    2990             : 
    2991             :         case OCLASS_REWRITE:
    2992             :             {
    2993             :                 Relation    ruleDesc;
    2994             :                 ScanKeyData skey[1];
    2995             :                 SysScanDesc rcscan;
    2996             :                 HeapTuple   tup;
    2997             :                 Form_pg_rewrite rule;
    2998             : 
    2999         274 :                 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
    3000             : 
    3001         274 :                 ScanKeyInit(&skey[0],
    3002             :                             ObjectIdAttributeNumber,
    3003             :                             BTEqualStrategyNumber, F_OIDEQ,
    3004         274 :                             ObjectIdGetDatum(object->objectId));
    3005             : 
    3006         274 :                 rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
    3007             :                                             NULL, 1, skey);
    3008             : 
    3009         274 :                 tup = systable_getnext(rcscan);
    3010             : 
    3011         274 :                 if (!HeapTupleIsValid(tup))
    3012           0 :                     elog(ERROR, "could not find tuple for rule %u",
    3013             :                          object->objectId);
    3014             : 
    3015         274 :                 rule = (Form_pg_rewrite) GETSTRUCT(tup);
    3016             : 
    3017         274 :                 appendStringInfo(&buffer, _("rule %s on "),
    3018         274 :                                  NameStr(rule->rulename));
    3019         274 :                 getRelationDescription(&buffer, rule->ev_class);
    3020             : 
    3021         274 :                 systable_endscan(rcscan);
    3022         274 :                 heap_close(ruleDesc, AccessShareLock);
    3023         274 :                 break;
    3024             :             }
    3025             : 
    3026             :         case OCLASS_TRIGGER:
    3027             :             {
    3028             :                 Relation    trigDesc;
    3029             :                 ScanKeyData skey[1];
    3030             :                 SysScanDesc tgscan;
    3031             :                 HeapTuple   tup;
    3032             :                 Form_pg_trigger trig;
    3033             : 
    3034         354 :                 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
    3035             : 
    3036         354 :                 ScanKeyInit(&skey[0],
    3037             :                             ObjectIdAttributeNumber,
    3038             :                             BTEqualStrategyNumber, F_OIDEQ,
    3039         354 :                             ObjectIdGetDatum(object->objectId));
    3040             : 
    3041         354 :                 tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
    3042             :                                             NULL, 1, skey);
    3043             : 
    3044         354 :                 tup = systable_getnext(tgscan);
    3045             : 
    3046         354 :                 if (!HeapTupleIsValid(tup))
    3047           0 :                     elog(ERROR, "could not find tuple for trigger %u",
    3048             :                          object->objectId);
    3049             : 
    3050         354 :                 trig = (Form_pg_trigger) GETSTRUCT(tup);
    3051             : 
    3052         354 :                 appendStringInfo(&buffer, _("trigger %s on "),
    3053         354 :                                  NameStr(trig->tgname));
    3054         354 :                 getRelationDescription(&buffer, trig->tgrelid);
    3055             : 
    3056         354 :                 systable_endscan(tgscan);
    3057         354 :                 heap_close(trigDesc, AccessShareLock);
    3058         354 :                 break;
    3059             :             }
    3060             : 
    3061             :         case OCLASS_SCHEMA:
    3062             :             {
    3063             :                 char       *nspname;
    3064             : 
    3065           8 :                 nspname = get_namespace_name(object->objectId);
    3066           8 :                 if (!nspname)
    3067           0 :                     elog(ERROR, "cache lookup failed for namespace %u",
    3068             :                          object->objectId);
    3069           8 :                 appendStringInfo(&buffer, _("schema %s"), nspname);
    3070           8 :                 break;
    3071             :             }
    3072             : 
    3073             :         case OCLASS_STATISTIC_EXT:
    3074             :             {
    3075             :                 HeapTuple   stxTup;
    3076             :                 Form_pg_statistic_ext stxForm;
    3077             : 
    3078          14 :                 stxTup = SearchSysCache1(STATEXTOID,
    3079             :                                          ObjectIdGetDatum(object->objectId));
    3080          14 :                 if (!HeapTupleIsValid(stxTup))
    3081           0 :                     elog(ERROR, "could not find tuple for statistics object %u",
    3082             :                          object->objectId);
    3083             : 
    3084          14 :                 stxForm = (Form_pg_statistic_ext) GETSTRUCT(stxTup);
    3085             : 
    3086          14 :                 appendStringInfo(&buffer, _("statistics object %s"),
    3087          14 :                                  NameStr(stxForm->stxname));
    3088             : 
    3089          14 :                 ReleaseSysCache(stxTup);
    3090          14 :                 break;
    3091             :             }
    3092             : 
    3093             :         case OCLASS_TSPARSER:
    3094             :             {
    3095             :                 HeapTuple   tup;
    3096             : 
    3097           5 :                 tup = SearchSysCache1(TSPARSEROID,
    3098             :                                       ObjectIdGetDatum(object->objectId));
    3099           5 :                 if (!HeapTupleIsValid(tup))
    3100           0 :                     elog(ERROR, "cache lookup failed for text search parser %u",
    3101             :                          object->objectId);
    3102           5 :                 appendStringInfo(&buffer, _("text search parser %s"),
    3103           5 :                                  NameStr(((Form_pg_ts_parser) GETSTRUCT(tup))->prsname));
    3104           5 :                 ReleaseSysCache(tup);
    3105           5 :                 break;
    3106             :             }
    3107             : 
    3108             :         case OCLASS_TSDICT:
    3109             :             {
    3110             :                 HeapTuple   tup;
    3111             : 
    3112           6 :                 tup = SearchSysCache1(TSDICTOID,
    3113             :                                       ObjectIdGetDatum(object->objectId));
    3114           6 :                 if (!HeapTupleIsValid(tup))
    3115           0 :                     elog(ERROR, "cache lookup failed for text search dictionary %u",
    3116             :                          object->objectId);
    3117           6 :                 appendStringInfo(&buffer, _("text search dictionary %s"),
    3118           6 :                                  NameStr(((Form_pg_ts_dict) GETSTRUCT(tup))->dictname));
    3119           6 :                 ReleaseSysCache(tup);
    3120           6 :                 break;
    3121             :             }
    3122             : 
    3123             :         case OCLASS_TSTEMPLATE:
    3124             :             {
    3125             :                 HeapTuple   tup;
    3126             : 
    3127           5 :                 tup = SearchSysCache1(TSTEMPLATEOID,
    3128             :                                       ObjectIdGetDatum(object->objectId));
    3129           5 :                 if (!HeapTupleIsValid(tup))
    3130           0 :                     elog(ERROR, "cache lookup failed for text search template %u",
    3131             :                          object->objectId);
    3132           5 :                 appendStringInfo(&buffer, _("text search template %s"),
    3133           5 :                                  NameStr(((Form_pg_ts_template) GETSTRUCT(tup))->tmplname));
    3134           5 :                 ReleaseSysCache(tup);
    3135           5 :                 break;
    3136             :             }
    3137             : 
    3138             :         case OCLASS_TSCONFIG:
    3139             :             {
    3140             :                 HeapTuple   tup;
    3141             : 
    3142           6 :                 tup = SearchSysCache1(TSCONFIGOID,
    3143             :                                       ObjectIdGetDatum(object->objectId));
    3144           6 :                 if (!HeapTupleIsValid(tup))
    3145           0 :                     elog(ERROR, "cache lookup failed for text search configuration %u",
    3146             :                          object->objectId);
    3147           6 :                 appendStringInfo(&buffer, _("text search configuration %s"),
    3148           6 :                                  NameStr(((Form_pg_ts_config) GETSTRUCT(tup))->cfgname));
    3149           6 :                 ReleaseSysCache(tup);
    3150           6 :                 break;
    3151             :             }
    3152             : 
    3153             :         case OCLASS_ROLE:
    3154             :             {
    3155           0 :                 appendStringInfo(&buffer, _("role %s"),
    3156             :                                  GetUserNameFromId(object->objectId, false));
    3157           0 :                 break;
    3158             :             }
    3159             : 
    3160             :         case OCLASS_DATABASE:
    3161             :             {
    3162             :                 char       *datname;
    3163             : 
    3164           2 :                 datname = get_database_name(object->objectId);
    3165           2 :                 if (!datname)
    3166           0 :                     elog(ERROR, "cache lookup failed for database %u",
    3167             :                          object->objectId);
    3168           2 :                 appendStringInfo(&buffer, _("database %s"), datname);
    3169           2 :                 break;
    3170             :             }
    3171             : 
    3172             :         case OCLASS_TBLSPACE:
    3173             :             {
    3174             :                 char       *tblspace;
    3175             : 
    3176           0 :                 tblspace = get_tablespace_name(object->objectId);
    3177           0 :                 if (!tblspace)
    3178           0 :                     elog(ERROR, "cache lookup failed for tablespace %u",
    3179             :                          object->objectId);
    3180           0 :                 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
    3181           0 :                 break;
    3182             :             }
    3183             : 
    3184             :         case OCLASS_FDW:
    3185             :             {
    3186             :                 ForeignDataWrapper *fdw;
    3187             : 
    3188          10 :                 fdw = GetForeignDataWrapper(object->objectId);
    3189          10 :                 appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
    3190          10 :                 break;
    3191             :             }
    3192             : 
    3193             :         case OCLASS_FOREIGN_SERVER:
    3194             :             {
    3195             :                 ForeignServer *srv;
    3196             : 
    3197          19 :                 srv = GetForeignServer(object->objectId);
    3198          19 :                 appendStringInfo(&buffer, _("server %s"), srv->servername);
    3199          19 :                 break;
    3200             :             }
    3201             : 
    3202             :         case OCLASS_USER_MAPPING:
    3203             :             {
    3204             :                 HeapTuple   tup;
    3205             :                 Oid         useid;
    3206             :                 char       *usename;
    3207             :                 Form_pg_user_mapping umform;
    3208             :                 ForeignServer *srv;
    3209             : 
    3210          20 :                 tup = SearchSysCache1(USERMAPPINGOID,
    3211             :                                       ObjectIdGetDatum(object->objectId));
    3212          20 :                 if (!HeapTupleIsValid(tup))
    3213           0 :                     elog(ERROR, "cache lookup failed for user mapping %u",
    3214             :                          object->objectId);
    3215          20 :                 umform = (Form_pg_user_mapping) GETSTRUCT(tup);
    3216          20 :                 useid = umform->umuser;
    3217          20 :                 srv = GetForeignServer(umform->umserver);
    3218             : 
    3219          20 :                 ReleaseSysCache(tup);
    3220             : 
    3221          20 :                 if (OidIsValid(useid))
    3222          16 :                     usename = GetUserNameFromId(useid, false);
    3223             :                 else
    3224           4 :                     usename = "public";
    3225             : 
    3226          20 :                 appendStringInfo(&buffer, _("user mapping for %s on server %s"), usename,
    3227             :                                  srv->servername);
    3228          20 :                 break;
    3229             :             }
    3230             : 
    3231             :         case OCLASS_DEFACL:
    3232             :             {
    3233             :                 Relation    defaclrel;
    3234             :                 ScanKeyData skey[1];
    3235             :                 SysScanDesc rcscan;
    3236             :                 HeapTuple   tup;
    3237             :                 Form_pg_default_acl defacl;
    3238             : 
    3239           7 :                 defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
    3240             : 
    3241           7 :                 ScanKeyInit(&skey[0],
    3242             :                             ObjectIdAttributeNumber,
    3243             :                             BTEqualStrategyNumber, F_OIDEQ,
    3244           7 :                             ObjectIdGetDatum(object->objectId));
    3245             : 
    3246           7 :                 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
    3247             :                                             true, NULL, 1, skey);
    3248             : 
    3249           7 :                 tup = systable_getnext(rcscan);
    3250             : 
    3251           7 :                 if (!HeapTupleIsValid(tup))
    3252           0 :                     elog(ERROR, "could not find tuple for default ACL %u",
    3253             :                          object->objectId);
    3254             : 
    3255           7 :                 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
    3256             : 
    3257           7 :                 switch (defacl->defaclobjtype)
    3258             :                 {
    3259             :                     case DEFACLOBJ_RELATION:
    3260           5 :                         appendStringInfo(&buffer,
    3261             :                                          _("default privileges on new relations belonging to role %s"),
    3262             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3263           5 :                         break;
    3264             :                     case DEFACLOBJ_SEQUENCE:
    3265           0 :                         appendStringInfo(&buffer,
    3266             :                                          _("default privileges on new sequences belonging to role %s"),
    3267             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3268           0 :                         break;
    3269             :                     case DEFACLOBJ_FUNCTION:
    3270           1 :                         appendStringInfo(&buffer,
    3271             :                                          _("default privileges on new functions belonging to role %s"),
    3272             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3273           1 :                         break;
    3274             :                     case DEFACLOBJ_TYPE:
    3275           1 :                         appendStringInfo(&buffer,
    3276             :                                          _("default privileges on new types belonging to role %s"),
    3277             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3278           1 :                         break;
    3279             :                     case DEFACLOBJ_NAMESPACE:
    3280           0 :                         appendStringInfo(&buffer,
    3281             :                                          _("default privileges on new schemas belonging to role %s"),
    3282             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3283           0 :                         break;
    3284             :                     default:
    3285             :                         /* shouldn't get here */
    3286           0 :                         appendStringInfo(&buffer,
    3287             :                                          _("default privileges belonging to role %s"),
    3288             :                                          GetUserNameFromId(defacl->defaclrole, false));
    3289           0 :                         break;
    3290             :                 }
    3291             : 
    3292           7 :                 if (OidIsValid(defacl->defaclnamespace))
    3293             :                 {
    3294           5 :                     appendStringInfo(&buffer,
    3295             :                                      _(" in schema %s"),
    3296             :                                      get_namespace_name(defacl->defaclnamespace));
    3297             :                 }
    3298             : 
    3299           7 :                 systable_endscan(rcscan);
    3300           7 :                 heap_close(defaclrel, AccessShareLock);
    3301           7 :                 break;
    3302             :             }
    3303             : 
    3304             :         case OCLASS_EXTENSION:
    3305             :             {
    3306             :                 char       *extname;
    3307             : 
    3308           0 :                 extname = get_extension_name(object->objectId);
    3309           0 :                 if (!extname)
    3310           0 :                     elog(ERROR, "cache lookup failed for extension %u",
    3311             :                          object->objectId);
    3312           0 :                 appendStringInfo(&buffer, _("extension %s"), extname);
    3313           0 :                 break;
    3314             :             }
    3315             : 
    3316             :         case OCLASS_EVENT_TRIGGER:
    3317             :             {
    3318             :                 HeapTuple   tup;
    3319             : 
    3320           2 :                 tup = SearchSysCache1(EVENTTRIGGEROID,
    3321             :                                       ObjectIdGetDatum(object->objectId));
    3322           2 :                 if (!HeapTupleIsValid(tup))
    3323           0 :                     elog(ERROR, "cache lookup failed for event trigger %u",
    3324             :                          object->objectId);
    3325           2 :                 appendStringInfo(&buffer, _("event trigger %s"),
    3326           2 :                                  NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname));
    3327           2 :                 ReleaseSysCache(tup);
    3328           2 :                 break;
    3329             :             }
    3330             : 
    3331             :         case OCLASS_POLICY:
    3332             :             {
    3333             :                 Relation    policy_rel;
    3334             :                 ScanKeyData skey[1];
    3335             :                 SysScanDesc sscan;
    3336             :                 HeapTuple   tuple;
    3337             :                 Form_pg_policy form_policy;
    3338             : 
    3339          59 :                 policy_rel = heap_open(PolicyRelationId, AccessShareLock);
    3340             : 
    3341          59 :                 ScanKeyInit(&skey[0],
    3342             :                             ObjectIdAttributeNumber,
    3343             :                             BTEqualStrategyNumber, F_OIDEQ,
    3344          59 :                             ObjectIdGetDatum(object->objectId));
    3345             : 
    3346          59 :                 sscan = systable_beginscan(policy_rel, PolicyOidIndexId,
    3347             :                                            true, NULL, 1, skey);
    3348             : 
    3349          59 :                 tuple = systable_getnext(sscan);
    3350             : 
    3351          59 :                 if (!HeapTupleIsValid(tuple))
    3352           0 :                     elog(ERROR, "could not find tuple for policy %u",
    3353             :                          object->objectId);
    3354             : 
    3355          59 :                 form_policy = (Form_pg_policy) GETSTRUCT(tuple);
    3356             : 
    3357          59 :                 appendStringInfo(&buffer, _("policy %s on "),
    3358          59 :                                  NameStr(form_policy->polname));
    3359          59 :                 getRelationDescription(&buffer, form_policy->polrelid);
    3360             : 
    3361          59 :                 systable_endscan(sscan);
    3362          59 :                 heap_close(policy_rel, AccessShareLock);
    3363          59 :                 break;
    3364             :             }
    3365             : 
    3366             :         case OCLASS_PUBLICATION:
    3367             :             {
    3368           0 :                 appendStringInfo(&buffer, _("publication %s"),
    3369             :                                  get_publication_name(object->objectId));
    3370           0 :                 break;
    3371             :             }
    3372             : 
    3373             :         case OCLASS_PUBLICATION_REL:
    3374             :             {
    3375             :                 HeapTuple   tup;
    3376             :                 char       *pubname;
    3377             :                 Form_pg_publication_rel prform;
    3378             : 
    3379           9 :                 tup = SearchSysCache1(PUBLICATIONREL,
    3380             :                                       ObjectIdGetDatum(object->objectId));
    3381           9 :                 if (!HeapTupleIsValid(tup))
    3382           0 :                     elog(ERROR, "cache lookup failed for publication table %u",
    3383             :                          object->objectId);
    3384             : 
    3385           9 :                 prform = (Form_pg_publication_rel) GETSTRUCT(tup);
    3386           9 :                 pubname = get_publication_name(prform->prpubid);
    3387             : 
    3388           9 :                 appendStringInfo(&buffer, _("publication table %s in publication %s"),
    3389             :                                  get_rel_name(prform->prrelid), pubname);
    3390           9 :                 ReleaseSysCache(tup);
    3391           9 :                 break;
    3392             :             }
    3393             : 
    3394             :         case OCLASS_SUBSCRIPTION:
    3395             :             {
    3396           0 :                 appendStringInfo(&buffer, _("subscription %s"),
    3397             :                                  get_subscription_name(object->objectId));
    3398           0 :                 break;
    3399             :             }
    3400             : 
    3401             :         case OCLASS_TRANSFORM:
    3402             :             {
    3403             :                 HeapTuple   trfTup;
    3404             :                 Form_pg_transform trfForm;
    3405             : 
    3406           0 :                 trfTup = SearchSysCache1(TRFOID,
    3407             :                                          ObjectIdGetDatum(object->objectId));
    3408           0 :                 if (!HeapTupleIsValid(trfTup))
    3409           0 :                     elog(ERROR, "could not find tuple for transform %u",
    3410             :                          object->objectId);
    3411             : 
    3412           0 :                 trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
    3413             : 
    3414           0 :                 appendStringInfo(&buffer, _("transform for %s language %s"),
    3415             :                                  format_type_be(trfForm->trftype),
    3416             :                                  get_language_name(trfForm->trflang, false));
    3417             : 
    3418           0 :                 ReleaseSysCache(trfTup);
    3419           0 :                 break;
    3420             :             }
    3421             : 
    3422             :             /*
    3423             :              * There's intentionally no default: case here; we want the
    3424             :              * compiler to warn if a new OCLASS hasn't been handled above.
    3425             :              */
    3426             :     }
    3427             : 
    3428        6754 :     return buffer.data;
    3429             : }
    3430             : 
    3431             : /*
    3432             :  * getObjectDescriptionOids: as above, except the object is specified by Oids
    3433             :  */
    3434             : char *
    3435           0 : getObjectDescriptionOids(Oid classid, Oid objid)
    3436             : {
    3437             :     ObjectAddress address;
    3438             : 
    3439           0 :     address.classId = classid;
    3440           0 :     address.objectId = objid;
    3441           0 :     address.objectSubId = 0;
    3442             : 
    3443           0 :     return getObjectDescription(&address);
    3444             : }
    3445             : 
    3446             : /*
    3447             :  * subroutine for getObjectDescription: describe a relation
    3448             :  */
    3449             : static void
    3450        2997 : getRelationDescription(StringInfo buffer, Oid relid)
    3451             : {
    3452             :     HeapTuple   relTup;
    3453             :     Form_pg_class relForm;
    3454             :     char       *nspname;
    3455             :     char       *relname;
    3456             : 
    3457        2997 :     relTup = SearchSysCache1(RELOID,
    3458             :                              ObjectIdGetDatum(relid));
    3459        2997 :     if (!HeapTupleIsValid(relTup))
    3460           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    3461        2997 :     relForm = (Form_pg_class) GETSTRUCT(relTup);
    3462             : 
    3463             :     /* Qualify the name if not visible in search path */
    3464        2997 :     if (RelationIsVisible(relid))
    3465        1989 :         nspname = NULL;
    3466             :     else
    3467        1008 :         nspname = get_namespace_name(relForm->relnamespace);
    3468             : 
    3469        2997 :     relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
    3470             : 
    3471        2997 :     switch (relForm->relkind)
    3472             :     {
    3473             :         case RELKIND_RELATION:
    3474             :         case RELKIND_PARTITIONED_TABLE:
    3475        1201 :             appendStringInfo(buffer, _("table %s"),
    3476             :                              relname);
    3477        1201 :             break;
    3478             :         case RELKIND_INDEX:
    3479         769 :             appendStringInfo(buffer, _("index %s"),
    3480             :                              relname);
    3481         769 :             break;
    3482             :         case RELKIND_SEQUENCE:
    3483          65 :             appendStringInfo(buffer, _("sequence %s"),
    3484             :                              relname);
    3485          65 :             break;
    3486             :         case RELKIND_TOASTVALUE:
    3487         448 :             appendStringInfo(buffer, _("toast table %s"),
    3488             :                              relname);
    3489         448 :             break;
    3490             :         case RELKIND_VIEW:
    3491         403 :             appendStringInfo(buffer, _("view %s"),
    3492             :                              relname);
    3493         403 :             break;
    3494             :         case RELKIND_MATVIEW:
    3495          59 :             appendStringInfo(buffer, _("materialized view %s"),
    3496             :                              relname);
    3497          59 :             break;
    3498             :         case RELKIND_COMPOSITE_TYPE:
    3499          31 :             appendStringInfo(buffer, _("composite type %s"),
    3500             :                              relname);
    3501          31 :             break;
    3502             :         case RELKIND_FOREIGN_TABLE:
    3503          21 :             appendStringInfo(buffer, _("foreign table %s"),
    3504             :                              relname);
    3505          21 :             break;
    3506             :         default:
    3507             :             /* shouldn't get here */
    3508           0 :             appendStringInfo(buffer, _("relation %s"),
    3509             :                              relname);
    3510           0 :             break;
    3511             :     }
    3512             : 
    3513        2997 :     ReleaseSysCache(relTup);
    3514        2997 : }
    3515             : 
    3516             : /*
    3517             :  * subroutine for getObjectDescription: describe an operator family
    3518             :  */
    3519             : static void
    3520          74 : getOpFamilyDescription(StringInfo buffer, Oid opfid)
    3521             : {
    3522             :     HeapTuple   opfTup;
    3523             :     Form_pg_opfamily opfForm;
    3524             :     HeapTuple   amTup;
    3525             :     Form_pg_am  amForm;
    3526             :     char       *nspname;
    3527             : 
    3528          74 :     opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
    3529          74 :     if (!HeapTupleIsValid(opfTup))
    3530           0 :         elog(ERROR, "cache lookup failed for opfamily %u", opfid);
    3531          74 :     opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
    3532             : 
    3533          74 :     amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
    3534          74 :     if (!HeapTupleIsValid(amTup))
    3535           0 :         elog(ERROR, "cache lookup failed for access method %u",
    3536             :              opfForm->opfmethod);
    3537          74 :     amForm = (Form_pg_am) GETSTRUCT(amTup);
    3538             : 
    3539             :     /* Qualify the name if not visible in search path */
    3540          74 :     if (OpfamilyIsVisible(opfid))
    3541          71 :         nspname = NULL;
    3542             :     else
    3543           3 :         nspname = get_namespace_name(opfForm->opfnamespace);
    3544             : 
    3545          74 :     appendStringInfo(buffer, _("operator family %s for access method %s"),
    3546             :                      quote_qualified_identifier(nspname,
    3547          74 :                                                 NameStr(opfForm->opfname)),
    3548          74 :                      NameStr(amForm->amname));
    3549             : 
    3550          74 :     ReleaseSysCache(amTup);
    3551          74 :     ReleaseSysCache(opfTup);
    3552          74 : }
    3553             : 
    3554             : /*
    3555             :  * SQL-level callable version of getObjectDescription
    3556             :  */
    3557             : Datum
    3558          12 : pg_describe_object(PG_FUNCTION_ARGS)
    3559             : {
    3560          12 :     Oid         classid = PG_GETARG_OID(0);
    3561          12 :     Oid         objid = PG_GETARG_OID(1);
    3562          12 :     int32       objsubid = PG_GETARG_INT32(2);
    3563             :     char       *description;
    3564             :     ObjectAddress address;
    3565             : 
    3566             :     /* for "pinned" items in pg_depend, return null */
    3567          12 :     if (!OidIsValid(classid) && !OidIsValid(objid))
    3568           0 :         PG_RETURN_NULL();
    3569             : 
    3570          12 :     address.classId = classid;
    3571          12 :     address.objectId = objid;
    3572          12 :     address.objectSubId = objsubid;
    3573             : 
    3574          12 :     description = getObjectDescription(&address);
    3575          12 :     PG_RETURN_TEXT_P(cstring_to_text(description));
    3576             : }
    3577             : 
    3578             : /*
    3579             :  * SQL-level callable function to obtain object type + identity
    3580             :  */
    3581             : Datum
    3582         276 : pg_identify_object(PG_FUNCTION_ARGS)
    3583             : {
    3584         276 :     Oid         classid = PG_GETARG_OID(0);
    3585         276 :     Oid         objid = PG_GETARG_OID(1);
    3586         276 :     int32       objsubid = PG_GETARG_INT32(2);
    3587         276 :     Oid         schema_oid = InvalidOid;
    3588         276 :     const char *objname = NULL;
    3589             :     ObjectAddress address;
    3590             :     Datum       values[4];
    3591             :     bool        nulls[4];
    3592             :     TupleDesc   tupdesc;
    3593             :     HeapTuple   htup;
    3594             : 
    3595         276 :     address.classId = classid;
    3596         276 :     address.objectId = objid;
    3597         276 :     address.objectSubId = objsubid;
    3598             : 
    3599             :     /*
    3600             :      * Construct a tuple descriptor for the result row.  This must match this
    3601             :      * function's pg_proc entry!
    3602             :      */
    3603         276 :     tupdesc = CreateTemplateTupleDesc(4, false);
    3604         276 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
    3605             :                        TEXTOID, -1, 0);
    3606         276 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "schema",
    3607             :                        TEXTOID, -1, 0);
    3608         276 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "name",
    3609             :                        TEXTOID, -1, 0);
    3610         276 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "identity",
    3611             :                        TEXTOID, -1, 0);
    3612             : 
    3613         276 :     tupdesc = BlessTupleDesc(tupdesc);
    3614             : 
    3615         276 :     if (is_objectclass_supported(address.classId))
    3616             :     {
    3617             :         HeapTuple   objtup;
    3618         234 :         Relation    catalog = heap_open(address.classId, AccessShareLock);
    3619             : 
    3620         234 :         objtup = get_catalog_object_by_oid(catalog, address.objectId);
    3621         234 :         if (objtup != NULL)
    3622             :         {
    3623             :             bool        isnull;
    3624             :             AttrNumber  nspAttnum;
    3625             :             AttrNumber  nameAttnum;
    3626             : 
    3627         234 :             nspAttnum = get_object_attnum_namespace(address.classId);
    3628         234 :             if (nspAttnum != InvalidAttrNumber)
    3629             :             {
    3630         156 :                 schema_oid = heap_getattr(objtup, nspAttnum,
    3631             :                                           RelationGetDescr(catalog), &isnull);
    3632         156 :                 if (isnull)
    3633           0 :                     elog(ERROR, "invalid null namespace in object %u/%u/%d",
    3634             :                          address.classId, address.objectId, address.objectSubId);
    3635             :             }
    3636             : 
    3637             :             /*
    3638             :              * We only return the object name if it can be used (together with
    3639             :              * the schema name, if any) as a unique identifier.
    3640             :              */
    3641         234 :             if (get_object_namensp_unique(address.classId))
    3642             :             {
    3643         174 :                 nameAttnum = get_object_attnum_name(address.classId);
    3644         174 :                 if (nameAttnum != InvalidAttrNumber)
    3645             :                 {
    3646             :                     Datum       nameDatum;
    3647             : 
    3648         174 :                     nameDatum = heap_getattr(objtup, nameAttnum,
    3649             :                                              RelationGetDescr(catalog), &isnull);
    3650         174 :                     if (isnull)
    3651           0 :                         elog(ERROR, "invalid null name in object %u/%u/%d",
    3652             :                              address.classId, address.objectId, address.objectSubId);
    3653         174 :                     objname = quote_identifier(NameStr(*(DatumGetName(nameDatum))));
    3654             :                 }
    3655             :             }
    3656             :         }
    3657             : 
    3658         234 :         heap_close(catalog, AccessShareLock);
    3659             :     }
    3660             : 
    3661             :     /* object type */
    3662         276 :     values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
    3663         276 :     nulls[0] = false;
    3664             : 
    3665             :     /* schema name */
    3666         276 :     if (OidIsValid(schema_oid))
    3667             :     {
    3668         156 :         const char *schema = quote_identifier(get_namespace_name(schema_oid));
    3669             : 
    3670         156 :         values[1] = CStringGetTextDatum(schema);
    3671         156 :         nulls[1] = false;
    3672             :     }
    3673             :     else
    3674         120 :         nulls[1] = true;
    3675             : 
    3676             :     /* object name */
    3677         276 :     if (objname)
    3678             :     {
    3679         174 :         values[2] = CStringGetTextDatum(objname);
    3680         174 :         nulls[2] = false;
    3681             :     }
    3682             :     else
    3683         102 :         nulls[2] = true;
    3684             : 
    3685             :     /* object identity */
    3686         276 :     values[3] = CStringGetTextDatum(getObjectIdentity(&address));
    3687         276 :     nulls[3] = false;
    3688             : 
    3689         276 :     htup = heap_form_tuple(tupdesc, values, nulls);
    3690             : 
    3691         276 :     PG_RETURN_DATUM(HeapTupleGetDatum(htup));
    3692             : }
    3693             : 
    3694             : /*
    3695             :  * SQL-level callable function to obtain object type + identity
    3696             :  */
    3697             : Datum
    3698          46 : pg_identify_object_as_address(PG_FUNCTION_ARGS)
    3699             : {
    3700          46 :     Oid         classid = PG_GETARG_OID(0);
    3701          46 :     Oid         objid = PG_GETARG_OID(1);
    3702          46 :     int32       objsubid = PG_GETARG_INT32(2);
    3703             :     ObjectAddress address;
    3704             :     char       *identity;
    3705             :     List       *names;
    3706             :     List       *args;
    3707             :     Datum       values[3];
    3708             :     bool        nulls[3];
    3709             :     TupleDesc   tupdesc;
    3710             :     HeapTuple   htup;
    3711             : 
    3712          46 :     address.classId = classid;
    3713          46 :     address.objectId = objid;
    3714          46 :     address.objectSubId = objsubid;
    3715             : 
    3716             :     /*
    3717             :      * Construct a tuple descriptor for the result row.  This must match this
    3718             :      * function's pg_proc entry!
    3719             :      */
    3720          46 :     tupdesc = CreateTemplateTupleDesc(3, false);
    3721          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
    3722             :                        TEXTOID, -1, 0);
    3723          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "object_names",
    3724             :                        TEXTARRAYOID, -1, 0);
    3725          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "object_args",
    3726             :                        TEXTARRAYOID, -1, 0);
    3727             : 
    3728          46 :     tupdesc = BlessTupleDesc(tupdesc);
    3729             : 
    3730             :     /* object type */
    3731          46 :     values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
    3732          46 :     nulls[0] = false;
    3733             : 
    3734             :     /* object identity */
    3735          46 :     identity = getObjectIdentityParts(&address, &names, &args);
    3736          46 :     pfree(identity);
    3737             : 
    3738             :     /* object_names */
    3739          46 :     values[1] = PointerGetDatum(strlist_to_textarray(names));
    3740          46 :     nulls[1] = false;
    3741             : 
    3742             :     /* object_args */
    3743          46 :     if (args)
    3744          12 :         values[2] = PointerGetDatum(strlist_to_textarray(args));
    3745             :     else
    3746          34 :         values[2] = PointerGetDatum(construct_empty_array(TEXTOID));
    3747          46 :     nulls[2] = false;
    3748             : 
    3749          46 :     htup = heap_form_tuple(tupdesc, values, nulls);
    3750             : 
    3751          46 :     PG_RETURN_DATUM(HeapTupleGetDatum(htup));
    3752             : }
    3753             : 
    3754             : /*
    3755             :  * Return a palloc'ed string that describes the type of object that the
    3756             :  * passed address is for.
    3757             :  *
    3758             :  * Keep ObjectTypeMap in sync with this.
    3759             :  */
    3760             : char *
    3761         458 : getObjectTypeDescription(const ObjectAddress *object)
    3762             : {
    3763             :     StringInfoData buffer;
    3764             : 
    3765         458 :     initStringInfo(&buffer);
    3766             : 
    3767         458 :     switch (getObjectClass(object))
    3768             :     {
    3769             :         case OCLASS_CLASS:
    3770         103 :             getRelationTypeDescription(&buffer, object->objectId,
    3771             :                                        object->objectSubId);
    3772         103 :             break;
    3773             : 
    3774             :         case OCLASS_PROC:
    3775          20 :             getProcedureTypeDescription(&buffer, object->objectId);
    3776          20 :             break;
    3777             : 
    3778             :         case OCLASS_TYPE:
    3779          86 :             appendStringInfoString(&buffer, "type");
    3780          86 :             break;
    3781             : 
    3782             :         case OCLASS_CAST:
    3783           7 :             appendStringInfoString(&buffer, "cast");
    3784           7 :             break;
    3785             : 
    3786             :         case OCLASS_COLLATION:
    3787           7 :             appendStringInfoString(&buffer, "collation");
    3788           7 :             break;
    3789             : 
    3790             :         case OCLASS_CONSTRAINT:
    3791          18 :             getConstraintTypeDescription(&buffer, object->objectId);
    3792          18 :             break;
    3793             : 
    3794             :         case OCLASS_CONVERSION:
    3795           7 :             appendStringInfoString(&buffer, "conversion");
    3796           7 :             break;
    3797             : 
    3798             :         case OCLASS_DEFAULT:
    3799          13 :             appendStringInfoString(&buffer, "default value");
    3800          13 :             break;
    3801             : 
    3802             :         case OCLASS_LANGUAGE:
    3803           7 :             appendStringInfoString(&buffer, "language");
    3804           7 :             break;
    3805             : 
    3806             :         case OCLASS_LARGEOBJECT:
    3807           0 :             appendStringInfoString(&buffer, "large object");
    3808           0 :             break;
    3809             : 
    3810             :         case OCLASS_OPERATOR:
    3811           7 :             appendStringInfoString(&buffer, "operator");
    3812           7 :             break;
    3813             : 
    3814             :         case OCLASS_OPCLASS:
    3815           7 :             appendStringInfoString(&buffer, "operator class");
    3816           7 :             break;
    3817             : 
    3818             :         case OCLASS_OPFAMILY:
    3819           7 :             appendStringInfoString(&buffer, "operator family");
    3820           7 :             break;
    3821             : 
    3822             :         case OCLASS_AM:
    3823           7 :             appendStringInfoString(&buffer, "access method");
    3824           7 :             break;
    3825             : 
    3826             :         case OCLASS_AMOP:
    3827           7 :             appendStringInfoString(&buffer, "operator of access method");
    3828           7 :             break;
    3829             : 
    3830             :         case OCLASS_AMPROC:
    3831           7 :             appendStringInfoString(&buffer, "function of access method");
    3832           7 :             break;
    3833             : 
    3834             :         case OCLASS_REWRITE:
    3835           7 :             appendStringInfoString(&buffer, "rule");
    3836           7 :             break;
    3837             : 
    3838             :         case OCLASS_TRIGGER:
    3839          11 :             appendStringInfoString(&buffer, "trigger");
    3840          11 :             break;
    3841             : 
    3842             :         case OCLASS_SCHEMA:
    3843          15 :             appendStringInfoString(&buffer, "schema");
    3844          15 :             break;
    3845             : 
    3846             :         case OCLASS_STATISTIC_EXT:
    3847           7 :             appendStringInfoString(&buffer, "statistics object");
    3848           7 :             break;
    3849             : 
    3850             :         case OCLASS_TSPARSER:
    3851           7 :             appendStringInfoString(&buffer, "text search parser");
    3852           7 :             break;
    3853             : 
    3854             :         case OCLASS_TSDICT:
    3855           7 :             appendStringInfoString(&buffer, "text search dictionary");
    3856           7 :             break;
    3857             : 
    3858             :         case OCLASS_TSTEMPLATE:
    3859           7 :             appendStringInfoString(&buffer, "text search template");
    3860           7 :             break;
    3861             : 
    3862             :         case OCLASS_TSCONFIG:
    3863           7 :             appendStringInfoString(&buffer, "text search configuration");
    3864           7 :             break;
    3865             : 
    3866             :         case OCLASS_ROLE:
    3867           7 :             appendStringInfoString(&buffer, "role");
    3868           7 :             break;
    3869             : 
    3870             :         case OCLASS_DATABASE:
    3871           0 :             appendStringInfoString(&buffer, "database");
    3872           0 :             break;
    3873             : 
    3874             :         case OCLASS_TBLSPACE:
    3875           0 :             appendStringInfoString(&buffer, "tablespace");
    3876           0 :             break;
    3877             : 
    3878             :         case OCLASS_FDW:
    3879           7 :             appendStringInfoString(&buffer, "foreign-data wrapper");
    3880           7 :             break;
    3881             : 
    3882             :         case OCLASS_FOREIGN_SERVER:
    3883           7 :             appendStringInfoString(&buffer, "server");
    3884           7 :             break;
    3885             : 
    3886             :         case OCLASS_USER_MAPPING:
    3887           8 :             appendStringInfoString(&buffer, "user mapping");
    3888           8 :             break;
    3889             : 
    3890             :         case OCLASS_DEFACL:
    3891          15 :             appendStringInfoString(&buffer, "default acl");
    3892          15 :             break;
    3893             : 
    3894             :         case OCLASS_EXTENSION:
    3895           0 :             appendStringInfoString(&buffer, "extension");
    3896           0 :             break;
    3897             : 
    3898             :         case OCLASS_EVENT_TRIGGER:
    3899           0 :             appendStringInfoString(&buffer, "event trigger");
    3900           0 :             break;
    3901             : 
    3902             :         case OCLASS_POLICY:
    3903           8 :             appendStringInfoString(&buffer, "policy");
    3904           8 :             break;
    3905             : 
    3906             :         case OCLASS_PUBLICATION:
    3907           7 :             appendStringInfoString(&buffer, "publication");
    3908           7 :             break;
    3909             : 
    3910             :         case OCLASS_PUBLICATION_REL:
    3911           7 :             appendStringInfoString(&buffer, "publication relation");
    3912           7 :             break;
    3913             : 
    3914             :         case OCLASS_SUBSCRIPTION:
    3915           7 :             appendStringInfoString(&buffer, "subscription");
    3916           7 :             break;
    3917             : 
    3918             :         case OCLASS_TRANSFORM:
    3919           7 :             appendStringInfoString(&buffer, "transform");
    3920           7 :             break;
    3921             : 
    3922             :             /*
    3923             :              * There's intentionally no default: case here; we want the
    3924             :              * compiler to warn if a new OCLASS hasn't been handled above.
    3925             :              */
    3926             :     }
    3927             : 
    3928         458 :     return buffer.data;
    3929             : }
    3930             : 
    3931             : /*
    3932             :  * subroutine for getObjectTypeDescription: describe a relation type
    3933             :  */
    3934             : static void
    3935         103 : getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
    3936             : {
    3937             :     HeapTuple   relTup;
    3938             :     Form_pg_class relForm;
    3939             : 
    3940         103 :     relTup = SearchSysCache1(RELOID,
    3941             :                              ObjectIdGetDatum(relid));
    3942         103 :     if (!HeapTupleIsValid(relTup))
    3943           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    3944         103 :     relForm = (Form_pg_class) GETSTRUCT(relTup);
    3945             : 
    3946         103 :     switch (relForm->relkind)
    3947             :     {
    3948             :         case RELKIND_RELATION:
    3949             :         case RELKIND_PARTITIONED_TABLE:
    3950          40 :             appendStringInfoString(buffer, "table");
    3951          40 :             break;
    3952             :         case RELKIND_INDEX:
    3953          18 :             appendStringInfoString(buffer, "index");
    3954          18 :             break;
    3955             :         case RELKIND_SEQUENCE:
    3956           9 :             appendStringInfoString(buffer, "sequence");
    3957           9 :             break;
    3958             :         case RELKIND_TOASTVALUE:
    3959           8 :             appendStringInfoString(buffer, "toast table");
    3960           8 :             break;
    3961             :         case RELKIND_VIEW:
    3962           7 :             appendStringInfoString(buffer, "view");
    3963           7 :             break;
    3964             :         case RELKIND_MATVIEW:
    3965           7 :             appendStringInfoString(buffer, "materialized view");
    3966           7 :             break;
    3967             :         case RELKIND_COMPOSITE_TYPE:
    3968           0 :             appendStringInfoString(buffer, "composite type");
    3969           0 :             break;
    3970             :         case RELKIND_FOREIGN_TABLE:
    3971          14 :             appendStringInfoString(buffer, "foreign table");
    3972          14 :             break;
    3973             :         default:
    3974             :             /* shouldn't get here */
    3975           0 :             appendStringInfoString(buffer, "relation");
    3976           0 :             break;
    3977             :     }
    3978             : 
    3979         103 :     if (objectSubId != 0)
    3980          16 :         appendStringInfoString(buffer, " column");
    3981             : 
    3982         103 :     ReleaseSysCache(relTup);
    3983         103 : }
    3984             : 
    3985             : /*
    3986             :  * subroutine for getObjectTypeDescription: describe a constraint type
    3987             :  */
    3988             : static void
    3989          18 : getConstraintTypeDescription(StringInfo buffer, Oid constroid)
    3990             : {
    3991             :     Relation    constrRel;
    3992             :     HeapTuple   constrTup;
    3993             :     Form_pg_constraint constrForm;
    3994             : 
    3995          18 :     constrRel = heap_open(ConstraintRelationId, AccessShareLock);
    3996          18 :     constrTup = get_catalog_object_by_oid(constrRel, constroid);
    3997          18 :     if (!HeapTupleIsValid(constrTup))
    3998           0 :         elog(ERROR, "cache lookup failed for constraint %u", constroid);
    3999             : 
    4000          18 :     constrForm = (Form_pg_constraint) GETSTRUCT(constrTup);
    4001             : 
    4002          18 :     if (OidIsValid(constrForm->conrelid))
    4003          11 :         appendStringInfoString(buffer, "table constraint");
    4004           7 :     else if (OidIsValid(constrForm->contypid))
    4005           7 :         appendStringInfoString(buffer, "domain constraint");
    4006             :     else
    4007           0 :         elog(ERROR, "invalid constraint %u", HeapTupleGetOid(constrTup));
    4008             : 
    4009          18 :     heap_close(constrRel, AccessShareLock);
    4010          18 : }
    4011             : 
    4012             : /*
    4013             :  * subroutine for getObjectTypeDescription: describe a procedure type
    4014             :  */
    4015             : static void
    4016          20 : getProcedureTypeDescription(StringInfo buffer, Oid procid)
    4017             : {
    4018             :     HeapTuple   procTup;
    4019             :     Form_pg_proc procForm;
    4020             : 
    4021          20 :     procTup = SearchSysCache1(PROCOID,
    4022             :                               ObjectIdGetDatum(procid));
    4023          20 :     if (!HeapTupleIsValid(procTup))
    4024           0 :         elog(ERROR, "cache lookup failed for procedure %u", procid);
    4025          20 :     procForm = (Form_pg_proc) GETSTRUCT(procTup);
    4026             : 
    4027          20 :     if (procForm->proisagg)
    4028          10 :         appendStringInfoString(buffer, "aggregate");
    4029             :     else
    4030          10 :         appendStringInfoString(buffer, "function");
    4031             : 
    4032          20 :     ReleaseSysCache(procTup);
    4033          20 : }
    4034             : 
    4035             : /*
    4036             :  * Obtain a given object's identity, as a palloc'ed string.
    4037             :  *
    4038             :  * This is for machine consumption, so it's not translated.  All elements are
    4039             :  * schema-qualified when appropriate.
    4040             :  */
    4041             : char *
    4042         276 : getObjectIdentity(const ObjectAddress *object)
    4043             : {
    4044         276 :     return getObjectIdentityParts(object, NULL, NULL);
    4045             : }
    4046             : 
    4047             : /*
    4048             :  * As above, but more detailed.
    4049             :  *
    4050             :  * There are two sets of return values: the identity itself as a palloc'd
    4051             :  * string is returned.  objname and objargs, if not NULL, are output parameters
    4052             :  * that receive lists of C-strings that are useful to give back to
    4053             :  * get_object_address() to reconstruct the ObjectAddress.
    4054             :  */
    4055             : char *
    4056         478 : getObjectIdentityParts(const ObjectAddress *object,
    4057             :                        List **objname, List **objargs)
    4058             : {
    4059             :     StringInfoData buffer;
    4060             : 
    4061         478 :     initStringInfo(&buffer);
    4062             : 
    4063             :     /*
    4064             :      * Make sure that both objname and objargs were passed, or none was; and
    4065             :      * initialize them to empty lists.  For objname this is useless because it
    4066             :      * will be initialized in all cases inside the switch; but we do it anyway
    4067             :      * so that we can test below that no branch leaves it unset.
    4068             :      */
    4069         478 :     Assert(PointerIsValid(objname) == PointerIsValid(objargs));
    4070         478 :     if (objname)
    4071             :     {
    4072         190 :         *objname = NIL;
    4073         190 :         *objargs = NIL;
    4074             :     }
    4075             : 
    4076         478 :     switch (getObjectClass(object))
    4077             :     {
    4078             :         case OCLASS_CLASS:
    4079         116 :             getRelationIdentity(&buffer, object->objectId, objname);
    4080         116 :             if (object->objectSubId != 0)
    4081             :             {
    4082             :                 char       *attr;
    4083             : 
    4084          29 :                 attr = get_relid_attribute_name(object->objectId,
    4085          29 :                                                 object->objectSubId);
    4086          29 :                 appendStringInfo(&buffer, ".%s", quote_identifier(attr));
    4087          29 :                 if (objname)
    4088          11 :                     *objname = lappend(*objname, attr);
    4089             :             }
    4090         116 :             break;
    4091             : 
    4092             :         case OCLASS_PROC:
    4093          20 :             appendStringInfoString(&buffer,
    4094          20 :                                    format_procedure_qualified(object->objectId));
    4095          20 :             if (objname)
    4096           8 :                 format_procedure_parts(object->objectId, objname, objargs);
    4097          20 :             break;
    4098             : 
    4099             :         case OCLASS_TYPE:
    4100             :             {
    4101             :                 char       *typeout;
    4102             : 
    4103          93 :                 typeout = format_type_be_qualified(object->objectId);
    4104          93 :                 appendStringInfoString(&buffer, typeout);
    4105          93 :                 if (objname)
    4106          63 :                     *objname = list_make1(typeout);
    4107             :             }
    4108          93 :             break;
    4109             : 
    4110             :         case OCLASS_CAST:
    4111             :             {
    4112             :                 Relation    castRel;
    4113             :                 HeapTuple   tup;
    4114             :                 Form_pg_cast castForm;
    4115             : 
    4116           7 :                 castRel = heap_open(CastRelationId, AccessShareLock);
    4117             : 
    4118           7 :                 tup = get_catalog_object_by_oid(castRel, object->objectId);
    4119             : 
    4120           7 :                 if (!HeapTupleIsValid(tup))
    4121           0 :                     elog(ERROR, "could not find tuple for cast %u",
    4122             :                          object->objectId);
    4123             : 
    4124           7 :                 castForm = (Form_pg_cast) GETSTRUCT(tup);
    4125             : 
    4126           7 :                 appendStringInfo(&buffer, "(%s AS %s)",
    4127             :                                  format_type_be_qualified(castForm->castsource),
    4128             :                                  format_type_be_qualified(castForm->casttarget));
    4129             : 
    4130           7 :                 if (objname)
    4131             :                 {
    4132           1 :                     *objname = list_make1(format_type_be_qualified(castForm->castsource));
    4133           1 :                     *objargs = list_make1(format_type_be_qualified(castForm->casttarget));
    4134             :                 }
    4135             : 
    4136           7 :                 heap_close(castRel, AccessShareLock);
    4137           7 :                 break;
    4138             :             }
    4139             : 
    4140             :         case OCLASS_COLLATION:
    4141             :             {
    4142             :                 HeapTuple   collTup;
    4143             :                 Form_pg_collation coll;
    4144             :                 char       *schema;
    4145             : 
    4146           7 :                 collTup = SearchSysCache1(COLLOID,
    4147             :                                           ObjectIdGetDatum(object->objectId));
    4148           7 :                 if (!HeapTupleIsValid(collTup))
    4149           0 :                     elog(ERROR, "cache lookup failed for collation %u",
    4150             :                          object->objectId);
    4151           7 :                 coll = (Form_pg_collation) GETSTRUCT(collTup);
    4152           7 :                 schema = get_namespace_name_or_temp(coll->collnamespace);
    4153           7 :                 appendStringInfoString(&buffer,
    4154           7 :                                        quote_qualified_identifier(schema,
    4155           7 :                                                                   NameStr(coll->collname)));
    4156           7 :                 if (objname)
    4157           1 :                     *objname = list_make2(schema,
    4158             :                                           pstrdup(NameStr(coll->collname)));
    4159           7 :                 ReleaseSysCache(collTup);
    4160           7 :                 break;
    4161             :             }
    4162             : 
    4163             :         case OCLASS_CONSTRAINT:
    4164             :             {
    4165             :                 HeapTuple   conTup;
    4166             :                 Form_pg_constraint con;
    4167             : 
    4168          18 :                 conTup = SearchSysCache1(CONSTROID,
    4169             :                                          ObjectIdGetDatum(object->objectId));
    4170          18 :                 if (!HeapTupleIsValid(conTup))
    4171           0 :                     elog(ERROR, "cache lookup failed for constraint %u",
    4172             :                          object->objectId);
    4173          18 :                 con = (Form_pg_constraint) GETSTRUCT(conTup);
    4174             : 
    4175          18 :                 if (OidIsValid(con->conrelid))
    4176             :                 {
    4177          11 :                     appendStringInfo(&buffer, "%s on ",
    4178          11 :                                      quote_identifier(NameStr(con->conname)));
    4179          11 :                     getRelationIdentity(&buffer, con->conrelid, objname);
    4180          11 :                     if (objname)
    4181           5 :                         *objname = lappend(*objname, pstrdup(NameStr(con->conname)));
    4182             :                 }
    4183             :                 else
    4184             :                 {
    4185             :                     ObjectAddress domain;
    4186             : 
    4187           7 :                     Assert(OidIsValid(con->contypid));
    4188           7 :                     domain.classId = TypeRelationId;
    4189           7 :                     domain.objectId = con->contypid;
    4190           7 :                     domain.objectSubId = 0;
    4191             : 
    4192          14 :                     appendStringInfo(&buffer, "%s on %s",
    4193           7 :                                      quote_identifier(NameStr(con->conname)),
    4194             :                                      getObjectIdentityParts(&domain, objname, objargs));
    4195             : 
    4196           7 :                     if (objname)
    4197           1 :                         *objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
    4198             :                 }
    4199             : 
    4200          18 :                 ReleaseSysCache(conTup);
    4201          18 :                 break;
    4202             :             }
    4203             : 
    4204             :         case OCLASS_CONVERSION:
    4205             :             {
    4206             :                 HeapTuple   conTup;
    4207             :                 Form_pg_conversion conForm;
    4208             :                 char       *schema;
    4209             : 
    4210           7 :                 conTup = SearchSysCache1(CONVOID,
    4211             :                                          ObjectIdGetDatum(object->objectId));
    4212           7 :                 if (!HeapTupleIsValid(conTup))
    4213           0 :                     elog(ERROR, "cache lookup failed for conversion %u",
    4214             :                          object->objectId);
    4215           7 :                 conForm = (Form_pg_conversion) GETSTRUCT(conTup);
    4216           7 :                 schema = get_namespace_name_or_temp(conForm->connamespace);
    4217           7 :                 appendStringInfoString(&buffer,
    4218           7 :                                        quote_qualified_identifier(schema,
    4219           7 :                                                                   NameStr(conForm->conname)));
    4220           7 :                 if (objname)
    4221           1 :                     *objname = list_make2(schema,
    4222             :                                           pstrdup(NameStr(conForm->conname)));
    4223           7 :                 ReleaseSysCache(conTup);
    4224           7 :                 break;
    4225             :             }
    4226             : 
    4227             :         case OCLASS_DEFAULT:
    4228             :             {
    4229             :                 Relation    attrdefDesc;
    4230             :                 ScanKeyData skey[1];
    4231             :                 SysScanDesc adscan;
    4232             : 
    4233             :                 HeapTuple   tup;
    4234             :                 Form_pg_attrdef attrdef;
    4235             :                 ObjectAddress colobject;
    4236             : 
    4237          13 :                 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
    4238             : 
    4239          13 :                 ScanKeyInit(&skey[0],
    4240             :                             ObjectIdAttributeNumber,
    4241             :                             BTEqualStrategyNumber, F_OIDEQ,
    4242          13 :                             ObjectIdGetDatum(object->objectId));
    4243             : 
    4244          13 :                 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
    4245             :                                             true, NULL, 1, skey);
    4246             : 
    4247          13 :                 tup = systable_getnext(adscan);
    4248             : 
    4249          13 :                 if (!HeapTupleIsValid(tup))
    4250           0 :                     elog(ERROR, "could not find tuple for attrdef %u",
    4251             :                          object->objectId);
    4252             : 
    4253          13 :                 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
    4254             : 
    4255          13 :                 colobject.classId = RelationRelationId;
    4256          13 :                 colobject.objectId = attrdef->adrelid;
    4257          13 :                 colobject.objectSubId = attrdef->adnum;
    4258             : 
    4259          13 :                 appendStringInfo(&buffer, "for %s",
    4260             :                                  getObjectIdentityParts(&colobject,
    4261             :                                                         objname, objargs));
    4262             : 
    4263          13 :                 systable_endscan(adscan);
    4264          13 :                 heap_close(attrdefDesc, AccessShareLock);
    4265          13 :                 break;
    4266             :             }
    4267             : 
    4268             :         case OCLASS_LANGUAGE:
    4269             :             {
    4270             :                 HeapTuple   langTup;
    4271             :                 Form_pg_language langForm;
    4272             : 
    4273           7 :                 langTup = SearchSysCache1(LANGOID,
    4274             :                                           ObjectIdGetDatum(object->objectId));
    4275           7 :                 if (!HeapTupleIsValid(langTup))
    4276           0 :                     elog(ERROR, "cache lookup failed for language %u",
    4277             :                          object->objectId);
    4278           7 :                 langForm = (Form_pg_language) GETSTRUCT(langTup);
    4279           7 :                 appendStringInfoString(&buffer,
    4280           7 :                                        quote_identifier(NameStr(langForm->lanname)));
    4281           7 :                 if (objname)
    4282           1 :                     *objname = list_make1(pstrdup(NameStr(langForm->lanname)));
    4283           7 :                 ReleaseSysCache(langTup);
    4284           7 :                 break;
    4285             :             }
    4286             :         case OCLASS_LARGEOBJECT:
    4287           0 :             appendStringInfo(&buffer, "%u",
    4288             :                              object->objectId);
    4289           0 :             if (objname)
    4290           0 :                 *objname = list_make1(psprintf("%u", object->objectId));
    4291           0 :             break;
    4292             : 
    4293             :         case OCLASS_OPERATOR:
    4294           7 :             appendStringInfoString(&buffer,
    4295           7 :                                    format_operator_qualified(object->objectId));
    4296           7 :             if (objname)
    4297           1 :                 format_operator_parts(object->objectId, objname, objargs);
    4298           7 :             break;
    4299             : 
    4300             :         case OCLASS_OPCLASS:
    4301             :             {
    4302             :                 HeapTuple   opcTup;
    4303             :                 Form_pg_opclass opcForm;
    4304             :                 HeapTuple   amTup;
    4305             :                 Form_pg_am  amForm;
    4306             :                 char       *schema;
    4307             : 
    4308           7 :                 opcTup = SearchSysCache1(CLAOID,
    4309             :                                          ObjectIdGetDatum(object->objectId));
    4310           7 :                 if (!HeapTupleIsValid(opcTup))
    4311           0 :                     elog(ERROR, "cache lookup failed for opclass %u",
    4312             :                          object->objectId);
    4313           7 :                 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
    4314           7 :                 schema = get_namespace_name_or_temp(opcForm->opcnamespace);
    4315             : 
    4316           7 :                 amTup = SearchSysCache1(AMOID,
    4317             :                                         ObjectIdGetDatum(opcForm->opcmethod));
    4318           7 :                 if (!HeapTupleIsValid(amTup))
    4319           0 :                     elog(ERROR, "cache lookup failed for access method %u",
    4320             :                          opcForm->opcmethod);
    4321           7 :                 amForm = (Form_pg_am) GETSTRUCT(amTup);
    4322             : 
    4323          14 :                 appendStringInfo(&buffer, "%s USING %s",
    4324             :                                  quote_qualified_identifier(schema,
    4325           7 :                                                             NameStr(opcForm->opcname)),
    4326           7 :                                  quote_identifier(NameStr(amForm->amname)));
    4327           7 :                 if (objname)
    4328           1 :                     *objname = list_make3(pstrdup(NameStr(amForm->amname)),
    4329             :                                           schema,
    4330             :                                           pstrdup(NameStr(opcForm->opcname)));
    4331             : 
    4332           7 :                 ReleaseSysCache(amTup);
    4333           7 :                 ReleaseSysCache(opcTup);
    4334           7 :                 break;
    4335             :             }
    4336             : 
    4337             :         case OCLASS_OPFAMILY:
    4338           7 :             getOpFamilyIdentity(&buffer, object->objectId, objname);
    4339           7 :             break;
    4340             : 
    4341             :         case OCLASS_AM:
    4342             :             {
    4343             :                 char       *amname;
    4344             : 
    4345           7 :                 amname = get_am_name(object->objectId);
    4346           7 :                 if (!amname)
    4347           0 :                     elog(ERROR, "cache lookup failed for access method %u",
    4348             :                          object->objectId);
    4349           7 :                 appendStringInfoString(&buffer, quote_identifier(amname));
    4350           7 :                 if (objname)
    4351           1 :                     *objname = list_make1(amname);
    4352             :             }
    4353           7 :             break;
    4354             : 
    4355             :         case OCLASS_AMOP:
    4356             :             {
    4357             :                 Relation    amopDesc;
    4358             :                 HeapTuple   tup;
    4359             :                 ScanKeyData skey[1];
    4360             :                 SysScanDesc amscan;
    4361             :                 Form_pg_amop amopForm;
    4362             :                 StringInfoData opfam;
    4363             :                 char       *ltype;
    4364             :                 char       *rtype;
    4365             : 
    4366           7 :                 amopDesc = heap_open(AccessMethodOperatorRelationId,
    4367             :                                      AccessShareLock);
    4368             : 
    4369           7 :                 ScanKeyInit(&skey[0],
    4370             :                             ObjectIdAttributeNumber,
    4371             :                             BTEqualStrategyNumber, F_OIDEQ,
    4372           7 :                             ObjectIdGetDatum(object->objectId));
    4373             : 
    4374           7 :                 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
    4375             :                                             NULL, 1, skey);
    4376             : 
    4377           7 :                 tup = systable_getnext(amscan);
    4378             : 
    4379           7 :                 if (!HeapTupleIsValid(tup))
    4380           0 :                     elog(ERROR, "could not find tuple for amop entry %u",
    4381             :                          object->objectId);
    4382             : 
    4383           7 :                 amopForm = (Form_pg_amop) GETSTRUCT(tup);
    4384             : 
    4385           7 :                 initStringInfo(&opfam);
    4386           7 :                 getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname);
    4387             : 
    4388           7 :                 ltype = format_type_be_qualified(amopForm->amoplefttype);
    4389           7 :                 rtype = format_type_be_qualified(amopForm->amoprighttype);
    4390             : 
    4391           7 :                 if (objname)
    4392             :                 {
    4393           1 :                     *objname = lappend(*objname,
    4394           1 :                                        psprintf("%d", amopForm->amopstrategy));
    4395           1 :                     *objargs = list_make2(ltype, rtype);
    4396             :                 }
    4397             : 
    4398          14 :                 appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
    4399           7 :                                  amopForm->amopstrategy,
    4400             :                                  ltype, rtype, opfam.data);
    4401             : 
    4402           7 :                 pfree(opfam.data);
    4403             : 
    4404           7 :                 systable_endscan(amscan);
    4405           7 :                 heap_close(amopDesc, AccessShareLock);
    4406           7 :                 break;
    4407             :             }
    4408             : 
    4409             :         case OCLASS_AMPROC:
    4410             :             {
    4411             :                 Relation    amprocDesc;
    4412             :                 ScanKeyData skey[1];
    4413             :                 SysScanDesc amscan;
    4414             :                 HeapTuple   tup;
    4415             :                 Form_pg_amproc amprocForm;
    4416             :                 StringInfoData opfam;
    4417             :                 char       *ltype;
    4418             :                 char       *rtype;
    4419             : 
    4420           7 :                 amprocDesc = heap_open(AccessMethodProcedureRelationId,
    4421             :                                        AccessShareLock);
    4422             : 
    4423           7 :                 ScanKeyInit(&skey[0],
    4424             :                             ObjectIdAttributeNumber,
    4425             :                             BTEqualStrategyNumber, F_OIDEQ,
    4426           7 :                             ObjectIdGetDatum(object->objectId));
    4427             : 
    4428           7 :                 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
    4429             :                                             NULL, 1, skey);
    4430             : 
    4431           7 :                 tup = systable_getnext(amscan);
    4432             : 
    4433           7 :                 if (!HeapTupleIsValid(tup))
    4434           0 :                     elog(ERROR, "could not find tuple for amproc entry %u",
    4435             :                          object->objectId);
    4436             : 
    4437           7 :                 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
    4438             : 
    4439           7 :                 initStringInfo(&opfam);
    4440           7 :                 getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname);
    4441             : 
    4442           7 :                 ltype = format_type_be_qualified(amprocForm->amproclefttype);
    4443           7 :                 rtype = format_type_be_qualified(amprocForm->amprocrighttype);
    4444             : 
    4445           7 :                 if (objname)
    4446             :                 {
    4447           1 :                     *objname = lappend(*objname,
    4448           1 :                                        psprintf("%d", amprocForm->amprocnum));
    4449           1 :                     *objargs = list_make2(ltype, rtype);
    4450             :                 }
    4451             : 
    4452          14 :                 appendStringInfo(&buffer, "function %d (%s, %s) of %s",
    4453           7 :                                  amprocForm->amprocnum,
    4454             :                                  ltype, rtype, opfam.data);
    4455             : 
    4456           7 :                 pfree(opfam.data);
    4457             : 
    4458           7 :                 systable_endscan(amscan);
    4459           7 :                 heap_close(amprocDesc, AccessShareLock);
    4460           7 :                 break;
    4461             :             }
    4462             : 
    4463             :         case OCLASS_REWRITE:
    4464             :             {
    4465             :                 Relation    ruleDesc;
    4466             :                 HeapTuple   tup;
    4467             :                 Form_pg_rewrite rule;
    4468             : 
    4469           7 :                 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
    4470             : 
    4471           7 :                 tup = get_catalog_object_by_oid(ruleDesc, object->objectId);
    4472             : 
    4473           7 :                 if (!HeapTupleIsValid(tup))
    4474           0 :                     elog(ERROR, "could not find tuple for rule %u",
    4475             :                          object->objectId);
    4476             : 
    4477           7 :                 rule = (Form_pg_rewrite) GETSTRUCT(tup);
    4478             : 
    4479           7 :                 appendStringInfo(&buffer, "%s on ",
    4480           7 :                                  quote_identifier(NameStr(rule->rulename)));
    4481           7 :                 getRelationIdentity(&buffer, rule->ev_class, objname);
    4482           7 :                 if (objname)
    4483           1 :                     *objname = lappend(*objname, pstrdup(NameStr(rule->rulename)));
    4484             : 
    4485           7 :                 heap_close(ruleDesc, AccessShareLock);
    4486           7 :                 break;
    4487             :             }
    4488             : 
    4489             :         case OCLASS_TRIGGER:
    4490             :             {
    4491             :                 Relation    trigDesc;
    4492             :                 HeapTuple   tup;
    4493             :                 Form_pg_trigger trig;
    4494             : 
    4495          11 :                 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
    4496             : 
    4497          11 :                 tup = get_catalog_object_by_oid(trigDesc, object->objectId);
    4498             : 
    4499          11 :                 if (!HeapTupleIsValid(tup))
    4500           0 :                     elog(ERROR, "could not find tuple for trigger %u",
    4501             :                          object->objectId);
    4502             : 
    4503          11 :                 trig = (Form_pg_trigger) GETSTRUCT(tup);
    4504             : 
    4505          11 :                 appendStringInfo(&buffer, "%s on ",
    4506          11 :                                  quote_identifier(NameStr(trig->tgname)));
    4507          11 :                 getRelationIdentity(&buffer, trig->tgrelid, objname);
    4508          11 :                 if (objname)
    4509           5 :                     *objname = lappend(*objname, pstrdup(NameStr(trig->tgname)));
    4510             : 
    4511          11 :                 heap_close(trigDesc, AccessShareLock);
    4512          11 :                 break;
    4513             :             }
    4514             : 
    4515             :         case OCLASS_SCHEMA:
    4516             :             {
    4517             :                 char       *nspname;
    4518             : 
    4519          15 :                 nspname = get_namespace_name_or_temp(object->objectId);
    4520          15 :                 if (!nspname)
    4521           0 :                     elog(ERROR, "cache lookup failed for namespace %u",
    4522             :                          object->objectId);
    4523          15 :                 appendStringInfoString(&buffer,
    4524             :                                        quote_identifier(nspname));
    4525          15 :                 if (objname)
    4526           9 :                     *objname = list_make1(nspname);
    4527          15 :                 break;
    4528             :             }
    4529             : 
    4530             :         case OCLASS_STATISTIC_EXT:
    4531             :             {
    4532             :                 HeapTuple   tup;
    4533             :                 Form_pg_statistic_ext formStatistic;
    4534             :                 char       *schema;
    4535             : 
    4536           7 :                 tup = SearchSysCache1(STATEXTOID,
    4537             :                                       ObjectIdGetDatum(object->objectId));
    4538           7 :                 if (!HeapTupleIsValid(tup))
    4539           0 :                     elog(ERROR, "cache lookup failed for statistics object %u",
    4540             :                          object->objectId);
    4541           7 :                 formStatistic = (Form_pg_statistic_ext) GETSTRUCT(tup);
    4542           7 :                 schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
    4543           7 :                 appendStringInfoString(&buffer,
    4544           7 :                                        quote_qualified_identifier(schema,
    4545           7 :                                                                   NameStr(formStatistic->stxname)));
    4546           7 :                 if (objname)
    4547           1 :                     *objname = list_make2(schema,
    4548             :                                           pstrdup(NameStr(formStatistic->stxname)));
    4549           7 :                 ReleaseSysCache(tup);
    4550             :             }
    4551           7 :             break;
    4552             : 
    4553             :         case OCLASS_TSPARSER:
    4554             :             {
    4555             :                 HeapTuple   tup;
    4556             :                 Form_pg_ts_parser formParser;
    4557             :                 char       *schema;
    4558             : 
    4559           7 :                 tup = SearchSysCache1(TSPARSEROID,
    4560             :                                       ObjectIdGetDatum(object->objectId));
    4561           7 :                 if (!HeapTupleIsValid(tup))
    4562           0 :                     elog(ERROR, "cache lookup failed for text search parser %u",
    4563             :                          object->objectId);
    4564           7 :                 formParser = (Form_pg_ts_parser) GETSTRUCT(tup);
    4565           7 :                 schema = get_namespace_name_or_temp(formParser->prsnamespace);
    4566           7 :                 appendStringInfoString(&buffer,
    4567           7 :                                        quote_qualified_identifier(schema,
    4568           7 :                                                                   NameStr(formParser->prsname)));
    4569           7 :                 if (objname)
    4570           1 :                     *objname = list_make2(schema,
    4571             :                                           pstrdup(NameStr(formParser->prsname)));
    4572           7 :                 ReleaseSysCache(tup);
    4573           7 :                 break;
    4574             :             }
    4575             : 
    4576             :         case OCLASS_TSDICT:
    4577             :             {
    4578             :                 HeapTuple   tup;
    4579             :                 Form_pg_ts_dict formDict;
    4580             :                 char       *schema;
    4581             : 
    4582           7 :                 tup = SearchSysCache1(TSDICTOID,
    4583             :                                       ObjectIdGetDatum(object->objectId));
    4584           7 :                 if (!HeapTupleIsValid(tup))
    4585           0 :                     elog(ERROR, "cache lookup failed for text search dictionary %u",
    4586             :                          object->objectId);
    4587           7 :                 formDict = (Form_pg_ts_dict) GETSTRUCT(tup);
    4588           7 :                 schema = get_namespace_name_or_temp(formDict->dictnamespace);
    4589           7 :                 appendStringInfoString(&buffer,
    4590           7 :                                        quote_qualified_identifier(schema,
    4591           7 :                                                                   NameStr(formDict->dictname)));
    4592           7 :                 if (objname)
    4593           1 :                     *objname = list_make2(schema,
    4594             :                                           pstrdup(NameStr(formDict->dictname)));
    4595           7 :                 ReleaseSysCache(tup);
    4596           7 :                 break;
    4597             :             }
    4598             : 
    4599             :         case OCLASS_TSTEMPLATE:
    4600             :             {
    4601             :                 HeapTuple   tup;
    4602             :                 Form_pg_ts_template formTmpl;
    4603             :                 char       *schema;
    4604             : 
    4605           7 :                 tup = SearchSysCache1(TSTEMPLATEOID,
    4606             :                                       ObjectIdGetDatum(object->objectId));
    4607           7 :                 if (!HeapTupleIsValid(tup))
    4608           0 :                     elog(ERROR, "cache lookup failed for text search template %u",
    4609             :                          object->objectId);
    4610           7 :                 formTmpl = (Form_pg_ts_template) GETSTRUCT(tup);
    4611           7 :                 schema = get_namespace_name_or_temp(formTmpl->tmplnamespace);
    4612           7 :                 appendStringInfoString(&buffer,
    4613           7 :                                        quote_qualified_identifier(schema,
    4614           7 :                                                                   NameStr(formTmpl->tmplname)));
    4615           7 :                 if (objname)
    4616           1 :                     *objname = list_make2(schema,
    4617             :                                           pstrdup(NameStr(formTmpl->tmplname)));
    4618           7 :                 ReleaseSysCache(tup);
    4619           7 :                 break;
    4620             :             }
    4621             : 
    4622             :         case OCLASS_TSCONFIG:
    4623             :             {
    4624             :                 HeapTuple   tup;
    4625             :                 Form_pg_ts_config formCfg;
    4626             :                 char       *schema;
    4627             : 
    4628           7 :                 tup = SearchSysCache1(TSCONFIGOID,
    4629             :                                       ObjectIdGetDatum(object->objectId));
    4630           7 :                 if (!HeapTupleIsValid(tup))
    4631           0 :                     elog(ERROR, "cache lookup failed for text search configuration %u",
    4632             :                          object->objectId);
    4633           7 :                 formCfg = (Form_pg_ts_config) GETSTRUCT(tup);
    4634           7 :                 schema = get_namespace_name_or_temp(formCfg->cfgnamespace);
    4635           7 :                 appendStringInfoString(&buffer,
    4636           7 :                                        quote_qualified_identifier(schema,
    4637           7 :                                                                   NameStr(formCfg->cfgname)));
    4638           7 :                 if (objname)
    4639           1 :                     *objname = list_make2(schema,
    4640             :                                           pstrdup(NameStr(formCfg->cfgname)));
    4641           7 :                 ReleaseSysCache(tup);
    4642           7 :                 break;
    4643             :             }
    4644             : 
    4645             :         case OCLASS_ROLE:
    4646             :             {
    4647             :                 char       *username;
    4648             : 
    4649           7 :                 username = GetUserNameFromId(object->objectId, false);
    4650           7 :                 if (objname)
    4651           1 :                     *objname = list_make1(username);
    4652           7 :                 appendStringInfoString(&buffer,
    4653             :                                        quote_identifier(username));
    4654           7 :                 break;
    4655             :             }
    4656             : 
    4657             :         case OCLASS_DATABASE:
    4658             :             {
    4659             :                 char       *datname;
    4660             : 
    4661           0 :                 datname = get_database_name(object->objectId);
    4662           0 :                 if (!datname)
    4663           0 :                     elog(ERROR, "cache lookup failed for database %u",
    4664             :                          object->objectId);
    4665           0 :                 if (objname)
    4666           0 :                     *objname = list_make1(datname);
    4667           0 :                 appendStringInfoString(&buffer,
    4668             :                                        quote_identifier(datname));
    4669           0 :                 break;
    4670             :             }
    4671             : 
    4672             :         case OCLASS_TBLSPACE:
    4673             :             {
    4674             :                 char       *tblspace;
    4675             : 
    4676           0 :                 tblspace = get_tablespace_name(object->objectId);
    4677           0 :                 if (!tblspace)
    4678           0 :                     elog(ERROR, "cache lookup failed for tablespace %u",
    4679             :                          object->objectId);
    4680           0 :                 if (objname)
    4681           0 :                     *objname = list_make1(tblspace);
    4682           0 :                 appendStringInfoString(&buffer,
    4683             :                                        quote_identifier(tblspace));
    4684           0 :                 break;
    4685             :             }
    4686             : 
    4687             :         case OCLASS_FDW:
    4688             :             {
    4689             :                 ForeignDataWrapper *fdw;
    4690             : 
    4691           7 :                 fdw = GetForeignDataWrapper(object->objectId);
    4692           7 :                 appendStringInfoString(&buffer, quote_identifier(fdw->fdwname));
    4693           7 :                 if (objname)
    4694           1 :                     *objname = list_make1(pstrdup(fdw->fdwname));
    4695           7 :                 break;
    4696             :             }
    4697             : 
    4698             :         case OCLASS_FOREIGN_SERVER:
    4699             :             {
    4700             :                 ForeignServer *srv;
    4701             : 
    4702           7 :                 srv = GetForeignServer(object->objectId);
    4703           7 :                 appendStringInfoString(&buffer,
    4704           7 :                                        quote_identifier(srv->servername));
    4705           7 :                 if (objname)
    4706           1 :                     *objname = list_make1(pstrdup(srv->servername));
    4707           7 :                 break;
    4708             :             }
    4709             : 
    4710             :         case OCLASS_USER_MAPPING:
    4711             :             {
    4712             :                 HeapTuple   tup;
    4713             :                 Oid         useid;
    4714             :                 Form_pg_user_mapping umform;
    4715             :                 ForeignServer *srv;
    4716             :                 const char *usename;
    4717             : 
    4718           8 :                 tup = SearchSysCache1(USERMAPPINGOID,
    4719             :                                       ObjectIdGetDatum(object->objectId));
    4720           8 :                 if (!HeapTupleIsValid(tup))
    4721           0 :                     elog(ERROR, "cache lookup failed for user mapping %u",
    4722             :                          object->objectId);
    4723           8 :                 umform = (Form_pg_user_mapping) GETSTRUCT(tup);
    4724           8 :                 useid = umform->umuser;
    4725           8 :                 srv = GetForeignServer(umform->umserver);
    4726             : 
    4727           8 :                 ReleaseSysCache(tup);
    4728             : 
    4729           8 :                 if (OidIsValid(useid))
    4730           8 :                     usename = GetUserNameFromId(useid, false);
    4731             :                 else
    4732           0 :                     usename = "public";
    4733             : 
    4734           8 :                 if (objname)
    4735             :                 {
    4736           2 :                     *objname = list_make1(pstrdup(usename));
    4737           2 :                     *objargs = list_make1(pstrdup(srv->servername));
    4738             :                 }
    4739             : 
    4740           8 :                 appendStringInfo(&buffer, "%s on server %s",
    4741             :                                  quote_identifier(usename),
    4742             :                                  srv->servername);
    4743           8 :                 break;
    4744             :             }
    4745             : 
    4746             :         case OCLASS_DEFACL:
    4747             :             {
    4748             :                 Relation    defaclrel;
    4749             :                 ScanKeyData skey[1];
    4750             :                 SysScanDesc rcscan;
    4751             :                 HeapTuple   tup;
    4752             :                 Form_pg_default_acl defacl;
    4753             :                 char       *schema;
    4754             :                 char       *username;
    4755             : 
    4756          15 :                 defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
    4757             : 
    4758          15 :                 ScanKeyInit(&skey[0],
    4759             :                             ObjectIdAttributeNumber,
    4760             :                             BTEqualStrategyNumber, F_OIDEQ,
    4761          15 :                             ObjectIdGetDatum(object->objectId));
    4762             : 
    4763          15 :                 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
    4764             :                                             true, NULL, 1, skey);
    4765             : 
    4766          15 :                 tup = systable_getnext(rcscan);
    4767             : 
    4768          15 :                 if (!HeapTupleIsValid(tup))
    4769           0 :                     elog(ERROR, "could not find tuple for default ACL %u",
    4770             :                          object->objectId);
    4771             : 
    4772          15 :                 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
    4773             : 
    4774          15 :                 username = GetUserNameFromId(defacl->defaclrole, false);
    4775          15 :                 appendStringInfo(&buffer,
    4776             :                                  "for role %s",
    4777             :                                  quote_identifier(username));
    4778             : 
    4779          15 :                 if (OidIsValid(defacl->defaclnamespace))
    4780             :                 {
    4781           7 :                     schema = get_namespace_name_or_temp(defacl->defaclnamespace);
    4782           7 :                     appendStringInfo(&buffer,
    4783             :                                      " in schema %s",
    4784             :                                      quote_identifier(schema));
    4785             :                 }
    4786             :                 else
    4787           8 :                     schema = NULL;
    4788             : 
    4789          15 :                 switch (defacl->defaclobjtype)
    4790             :                 {
    4791             :                     case DEFACLOBJ_RELATION:
    4792          15 :                         appendStringInfoString(&buffer,
    4793             :                                                " on tables");
    4794          15 :                         break;
    4795             :                     case DEFACLOBJ_SEQUENCE:
    4796           0 :                         appendStringInfoString(&buffer,
    4797             :                                                " on sequences");
    4798           0 :                         break;
    4799             :                     case DEFACLOBJ_FUNCTION:
    4800           0 :                         appendStringInfoString(&buffer,
    4801             :                                                " on functions");
    4802           0 :                         break;
    4803             :                     case DEFACLOBJ_TYPE:
    4804           0 :                         appendStringInfoString(&buffer,
    4805             :                                                " on types");
    4806           0 :                         break;
    4807             :                     case DEFACLOBJ_NAMESPACE:
    4808           0 :                         appendStringInfoString(&buffer,
    4809             :                                                " on schemas");
    4810           0 :                         break;
    4811             :                 }
    4812             : 
    4813          15 :                 if (objname)
    4814             :                 {
    4815           3 :                     *objname = list_make1(username);
    4816           3 :                     if (schema)
    4817           1 :                         *objname = lappend(*objname, schema);
    4818           3 :                     *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
    4819             :                 }
    4820             : 
    4821          15 :                 systable_endscan(rcscan);
    4822          15 :                 heap_close(defaclrel, AccessShareLock);
    4823          15 :                 break;
    4824             :             }
    4825             : 
    4826             :         case OCLASS_EXTENSION:
    4827             :             {
    4828             :                 char       *extname;
    4829             : 
    4830           0 :                 extname = get_extension_name(object->objectId);
    4831           0 :                 if (!extname)
    4832           0 :                     elog(ERROR, "cache lookup failed for extension %u",
    4833             :                          object->objectId);
    4834           0 :                 appendStringInfoString(&buffer, quote_identifier(extname));
    4835           0 :                 if (objname)
    4836           0 :                     *objname = list_make1(extname);
    4837           0 :                 break;
    4838             :             }
    4839             : 
    4840             :         case OCLASS_EVENT_TRIGGER:
    4841             :             {
    4842             :                 HeapTuple   tup;
    4843             :                 Form_pg_event_trigger trigForm;
    4844             : 
    4845             :                 /* no objname support here */
    4846           0 :                 if (objname)
    4847           0 :                     *objname = NIL;
    4848             : 
    4849           0 :                 tup = SearchSysCache1(EVENTTRIGGEROID,
    4850             :                                       ObjectIdGetDatum(object->objectId));
    4851           0 :                 if (!HeapTupleIsValid(tup))
    4852           0 :                     elog(ERROR, "cache lookup failed for event trigger %u",
    4853             :                          object->objectId);
    4854           0 :                 trigForm = (Form_pg_event_trigger) GETSTRUCT(tup);
    4855           0 :                 appendStringInfoString(&buffer,
    4856           0 :                                        quote_identifier(NameStr(trigForm->evtname)));
    4857           0 :                 ReleaseSysCache(tup);
    4858           0 :                 break;
    4859             :             }
    4860             : 
    4861             :         case OCLASS_POLICY:
    4862             :             {
    4863             :                 Relation    polDesc;
    4864             :                 HeapTuple   tup;
    4865             :                 Form_pg_policy policy;
    4866             : 
    4867           8 :                 polDesc = heap_open(PolicyRelationId, AccessShareLock);
    4868             : 
    4869           8 :                 tup = get_catalog_object_by_oid(polDesc, object->objectId);
    4870             : 
    4871           8 :                 if (!HeapTupleIsValid(tup))
    4872           0 :                     elog(ERROR, "could not find tuple for policy %u",
    4873             :                          object->objectId);
    4874             : 
    4875           8 :                 policy = (Form_pg_policy) GETSTRUCT(tup);
    4876             : 
    4877           8 :                 appendStringInfo(&buffer, "%s on ",
    4878           8 :                                  quote_identifier(NameStr(policy->polname)));
    4879           8 :                 getRelationIdentity(&buffer, policy->polrelid, objname);
    4880           8 :                 if (objname)
    4881           2 :                     *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
    4882             : 
    4883           8 :                 heap_close(polDesc, AccessShareLock);
    4884           8 :                 break;
    4885             :             }
    4886             : 
    4887             :         case OCLASS_PUBLICATION:
    4888             :             {
    4889             :                 char       *pubname;
    4890             : 
    4891           7 :                 pubname = get_publication_name(object->objectId);
    4892           7 :                 appendStringInfoString(&buffer,
    4893             :                                        quote_identifier(pubname));
    4894           7 :                 if (objname)
    4895           1 :                     *objname = list_make1(pubname);
    4896           7 :                 break;
    4897             :             }
    4898             : 
    4899             :         case OCLASS_PUBLICATION_REL:
    4900             :             {
    4901             :                 HeapTuple   tup;
    4902             :                 char       *pubname;
    4903             :                 Form_pg_publication_rel prform;
    4904             : 
    4905           7 :                 tup = SearchSysCache1(PUBLICATIONREL,
    4906             :                                       ObjectIdGetDatum(object->objectId));
    4907           7 :                 if (!HeapTupleIsValid(tup))
    4908           0 :                     elog(ERROR, "cache lookup failed for publication table %u",
    4909             :                          object->objectId);
    4910             : 
    4911           7 :                 prform = (Form_pg_publication_rel) GETSTRUCT(tup);
    4912           7 :                 pubname = get_publication_name(prform->prpubid);
    4913             : 
    4914           7 :                 appendStringInfo(&buffer, _("%s in publication %s"),
    4915             :                                  get_rel_name(prform->prrelid), pubname);
    4916             : 
    4917           7 :                 if (objname)
    4918             :                 {
    4919           1 :                     getRelationIdentity(&buffer, prform->prrelid, objname);
    4920           1 :                     *objargs = list_make1(pubname);
    4921             :                 }
    4922             : 
    4923           7 :                 ReleaseSysCache(tup);
    4924           7 :                 break;
    4925             :             }
    4926             : 
    4927             :         case OCLASS_SUBSCRIPTION:
    4928             :             {
    4929             :                 char       *subname;
    4930             : 
    4931           7 :                 subname = get_subscription_name(object->objectId);
    4932           7 :                 appendStringInfoString(&buffer,
    4933             :                                        quote_identifier(subname));
    4934           7 :                 if (objname)
    4935           1 :                     *objname = list_make1(subname);
    4936           7 :                 break;
    4937             :             }
    4938             : 
    4939             :         case OCLASS_TRANSFORM:
    4940             :             {
    4941             :                 Relation    transformDesc;
    4942             :                 HeapTuple   tup;
    4943             :                 Form_pg_transform transform;
    4944             :                 char       *transformLang;
    4945             :                 char       *transformType;
    4946             : 
    4947           7 :                 transformDesc = heap_open(TransformRelationId, AccessShareLock);
    4948             : 
    4949           7 :                 tup = get_catalog_object_by_oid(transformDesc, object->objectId);
    4950             : 
    4951           7 :                 if (!HeapTupleIsValid(tup))
    4952           0 :                     elog(ERROR, "could not find tuple for transform %u",
    4953             :                          object->objectId);
    4954             : 
    4955           7 :                 transform = (Form_pg_transform) GETSTRUCT(tup);
    4956             : 
    4957           7 :                 transformType = format_type_be_qualified(transform->trftype);
    4958           7 :                 transformLang = get_language_name(transform->trflang, false);
    4959             : 
    4960           7 :                 appendStringInfo(&buffer, "for %s on language %s",
    4961             :                                  transformType,
    4962             :                                  transformLang);
    4963           7 :                 if (objname)
    4964             :                 {
    4965           1 :                     *objname = list_make1(transformType);
    4966           1 :                     *objargs = list_make1(pstrdup(transformLang));
    4967             :                 }
    4968             : 
    4969           7 :                 heap_close(transformDesc, AccessShareLock);
    4970             :             }
    4971           7 :             break;
    4972             : 
    4973             :             /*
    4974             :              * There's intentionally no default: case here; we want the
    4975             :              * compiler to warn if a new OCLASS hasn't been handled above.
    4976             :              */
    4977             :     }
    4978             : 
    4979             :     /*
    4980             :      * If a get_object_address representation was requested, make sure we are
    4981             :      * providing one.  We don't check objargs, because many of the cases above
    4982             :      * leave it as NIL.
    4983             :      */
    4984         478 :     if (objname && *objname == NIL)
    4985           0 :         elog(ERROR, "requested object address for unsupported object class %d: text result \"%s\"",
    4986             :              (int) getObjectClass(object), buffer.data);
    4987             : 
    4988         478 :     return buffer.data;
    4989             : }
    4990             : 
    4991             : static void
    4992          21 : getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object)
    4993             : {
    4994             :     HeapTuple   opfTup;
    4995             :     Form_pg_opfamily opfForm;
    4996             :     HeapTuple   amTup;
    4997             :     Form_pg_am  amForm;
    4998             :     char       *schema;
    4999             : 
    5000          21 :     opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
    5001          21 :     if (!HeapTupleIsValid(opfTup))
    5002           0 :         elog(ERROR, "cache lookup failed for opfamily %u", opfid);
    5003          21 :     opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
    5004             : 
    5005          21 :     amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
    5006          21 :     if (!HeapTupleIsValid(amTup))
    5007           0 :         elog(ERROR, "cache lookup failed for access method %u",
    5008             :              opfForm->opfmethod);
    5009          21 :     amForm = (Form_pg_am) GETSTRUCT(amTup);
    5010             : 
    5011          21 :     schema = get_namespace_name_or_temp(opfForm->opfnamespace);
    5012          21 :     appendStringInfo(buffer, "%s USING %s",
    5013             :                      quote_qualified_identifier(schema,
    5014          21 :                                                 NameStr(opfForm->opfname)),
    5015          21 :                      NameStr(amForm->amname));
    5016             : 
    5017          21 :     if (object)
    5018           3 :         *object = list_make3(pstrdup(NameStr(amForm->amname)),
    5019             :                              pstrdup(schema),
    5020             :                              pstrdup(NameStr(opfForm->opfname)));
    5021             : 
    5022          21 :     ReleaseSysCache(amTup);
    5023          21 :     ReleaseSysCache(opfTup);
    5024          21 : }
    5025             : 
    5026             : /*
    5027             :  * Append the relation identity (quoted qualified name) to the given
    5028             :  * StringInfo.
    5029             :  */
    5030             : static void
    5031         154 : getRelationIdentity(StringInfo buffer, Oid relid, List **object)
    5032             : {
    5033             :     HeapTuple   relTup;
    5034             :     Form_pg_class relForm;
    5035             :     char       *schema;
    5036             : 
    5037         154 :     relTup = SearchSysCache1(RELOID,
    5038             :                              ObjectIdGetDatum(relid));
    5039         154 :     if (!HeapTupleIsValid(relTup))
    5040           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    5041         154 :     relForm = (Form_pg_class) GETSTRUCT(relTup);
    5042             : 
    5043         154 :     schema = get_namespace_name_or_temp(relForm->relnamespace);
    5044         154 :     appendStringInfoString(buffer,
    5045         154 :                            quote_qualified_identifier(schema,
    5046         154 :                                                       NameStr(relForm->relname)));
    5047         154 :     if (object)
    5048          76 :         *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
    5049             : 
    5050         154 :     ReleaseSysCache(relTup);
    5051         154 : }
    5052             : 
    5053             : /*
    5054             :  * Auxiliary function to return a TEXT array out of a list of C-strings.
    5055             :  */
    5056             : ArrayType *
    5057         237 : strlist_to_textarray(List *list)
    5058             : {
    5059             :     ArrayType  *arr;
    5060             :     Datum      *datums;
    5061         237 :     int         j = 0;
    5062             :     ListCell   *cell;
    5063             :     MemoryContext memcxt;
    5064             :     MemoryContext oldcxt;
    5065             : 
    5066         237 :     memcxt = AllocSetContextCreate(CurrentMemoryContext,
    5067             :                                    "strlist to array",
    5068             :                                    ALLOCSET_DEFAULT_SIZES);
    5069         237 :     oldcxt = MemoryContextSwitchTo(memcxt);
    5070             : 
    5071         237 :     datums = palloc(sizeof(text *) * list_length(list));
    5072         613 :     foreach(cell, list)
    5073             :     {
    5074         376 :         char       *name = lfirst(cell);
    5075             : 
    5076         376 :         datums[j++] = CStringGetTextDatum(name);
    5077             :     }
    5078             : 
    5079         237 :     MemoryContextSwitchTo(oldcxt);
    5080             : 
    5081         237 :     arr = construct_array(datums, list_length(list),
    5082             :                           TEXTOID, -1, false, 'i');
    5083         237 :     MemoryContextDelete(memcxt);
    5084             : 
    5085         237 :     return arr;
    5086             : }

Generated by: LCOV version 1.11