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

Generated by: LCOV version 2.0-1