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

Generated by: LCOV version 2.0-1