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

Generated by: LCOV version 1.14