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

Generated by: LCOV version 1.16