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