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