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