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

Generated by: LCOV version 1.13