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

Generated by: LCOV version 1.14