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

Generated by: LCOV version 1.14