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

Generated by: LCOV version 2.0-1