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