PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/catalog/objectaddress.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include "access/genam.h"
19#include "access/htup_details.h"
20#include "access/relation.h"
21#include "access/table.h"
22#include "catalog/catalog.h"
24#include "catalog/pg_am.h"
25#include "catalog/pg_amop.h"
26#include "catalog/pg_amproc.h"
27#include "catalog/pg_attrdef.h"
28#include "catalog/pg_authid.h"
30#include "catalog/pg_cast.h"
34#include "catalog/pg_database.h"
40#include "catalog/pg_language.h"
44#include "catalog/pg_opclass.h"
45#include "catalog/pg_operator.h"
46#include "catalog/pg_opfamily.h"
48#include "catalog/pg_policy.h"
49#include "catalog/pg_proc.h"
58#include "catalog/pg_rewrite.h"
63#include "catalog/pg_trigger.h"
65#include "catalog/pg_ts_dict.h"
68#include "catalog/pg_type.h"
70#include "commands/defrem.h"
72#include "commands/extension.h"
73#include "commands/policy.h"
74#include "commands/proclang.h"
75#include "commands/tablespace.h"
76#include "commands/trigger.h"
77#include "foreign/foreign.h"
78#include "funcapi.h"
79#include "miscadmin.h"
80#include "parser/parse_func.h"
81#include "parser/parse_oper.h"
82#include "parser/parse_type.h"
85#include "storage/lmgr.h"
86#include "storage/sinval.h"
87#include "utils/acl.h"
88#include "utils/builtins.h"
89#include "utils/fmgroids.h"
90#include "utils/lsyscache.h"
91#include "utils/memutils.h"
92#include "utils/regproc.h"
93#include "utils/syscache.h"
94
95/*
96 * ObjectProperty
97 *
98 * This array provides a common part of system object structure; to help
99 * consolidate routines to handle various kind of object classes.
100 */
101typedef struct
102{
103 const char *class_descr; /* string describing the catalog, for internal
104 * error messages */
105 Oid class_oid; /* oid of catalog */
106 Oid oid_index_oid; /* oid of index on system oid column */
107 SysCacheIdentifier oid_catcache_id; /* id of catcache on system oid column */
109 * (name,namespace), or (name) if
110 * the object does not live in a
111 * namespace */
112 AttrNumber attnum_oid; /* attribute number of oid column */
113 AttrNumber attnum_name; /* attnum of name field */
114 AttrNumber attnum_namespace; /* attnum of namespace field */
115 AttrNumber attnum_owner; /* attnum of owner field */
116 AttrNumber attnum_acl; /* attnum of acl field */
117 ObjectType objtype; /* OBJECT_* of this object type */
118 bool is_nsp_name_unique; /* can the nsp/name combination (or name
119 * alone, if there's no namespace) be
120 * considered a unique identifier for an
121 * object of this class? */
123
125{
126 {
127 "access method",
130 AMOID,
131 AMNAME,
138 true
139 },
140 {
141 "access method operator",
152 false
153 },
154 {
155 "access method procedure",
166 false
167 },
168 {
169 "cast",
180 false
181 },
182 {
183 "collation",
186 COLLOID,
187 SYSCACHEID_INVALID, /* COLLNAMEENCNSP also takes encoding */
194 true
195 },
196 {
197 "constraint",
200 CONSTROID,
207 -1,
208 false
209 },
210 {
211 "conversion",
214 CONVOID,
222 true
223 },
224 {
225 "database",
236 true
237 },
238 {
239 "default ACL",
250 false
251 },
252 {
253 "extension",
260 InvalidAttrNumber, /* extension doesn't belong to extnamespace */
264 true
265 },
266 {
267 "foreign-data wrapper",
278 true
279 },
280 {
281 "foreign server",
292 true
293 },
294 {
295 "function",
298 PROCOID,
299 SYSCACHEID_INVALID, /* PROCNAMEARGSNSP also takes argument types */
306 false
307 },
308 {
309 "language",
312 LANGOID,
313 LANGNAME,
320 true
321 },
322 {
323 "large object metadata",
334 false
335 },
336 {
337 "operator class",
340 CLAOID,
341 SYSCACHEID_INVALID, /* CLAAMNAMENSP also takes opcmethod */
348 true
349 },
350 {
351 "operator",
354 OPEROID,
355 SYSCACHEID_INVALID, /* OPERNAMENSP also takes left and right type */
362 false
363 },
364 {
365 "operator family",
369 SYSCACHEID_INVALID, /* OPFAMILYAMNAMENSP also takes opfmethod */
376 true
377 },
378 {
379 "property graph element",
389 -1,
390 false
391 },
392 {
393 "property graph element label",
396 -1,
397 -1,
403 -1,
404 false
405 },
406 {
407 "property graph label",
417 -1,
418 false
419 },
420 {
421 "property graph label property",
424 -1,
425 -1,
431 -1,
432 false
433 },
434 {
435 "property graph property",
438 -1,
445 -1,
446 false
447 },
448 {
449 "role",
452 AUTHOID,
453 AUTHNAME,
460 true
461 },
462 {
463 "role membership",
473 -1,
474 true
475 },
476 {
477 "rule",
488 false
489 },
490 {
491 "schema",
502 true
503 },
504 {
505 "relation",
508 RELOID,
516 true
517 },
518 {
519 "tablespace",
530 true
531 },
532 {
533 "transform",
536 TRFOID,
544 false
545 },
546 {
547 "trigger",
558 false
559 },
560 {
561 "policy",
572 false
573 },
574 {
575 "event trigger",
586 true
587 },
588 {
589 "text search configuration",
600 true
601 },
602 {
603 "text search dictionary",
606 TSDICTOID,
614 true
615 },
616 {
617 "text search parser",
628 true
629 },
630 {
631 "text search template",
642 true,
643 },
644 {
645 "type",
648 TYPEOID,
656 true
657 },
658 {
659 "publication",
670 true
671 },
672 {
673 "subscription",
684 true
685 },
686 {
687 "extended statistics",
696 InvalidAttrNumber, /* no ACL (same as relation) */
698 true
699 },
700 {
701 "user mapping",
712 false
713 },
714};
715
716/*
717 * This struct maps the string object types as returned by
718 * getObjectTypeDescription into ObjectType enum values. Note that some enum
719 * values can be obtained by different names, and that some string object types
720 * do not have corresponding values in the output enum. The user of this map
721 * must be careful to test for invalid values being returned.
722 *
723 * To ease maintenance, this follows the order of getObjectTypeDescription.
724 */
725static const struct object_type_map
726{
727 const char *tm_name;
729}
730
731 ObjectTypeMap[] =
732{
733 {
734 "table", OBJECT_TABLE
735 },
736 {
737 "index", OBJECT_INDEX
738 },
739 {
740 "sequence", OBJECT_SEQUENCE
741 },
742 {
743 "toast table", -1
744 }, /* unmapped */
745 {
746 "view", OBJECT_VIEW
747 },
748 {
749 "materialized view", OBJECT_MATVIEW
750 },
751 {
752 "composite type", -1
753 }, /* unmapped */
754 {
755 "foreign table", OBJECT_FOREIGN_TABLE
756 },
757 {
758 "property graph", OBJECT_PROPGRAPH
759 },
760 {
761 "table column", OBJECT_COLUMN
762 },
763 {
764 "index column", -1
765 }, /* unmapped */
766 {
767 "sequence column", -1
768 }, /* unmapped */
769 {
770 "toast table column", -1
771 }, /* unmapped */
772 {
773 "view column", -1
774 }, /* unmapped */
775 {
776 "materialized view column", -1
777 }, /* unmapped */
778 {
779 "composite type column", -1
780 }, /* unmapped */
781 {
782 "foreign table column", OBJECT_COLUMN
783 },
784 {
785 "aggregate", OBJECT_AGGREGATE
786 },
787 {
788 "function", OBJECT_FUNCTION
789 },
790 {
791 "procedure", OBJECT_PROCEDURE
792 },
793 {
794 "type", OBJECT_TYPE
795 },
796 {
797 "cast", OBJECT_CAST
798 },
799 {
800 "collation", OBJECT_COLLATION
801 },
802 {
803 "table constraint", OBJECT_TABCONSTRAINT
804 },
805 {
806 "domain constraint", OBJECT_DOMCONSTRAINT
807 },
808 {
809 "conversion", OBJECT_CONVERSION
810 },
811 {
812 "default value", OBJECT_DEFAULT
813 },
814 {
815 "language", OBJECT_LANGUAGE
816 },
817 {
818 "large object", OBJECT_LARGEOBJECT
819 },
820 {
821 "operator", OBJECT_OPERATOR
822 },
823 {
824 "operator class", OBJECT_OPCLASS
825 },
826 {
827 "operator family", OBJECT_OPFAMILY
828 },
829 {
830 "access method", OBJECT_ACCESS_METHOD
831 },
832 {
833 "operator of access method", OBJECT_AMOP
834 },
835 {
836 "function of access method", OBJECT_AMPROC
837 },
838 {
839 "rule", OBJECT_RULE
840 },
841 {
842 "trigger", OBJECT_TRIGGER
843 },
844 {
845 "schema", OBJECT_SCHEMA
846 },
847 {
848 "text search parser", OBJECT_TSPARSER
849 },
850 {
851 "text search dictionary", OBJECT_TSDICTIONARY
852 },
853 {
854 "text search template", OBJECT_TSTEMPLATE
855 },
856 {
857 "text search configuration", OBJECT_TSCONFIGURATION
858 },
859 {
860 "role", OBJECT_ROLE
861 },
862 {
863 "role membership", -1 /* unmapped */
864 },
865 {
866 "database", OBJECT_DATABASE
867 },
868 {
869 "tablespace", OBJECT_TABLESPACE
870 },
871 {
872 "foreign-data wrapper", OBJECT_FDW
873 },
874 {
875 "server", OBJECT_FOREIGN_SERVER
876 },
877 {
878 "user mapping", OBJECT_USER_MAPPING
879 },
880 {
881 "default acl", OBJECT_DEFACL
882 },
883 {
884 "extension", OBJECT_EXTENSION
885 },
886 {
887 "event trigger", OBJECT_EVENT_TRIGGER
888 },
889 {
890 "parameter ACL", OBJECT_PARAMETER_ACL
891 },
892 {
893 "policy", OBJECT_POLICY
894 },
895 {
896 "property graph element", -1
897 },
898 {
899 "property graph label", -1
900 },
901 {
902 "property graph property", -1
903 },
904 {
905 "publication", OBJECT_PUBLICATION
906 },
907 {
908 "publication namespace", OBJECT_PUBLICATION_NAMESPACE
909 },
910 {
911 "publication relation", OBJECT_PUBLICATION_REL
912 },
913 {
914 "subscription", OBJECT_SUBSCRIPTION
915 },
916 {
917 "transform", OBJECT_TRANSFORM
918 },
919 {
920 "statistics object", OBJECT_STATISTIC_EXT
921 }
923
925{
928 0
929};
930
932 String *strval, bool missing_ok);
934 List *object, Relation *relp,
935 LOCKMODE lockmode, bool missing_ok);
937 List *object, Relation *relp, bool missing_ok);
939 List *object, Relation *relp,
940 LOCKMODE lockmode, bool missing_ok);
942 List *object, Relation *relp, LOCKMODE lockmode,
943 bool missing_ok);
945 TypeName *typename, bool missing_ok);
947 bool missing_ok);
949 List *object, bool missing_ok);
950
952 bool missing_ok);
954 Relation *relp,
955 bool missing_ok);
957 bool missing_ok);
959 bool missing_ok);
961
962static void getRelationDescription(StringInfo buffer, Oid relid,
963 bool missing_ok);
964static void getOpFamilyDescription(StringInfo buffer, Oid opfid,
965 bool missing_ok);
966static void getRelationTypeDescription(StringInfo buffer, Oid relid,
967 int32 objectSubId, bool missing_ok);
968static void getProcedureTypeDescription(StringInfo buffer, Oid procid,
969 bool missing_ok);
971 bool missing_ok);
972static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object,
973 bool missing_ok);
974static void getRelationIdentity(StringInfo buffer, Oid relid, List **object,
975 bool missing_ok);
976
977/*
978 * Translate an object name and arguments (as passed by the parser) to an
979 * ObjectAddress.
980 *
981 * The returned object will be locked using the specified lockmode. If a
982 * sub-object is looked up, the parent object will be locked instead.
983 *
984 * If the object is a relation or a child object of a relation (e.g. an
985 * attribute or constraint), the relation is also opened and *relp receives
986 * the open relcache entry pointer; otherwise, *relp is set to NULL.
987 * (relp can be NULL if the caller never passes a relation-related object.) This
988 * is a bit grotty but it makes life simpler, since the caller will
989 * typically need the relcache entry too. Caller must close the relcache
990 * entry when done with it. The relation is locked with the specified lockmode
991 * if the target object is the relation itself or an attribute, but for other
992 * child objects, only AccessShareLock is acquired on the relation.
993 *
994 * If the object is not found, an error is thrown, unless missing_ok is
995 * true. In this case, no lock is acquired, relp is set to NULL, and the
996 * returned address has objectId set to InvalidOid.
997 *
998 * We don't currently provide a function to release the locks acquired here;
999 * typically, the lock must be held until commit to guard against a concurrent
1000 * drop operation.
1001 *
1002 * Note: If the object is not found, we don't give any indication of the
1003 * reason. (It might have been a missing schema if the name was qualified, or
1004 * a nonexistent type name in case of a cast, function or operator; etc).
1005 * Currently there is only one caller that might be interested in such info, so
1006 * we don't spend much effort here. If more callers start to care, it might be
1007 * better to add some support for that in this function.
1008 */
1011 Relation *relp, LOCKMODE lockmode, bool missing_ok)
1012{
1013 ObjectAddress address = {InvalidOid, InvalidOid, 0};
1015 Relation relation = NULL;
1017
1018 /* Some kind of lock must be taken. */
1019 Assert(lockmode != NoLock);
1020
1021 for (;;)
1022 {
1023 /*
1024 * Remember this value, so that, after looking up the object name and
1025 * locking it, we can check whether any invalidation messages have
1026 * been processed that might require a do-over.
1027 */
1029
1030 /* Look up object address. */
1031 switch (objtype)
1032 {
1033 case OBJECT_INDEX:
1034 case OBJECT_SEQUENCE:
1035 case OBJECT_TABLE:
1036 case OBJECT_VIEW:
1037 case OBJECT_MATVIEW:
1039 case OBJECT_PROPGRAPH:
1040 address =
1042 &relation, lockmode,
1043 missing_ok);
1044 break;
1045 case OBJECT_ATTRIBUTE:
1046 case OBJECT_COLUMN:
1047 address =
1048 get_object_address_attribute(objtype, castNode(List, object),
1049 &relation, lockmode,
1050 missing_ok);
1051 break;
1052 case OBJECT_DEFAULT:
1053 address =
1054 get_object_address_attrdef(objtype, castNode(List, object),
1055 &relation, lockmode,
1056 missing_ok);
1057 break;
1058 case OBJECT_RULE:
1059 case OBJECT_TRIGGER:
1061 case OBJECT_POLICY:
1062 address = get_object_address_relobject(objtype, castNode(List, object),
1063 &relation, missing_ok);
1064 break;
1066 {
1067 List *objlist;
1069 char *constrname;
1070
1071 objlist = castNode(List, object);
1074 missing_ok);
1076
1077 address.classId = ConstraintRelationId;
1078 address.objectId = get_domain_constraint_oid(domaddr.objectId,
1079 constrname, missing_ok);
1080 address.objectSubId = 0;
1081 }
1082 break;
1083 case OBJECT_DATABASE:
1084 case OBJECT_EXTENSION:
1085 case OBJECT_TABLESPACE:
1086 case OBJECT_ROLE:
1087 case OBJECT_SCHEMA:
1088 case OBJECT_LANGUAGE:
1089 case OBJECT_FDW:
1094 case OBJECT_PUBLICATION:
1096 address = get_object_address_unqualified(objtype,
1097 castNode(String, object), missing_ok);
1098 break;
1099 case OBJECT_TYPE:
1100 case OBJECT_DOMAIN:
1101 address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
1102 break;
1103 case OBJECT_AGGREGATE:
1104 case OBJECT_FUNCTION:
1105 case OBJECT_PROCEDURE:
1106 case OBJECT_ROUTINE:
1107 address.classId = ProcedureRelationId;
1108 address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
1109 address.objectSubId = 0;
1110 break;
1111 case OBJECT_OPERATOR:
1112 address.classId = OperatorRelationId;
1113 address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
1114 address.objectSubId = 0;
1115 break;
1116 case OBJECT_COLLATION:
1117 address.classId = CollationRelationId;
1118 address.objectId = get_collation_oid(castNode(List, object), missing_ok);
1119 address.objectSubId = 0;
1120 break;
1121 case OBJECT_CONVERSION:
1122 address.classId = ConversionRelationId;
1123 address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
1124 address.objectSubId = 0;
1125 break;
1126 case OBJECT_OPCLASS:
1127 case OBJECT_OPFAMILY:
1128 address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
1129 break;
1130 case OBJECT_AMOP:
1131 case OBJECT_AMPROC:
1132 address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
1133 break;
1134 case OBJECT_LARGEOBJECT:
1136 address.objectId = oidparse(object);
1137 address.objectSubId = 0;
1138 if (!LargeObjectExists(address.objectId))
1139 {
1140 if (!missing_ok)
1141 ereport(ERROR,
1143 errmsg("large object %u does not exist",
1144 address.objectId)));
1145 }
1146 break;
1147 case OBJECT_CAST:
1148 {
1149 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
1150 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
1153
1154 sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
1155 targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
1156 address.classId = CastRelationId;
1157 address.objectId =
1159 address.objectSubId = 0;
1160 }
1161 break;
1162 case OBJECT_TRANSFORM:
1163 {
1164 TypeName *typename = linitial_node(TypeName, castNode(List, object));
1165 char *langname = strVal(lsecond(castNode(List, object)));
1166 Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
1167 Oid lang_id = get_language_oid(langname, missing_ok);
1168
1169 address.classId = TransformRelationId;
1170 address.objectId =
1171 get_transform_oid(type_id, lang_id, missing_ok);
1172 address.objectSubId = 0;
1173 }
1174 break;
1175 case OBJECT_TSPARSER:
1176 address.classId = TSParserRelationId;
1177 address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
1178 address.objectSubId = 0;
1179 break;
1182 address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
1183 address.objectSubId = 0;
1184 break;
1185 case OBJECT_TSTEMPLATE:
1186 address.classId = TSTemplateRelationId;
1187 address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
1188 address.objectSubId = 0;
1189 break;
1191 address.classId = TSConfigRelationId;
1192 address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
1193 address.objectSubId = 0;
1194 break;
1196 address = get_object_address_usermapping(castNode(List, object),
1197 missing_ok);
1198 break;
1201 missing_ok);
1202 break;
1205 &relation,
1206 missing_ok);
1207 break;
1208 case OBJECT_DEFACL:
1209 address = get_object_address_defacl(castNode(List, object),
1210 missing_ok);
1211 break;
1215 missing_ok);
1216 address.objectSubId = 0;
1217 break;
1218 /* no default, to let compiler warn about missing case */
1219 }
1220
1221 if (!address.classId)
1222 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1223
1224 /*
1225 * If we could not find the supplied object, return without locking.
1226 */
1227 if (!OidIsValid(address.objectId))
1228 {
1229 Assert(missing_ok);
1230 return address;
1231 }
1232
1233 /*
1234 * If we're retrying, see if we got the same answer as last time. If
1235 * so, we're done; if not, we locked the wrong thing, so give up our
1236 * lock.
1237 */
1238 if (OidIsValid(old_address.classId))
1239 {
1240 if (old_address.classId == address.classId
1241 && old_address.objectId == address.objectId
1242 && old_address.objectSubId == address.objectSubId)
1243 break;
1244 if (old_address.classId != RelationRelationId)
1245 {
1246 if (IsSharedRelation(old_address.classId))
1248 old_address.objectId,
1249 0, lockmode);
1250 else
1252 old_address.objectId,
1253 0, lockmode);
1254 }
1255 }
1256
1257 /*
1258 * If we're dealing with a relation or attribute, then the relation is
1259 * already locked. Otherwise, we lock it now.
1260 */
1261 if (address.classId != RelationRelationId)
1262 {
1263 if (IsSharedRelation(address.classId))
1264 LockSharedObject(address.classId, address.objectId, 0,
1265 lockmode);
1266 else
1267 LockDatabaseObject(address.classId, address.objectId, 0,
1268 lockmode);
1269 }
1270
1271 /*
1272 * At this point, we've resolved the name to an OID and locked the
1273 * corresponding database object. However, it's possible that by the
1274 * time we acquire the lock on the object, concurrent DDL has modified
1275 * the database in such a way that the name we originally looked up no
1276 * longer resolves to that OID.
1277 *
1278 * We can be certain that this isn't an issue if (a) no shared
1279 * invalidation messages have been processed or (b) we've locked a
1280 * relation somewhere along the line. All the relation name lookups
1281 * in this module ultimately use RangeVarGetRelid() to acquire a
1282 * relation lock, and that function protects against the same kinds of
1283 * races we're worried about here. Even when operating on a
1284 * constraint, rule, or trigger, we still acquire AccessShareLock on
1285 * the relation, which is enough to freeze out any concurrent DDL.
1286 *
1287 * In all other cases, however, it's possible that the name we looked
1288 * up no longer refers to the object we locked, so we retry the lookup
1289 * and see whether we get the same answer.
1290 */
1291 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
1292 break;
1293 old_address = address;
1294 }
1295
1296 /* relp must be given if it's a relation */
1297 Assert(!relation || relp);
1298
1299 /* Return the object address and the relation. */
1300 if (relp)
1301 *relp = relation;
1302 return address;
1303}
1304
1305/*
1306 * Return an ObjectAddress based on a RangeVar and an object name. The
1307 * name of the relation identified by the RangeVar is prepended to the
1308 * (possibly empty) list passed in as object. This is useful to find
1309 * the ObjectAddress of objects that depend on a relation. All other
1310 * considerations are exactly as for get_object_address above.
1311 */
1314 Relation *relp, LOCKMODE lockmode,
1315 bool missing_ok)
1316{
1317 if (rel)
1318 {
1319 object = lcons(makeString(rel->relname), object);
1320 if (rel->schemaname)
1321 object = lcons(makeString(rel->schemaname), object);
1322 if (rel->catalogname)
1323 object = lcons(makeString(rel->catalogname), object);
1324 }
1325
1326 return get_object_address(objtype, (Node *) object,
1327 relp, lockmode, missing_ok);
1328}
1329
1330/*
1331 * Find an ObjectAddress for a type of object that is identified by an
1332 * unqualified name.
1333 */
1334static ObjectAddress
1336 String *strval, bool missing_ok)
1337{
1338 const char *name;
1339 ObjectAddress address;
1340
1341 name = strVal(strval);
1342
1343 /* Translate name to OID. */
1344 switch (objtype)
1345 {
1348 address.objectId = get_am_oid(name, missing_ok);
1349 address.objectSubId = 0;
1350 break;
1351 case OBJECT_DATABASE:
1352 address.classId = DatabaseRelationId;
1353 address.objectId = get_database_oid(name, missing_ok);
1354 address.objectSubId = 0;
1355 break;
1356 case OBJECT_EXTENSION:
1357 address.classId = ExtensionRelationId;
1358 address.objectId = get_extension_oid(name, missing_ok);
1359 address.objectSubId = 0;
1360 break;
1361 case OBJECT_TABLESPACE:
1362 address.classId = TableSpaceRelationId;
1363 address.objectId = get_tablespace_oid(name, missing_ok);
1364 address.objectSubId = 0;
1365 break;
1366 case OBJECT_ROLE:
1367 address.classId = AuthIdRelationId;
1368 address.objectId = get_role_oid(name, missing_ok);
1369 address.objectSubId = 0;
1370 break;
1371 case OBJECT_SCHEMA:
1372 address.classId = NamespaceRelationId;
1373 address.objectId = get_namespace_oid(name, missing_ok);
1374 address.objectSubId = 0;
1375 break;
1376 case OBJECT_LANGUAGE:
1377 address.classId = LanguageRelationId;
1378 address.objectId = get_language_oid(name, missing_ok);
1379 address.objectSubId = 0;
1380 break;
1381 case OBJECT_FDW:
1383 address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
1384 address.objectSubId = 0;
1385 break;
1388 address.objectId = get_foreign_server_oid(name, missing_ok);
1389 address.objectSubId = 0;
1390 break;
1393 address.objectId = get_event_trigger_oid(name, missing_ok);
1394 address.objectSubId = 0;
1395 break;
1398 address.objectId = ParameterAclLookup(name, missing_ok);
1399 address.objectSubId = 0;
1400 break;
1401 case OBJECT_PUBLICATION:
1403 address.objectId = get_publication_oid(name, missing_ok);
1404 address.objectSubId = 0;
1405 break;
1408 address.objectId = get_subscription_oid(name, missing_ok);
1409 address.objectSubId = 0;
1410 break;
1411 default:
1412 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1413 /* placate compiler, which doesn't know elog won't return */
1414 address.classId = InvalidOid;
1415 address.objectId = InvalidOid;
1416 address.objectSubId = 0;
1417 }
1418
1419 return address;
1420}
1421
1422/*
1423 * Locate a relation by qualified name.
1424 */
1425static ObjectAddress
1427 Relation *relp, LOCKMODE lockmode,
1428 bool missing_ok)
1429{
1430 Relation relation;
1431 ObjectAddress address;
1432
1433 address.classId = RelationRelationId;
1434 address.objectId = InvalidOid;
1435 address.objectSubId = 0;
1436
1438 lockmode, missing_ok);
1439 if (!relation)
1440 return address;
1441
1442 switch (objtype)
1443 {
1444 case OBJECT_INDEX:
1445 if (relation->rd_rel->relkind != RELKIND_INDEX &&
1446 relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
1447 ereport(ERROR,
1449 errmsg("\"%s\" is not an index",
1450 RelationGetRelationName(relation))));
1451 break;
1452 case OBJECT_PROPGRAPH:
1453 if (relation->rd_rel->relkind != RELKIND_PROPGRAPH)
1454 ereport(ERROR,
1456 errmsg("\"%s\" is not a property graph",
1457 RelationGetRelationName(relation))));
1458 break;
1459 case OBJECT_SEQUENCE:
1460 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
1461 ereport(ERROR,
1463 errmsg("\"%s\" is not a sequence",
1464 RelationGetRelationName(relation))));
1465 break;
1466 case OBJECT_TABLE:
1467 if (relation->rd_rel->relkind != RELKIND_RELATION &&
1468 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1469 ereport(ERROR,
1471 errmsg("\"%s\" is not a table",
1472 RelationGetRelationName(relation))));
1473 break;
1474 case OBJECT_VIEW:
1475 if (relation->rd_rel->relkind != RELKIND_VIEW)
1476 ereport(ERROR,
1478 errmsg("\"%s\" is not a view",
1479 RelationGetRelationName(relation))));
1480 break;
1481 case OBJECT_MATVIEW:
1482 if (relation->rd_rel->relkind != RELKIND_MATVIEW)
1483 ereport(ERROR,
1485 errmsg("\"%s\" is not a materialized view",
1486 RelationGetRelationName(relation))));
1487 break;
1489 if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1490 ereport(ERROR,
1492 errmsg("\"%s\" is not a foreign table",
1493 RelationGetRelationName(relation))));
1494 break;
1495 default:
1496 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1497 break;
1498 }
1499
1500 /* Done. */
1501 address.objectId = RelationGetRelid(relation);
1502 *relp = relation;
1503
1504 return address;
1505}
1506
1507/*
1508 * Find object address for an object that is attached to a relation.
1509 *
1510 * Note that we take only an AccessShareLock on the relation. We need not
1511 * pass down the LOCKMODE from get_object_address(), because that is the lock
1512 * mode for the object itself, not the relation to which it is attached.
1513 */
1514static ObjectAddress
1516 Relation *relp, bool missing_ok)
1517{
1518 ObjectAddress address;
1519 Relation relation = NULL;
1520 int nnames;
1521 const char *depname;
1522 List *relname;
1523 Oid reloid;
1524
1525 /* Extract name of dependent object. */
1526 depname = strVal(llast(object));
1527
1528 /* Separate relation name from dependent object name. */
1529 nnames = list_length(object);
1530 if (nnames < 2)
1531 ereport(ERROR,
1533 errmsg("must specify relation and object name")));
1534
1535 /* Extract relation name and open relation. */
1536 relname = list_copy_head(object, nnames - 1);
1539 missing_ok);
1540
1541 reloid = relation ? RelationGetRelid(relation) : InvalidOid;
1542
1543 switch (objtype)
1544 {
1545 case OBJECT_RULE:
1546 address.classId = RewriteRelationId;
1547 address.objectId = relation ?
1548 get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
1549 address.objectSubId = 0;
1550 break;
1551 case OBJECT_TRIGGER:
1552 address.classId = TriggerRelationId;
1553 address.objectId = relation ?
1554 get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
1555 address.objectSubId = 0;
1556 break;
1558 address.classId = ConstraintRelationId;
1559 address.objectId = relation ?
1560 get_relation_constraint_oid(reloid, depname, missing_ok) :
1561 InvalidOid;
1562 address.objectSubId = 0;
1563 break;
1564 case OBJECT_POLICY:
1565 address.classId = PolicyRelationId;
1566 address.objectId = relation ?
1567 get_relation_policy_oid(reloid, depname, missing_ok) :
1568 InvalidOid;
1569 address.objectSubId = 0;
1570 break;
1571 default:
1572 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1573 }
1574
1575 /* Avoid relcache leak when object not found. */
1576 if (!OidIsValid(address.objectId))
1577 {
1578 if (relation != NULL)
1579 table_close(relation, AccessShareLock);
1580
1581 relation = NULL; /* department of accident prevention */
1582 return address;
1583 }
1584
1585 /* Done. */
1586 *relp = relation;
1587 return address;
1588}
1589
1590/*
1591 * Find the ObjectAddress for an attribute.
1592 */
1593static ObjectAddress
1595 Relation *relp, LOCKMODE lockmode,
1596 bool missing_ok)
1597{
1598 ObjectAddress address;
1599 List *relname;
1600 Oid reloid;
1601 Relation relation;
1602 const char *attname;
1604
1605 /* Extract relation name and open relation. */
1606 if (list_length(object) < 2)
1607 ereport(ERROR,
1609 errmsg("column name must be qualified")));
1610 attname = strVal(llast(object));
1611 relname = list_copy_head(object, list_length(object) - 1);
1612 /* XXX no missing_ok support here */
1613 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1614 reloid = RelationGetRelid(relation);
1615
1616 /* Look up attribute and construct return value. */
1617 attnum = get_attnum(reloid, attname);
1619 {
1620 if (!missing_ok)
1621 ereport(ERROR,
1623 errmsg("column \"%s\" of relation \"%s\" does not exist",
1625
1626 address.classId = RelationRelationId;
1627 address.objectId = InvalidOid;
1629 relation_close(relation, lockmode);
1630 return address;
1631 }
1632
1633 address.classId = RelationRelationId;
1634 address.objectId = reloid;
1635 address.objectSubId = attnum;
1636
1637 *relp = relation;
1638 return address;
1639}
1640
1641/*
1642 * Find the ObjectAddress for an attribute's default value.
1643 */
1644static ObjectAddress
1646 Relation *relp, LOCKMODE lockmode,
1647 bool missing_ok)
1648{
1649 ObjectAddress address;
1650 List *relname;
1651 Oid reloid;
1652 Relation relation;
1653 const char *attname;
1655 TupleDesc tupdesc;
1656 Oid defoid;
1657
1658 /* Extract relation name and open relation. */
1659 if (list_length(object) < 2)
1660 ereport(ERROR,
1662 errmsg("column name must be qualified")));
1663 attname = strVal(llast(object));
1664 relname = list_copy_head(object, list_length(object) - 1);
1665 /* XXX no missing_ok support here */
1666 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1667 reloid = RelationGetRelid(relation);
1668
1669 tupdesc = RelationGetDescr(relation);
1670
1671 /* Look up attribute number and fetch the pg_attrdef OID */
1672 attnum = get_attnum(reloid, attname);
1674 if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
1675 defoid = GetAttrDefaultOid(reloid, attnum);
1676 if (!OidIsValid(defoid))
1677 {
1678 if (!missing_ok)
1679 ereport(ERROR,
1681 errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
1683
1685 address.objectId = InvalidOid;
1687 relation_close(relation, lockmode);
1688 return address;
1689 }
1690
1692 address.objectId = defoid;
1693 address.objectSubId = 0;
1694
1695 *relp = relation;
1696 return address;
1697}
1698
1699/*
1700 * Find the ObjectAddress for a type or domain
1701 */
1702static ObjectAddress
1703get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
1704{
1705 ObjectAddress address;
1706 Type tup;
1707
1708 address.classId = TypeRelationId;
1709 address.objectId = InvalidOid;
1710 address.objectSubId = 0;
1711
1712 tup = LookupTypeName(NULL, typename, NULL, missing_ok);
1713 if (!HeapTupleIsValid(tup))
1714 {
1715 if (!missing_ok)
1716 ereport(ERROR,
1718 errmsg("type \"%s\" does not exist",
1719 TypeNameToString(typename))));
1720 return address;
1721 }
1722 address.objectId = typeTypeId(tup);
1723
1724 if (objtype == OBJECT_DOMAIN)
1725 {
1726 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
1727 ereport(ERROR,
1729 errmsg("\"%s\" is not a domain",
1730 TypeNameToString(typename))));
1731 }
1732
1734
1735 return address;
1736}
1737
1738/*
1739 * Find the ObjectAddress for an opclass or opfamily.
1740 */
1741static ObjectAddress
1742get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
1743{
1744 Oid amoid;
1745 ObjectAddress address;
1746
1747 /* XXX no missing_ok support here */
1748 amoid = get_index_am_oid(strVal(linitial(object)), false);
1749 object = list_copy_tail(object, 1);
1750
1751 switch (objtype)
1752 {
1753 case OBJECT_OPCLASS:
1755 address.objectId = get_opclass_oid(amoid, object, missing_ok);
1756 address.objectSubId = 0;
1757 break;
1758 case OBJECT_OPFAMILY:
1760 address.objectId = get_opfamily_oid(amoid, object, missing_ok);
1761 address.objectSubId = 0;
1762 break;
1763 default:
1764 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1765 /* placate compiler, which doesn't know elog won't return */
1766 address.classId = InvalidOid;
1767 address.objectId = InvalidOid;
1768 address.objectSubId = 0;
1769 }
1770
1771 return address;
1772}
1773
1774/*
1775 * Find the ObjectAddress for an opclass/opfamily member.
1776 *
1777 * (The returned address corresponds to a pg_amop/pg_amproc object).
1778 */
1779static ObjectAddress
1781 List *object, bool missing_ok)
1782{
1784 ObjectAddress address;
1785 ListCell *cell;
1786 List *copy;
1787 TypeName *typenames[2];
1788 Oid typeoids[2];
1789 int membernum;
1790 int i;
1791
1792 /*
1793 * The last element of the object list contains the strategy or procedure
1794 * number. We need to strip that out before getting the opclass/family
1795 * address. The rest can be used directly by get_object_address_opcf().
1796 */
1797 membernum = atoi(strVal(llast(linitial(object))));
1798 copy = list_copy_head(linitial(object), list_length(linitial(object)) - 1);
1799
1800 /* no missing_ok support here */
1802
1803 /* find out left/right type names and OIDs */
1804 typenames[0] = typenames[1] = NULL;
1805 typeoids[0] = typeoids[1] = InvalidOid;
1806 i = 0;
1807 foreach(cell, lsecond(object))
1808 {
1810
1811 typenames[i] = lfirst_node(TypeName, cell);
1813 typeoids[i] = typaddr.objectId;
1814 if (++i >= 2)
1815 break;
1816 }
1817
1818 switch (objtype)
1819 {
1820 case OBJECT_AMOP:
1821 {
1822 HeapTuple tp;
1823
1825 InvalidOid);
1826
1828 ObjectIdGetDatum(famaddr.objectId),
1832 if (!HeapTupleIsValid(tp))
1833 {
1834 if (!missing_ok)
1835 ereport(ERROR,
1837 errmsg("operator %d (%s, %s) of %s does not exist",
1838 membernum,
1841 getObjectDescription(&famaddr, false))));
1842 }
1843 else
1844 {
1845 address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
1846 ReleaseSysCache(tp);
1847 }
1848 }
1849 break;
1850
1851 case OBJECT_AMPROC:
1852 {
1853 HeapTuple tp;
1854
1856 InvalidOid);
1857
1859 ObjectIdGetDatum(famaddr.objectId),
1863 if (!HeapTupleIsValid(tp))
1864 {
1865 if (!missing_ok)
1866 ereport(ERROR,
1868 errmsg("function %d (%s, %s) of %s does not exist",
1869 membernum,
1872 getObjectDescription(&famaddr, false))));
1873 }
1874 else
1875 {
1876 address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
1877 ReleaseSysCache(tp);
1878 }
1879 }
1880 break;
1881 default:
1882 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1883 }
1884
1885 return address;
1886}
1887
1888/*
1889 * Find the ObjectAddress for a user mapping.
1890 */
1891static ObjectAddress
1892get_object_address_usermapping(List *object, bool missing_ok)
1893{
1894 ObjectAddress address;
1895 Oid userid;
1896 char *username;
1897 char *servername;
1898 ForeignServer *server;
1899 HeapTuple tp;
1900
1902
1903 /* fetch string names from input lists, for error messages */
1904 username = strVal(linitial(object));
1905 servername = strVal(lsecond(object));
1906
1907 /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
1908 if (strcmp(username, "public") == 0)
1909 userid = InvalidOid;
1910 else
1911 {
1914 if (!HeapTupleIsValid(tp))
1915 {
1916 if (!missing_ok)
1917 ereport(ERROR,
1919 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1920 username, servername)));
1921 return address;
1922 }
1923 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
1924 ReleaseSysCache(tp);
1925 }
1926
1927 /* Now look up the pg_user_mapping tuple */
1928 server = GetForeignServerByName(servername, true);
1929 if (!server)
1930 {
1931 if (!missing_ok)
1932 ereport(ERROR,
1934 errmsg("server \"%s\" does not exist", servername)));
1935 return address;
1936 }
1938 ObjectIdGetDatum(userid),
1939 ObjectIdGetDatum(server->serverid));
1940 if (!HeapTupleIsValid(tp))
1941 {
1942 if (!missing_ok)
1943 ereport(ERROR,
1945 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1946 username, servername)));
1947 return address;
1948 }
1949
1950 address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
1951
1952 ReleaseSysCache(tp);
1953
1954 return address;
1955}
1956
1957/*
1958 * Find the ObjectAddress for a publication relation. The first element of
1959 * the object parameter is the relation name, the second is the
1960 * publication name.
1961 */
1962static ObjectAddress
1964 Relation *relp, bool missing_ok)
1965{
1966 ObjectAddress address;
1967 Relation relation;
1968 List *relname;
1969 char *pubname;
1970 Publication *pub;
1971
1973
1974 relname = linitial(object);
1976 AccessShareLock, missing_ok);
1977 if (!relation)
1978 return address;
1979
1980 /* fetch publication name from input list */
1981 pubname = strVal(lsecond(object));
1982
1983 /* Now look up the pg_publication tuple */
1984 pub = GetPublicationByName(pubname, missing_ok);
1985 if (!pub)
1986 {
1988 return address;
1989 }
1990
1991 /* Find the publication relation mapping in syscache. */
1992 address.objectId =
1995 ObjectIdGetDatum(pub->oid));
1996 if (!OidIsValid(address.objectId))
1997 {
1998 if (!missing_ok)
1999 ereport(ERROR,
2001 errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
2002 RelationGetRelationName(relation), pubname)));
2004 return address;
2005 }
2006
2007 *relp = relation;
2008 return address;
2009}
2010
2011/*
2012 * Find the ObjectAddress for a publication schema. The first element of the
2013 * object parameter is the schema name, the second is the publication name.
2014 */
2015static ObjectAddress
2017{
2018 ObjectAddress address;
2019 Publication *pub;
2020 char *pubname;
2021 char *schemaname;
2022 Oid schemaid;
2023
2025
2026 /* Fetch schema name and publication name from input list */
2027 schemaname = strVal(linitial(object));
2028 pubname = strVal(lsecond(object));
2029
2030 schemaid = get_namespace_oid(schemaname, missing_ok);
2031 if (!OidIsValid(schemaid))
2032 return address;
2033
2034 /* Now look up the pg_publication tuple */
2035 pub = GetPublicationByName(pubname, missing_ok);
2036 if (!pub)
2037 return address;
2038
2039 /* Find the publication schema mapping in syscache */
2040 address.objectId =
2044 ObjectIdGetDatum(pub->oid));
2045 if (!OidIsValid(address.objectId) && !missing_ok)
2046 ereport(ERROR,
2048 errmsg("publication schema \"%s\" in publication \"%s\" does not exist",
2049 schemaname, pubname)));
2050
2051 return address;
2052}
2053
2054/*
2055 * Find the ObjectAddress for a default ACL.
2056 */
2057static ObjectAddress
2058get_object_address_defacl(List *object, bool missing_ok)
2059{
2060 HeapTuple tp;
2061 Oid userid;
2062 Oid schemaid;
2063 char *username;
2064 char *schema;
2065 char objtype;
2066 char *objtype_str;
2067 ObjectAddress address;
2068
2070
2071 /*
2072 * First figure out the textual attributes so that they can be used for
2073 * error reporting.
2074 */
2075 username = strVal(lsecond(object));
2076 if (list_length(object) >= 3)
2077 schema = (char *) strVal(lthird(object));
2078 else
2079 schema = NULL;
2080
2081 /*
2082 * Decode defaclobjtype. Only first char is considered; the rest of the
2083 * string, if any, is blissfully ignored.
2084 */
2085 objtype = ((char *) strVal(linitial(object)))[0];
2086 switch (objtype)
2087 {
2088 case DEFACLOBJ_RELATION:
2089 objtype_str = "tables";
2090 break;
2091 case DEFACLOBJ_SEQUENCE:
2092 objtype_str = "sequences";
2093 break;
2094 case DEFACLOBJ_FUNCTION:
2095 objtype_str = "functions";
2096 break;
2097 case DEFACLOBJ_TYPE:
2098 objtype_str = "types";
2099 break;
2101 objtype_str = "schemas";
2102 break;
2104 objtype_str = "large objects";
2105 break;
2106 default:
2107 ereport(ERROR,
2109 errmsg("unrecognized default ACL object type \"%c\"", objtype),
2110 errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
2117 }
2118
2119 /*
2120 * Look up user ID. Behave as "default ACL not found" if the user doesn't
2121 * exist.
2122 */
2125 if (!HeapTupleIsValid(tp))
2126 goto not_found;
2127 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
2128 ReleaseSysCache(tp);
2129
2130 /*
2131 * If a schema name was given, look up its OID. If it doesn't exist,
2132 * behave as "default ACL not found".
2133 */
2134 if (schema)
2135 {
2136 schemaid = get_namespace_oid(schema, true);
2137 if (schemaid == InvalidOid)
2138 goto not_found;
2139 }
2140 else
2142
2143 /* Finally, look up the pg_default_acl object */
2145 ObjectIdGetDatum(userid),
2147 CharGetDatum(objtype));
2148 if (!HeapTupleIsValid(tp))
2149 goto not_found;
2150
2151 address.objectId = ((Form_pg_default_acl) GETSTRUCT(tp))->oid;
2152 ReleaseSysCache(tp);
2153
2154 return address;
2155
2156not_found:
2157 if (!missing_ok)
2158 {
2159 if (schema)
2160 ereport(ERROR,
2162 errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
2163 username, schema, objtype_str)));
2164 else
2165 ereport(ERROR,
2167 errmsg("default ACL for user \"%s\" on %s does not exist",
2169 }
2170 return address;
2171}
2172
2173/*
2174 * Convert an array of TEXT into a List of string Values, as emitted by the
2175 * parser, which is what get_object_address uses as input.
2176 */
2177static List *
2179{
2180 Datum *elems;
2181 bool *nulls;
2182 int nelems;
2183 List *list = NIL;
2184 int i;
2185
2186 deconstruct_array_builtin(arr, TEXTOID, &elems, &nulls, &nelems);
2187
2188 for (i = 0; i < nelems; i++)
2189 {
2190 if (nulls[i])
2191 ereport(ERROR,
2193 errmsg("name or argument lists may not contain nulls")));
2194 list = lappend(list, makeString(TextDatumGetCString(elems[i])));
2195 }
2196
2197 return list;
2198}
2199
2200/*
2201 * SQL-callable version of get_object_address
2202 */
2203Datum
2205{
2206 char *ttype = TextDatumGetCString(PG_GETARG_DATUM(0));
2209 int itype;
2211 List *name = NIL;
2212 TypeName *typename = NULL;
2213 List *args = NIL;
2214 Node *objnode = NULL;
2215 ObjectAddress addr;
2216 TupleDesc tupdesc;
2217 Datum values[3];
2218 bool nulls[3];
2219 HeapTuple htup;
2220 Relation relation;
2221
2222 /* Decode object type, raise error if unknown */
2224 if (itype < 0)
2225 ereport(ERROR,
2227 errmsg("unsupported object type \"%s\"", ttype)));
2228 type = (ObjectType) itype;
2229
2230 /*
2231 * Convert the text array to the representation appropriate for the given
2232 * object type. Most use a simple string Values list, but there are some
2233 * exceptions.
2234 */
2235 if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
2237 {
2238 Datum *elems;
2239 bool *nulls;
2240 int nelems;
2241
2242 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2243 if (nelems != 1)
2244 ereport(ERROR,
2246 errmsg("name list length must be exactly %d", 1)));
2247 if (nulls[0])
2248 ereport(ERROR,
2250 errmsg("name or argument lists may not contain nulls")));
2251 typename = typeStringToTypeName(TextDatumGetCString(elems[0]), NULL);
2252 }
2253 else if (type == OBJECT_LARGEOBJECT)
2254 {
2255 Datum *elems;
2256 bool *nulls;
2257 int nelems;
2258
2259 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2260 if (nelems != 1)
2261 ereport(ERROR,
2263 errmsg("name list length must be exactly %d", 1)));
2264 if (nulls[0])
2265 ereport(ERROR,
2267 errmsg("large object OID may not be null")));
2268 objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
2269 }
2270 else
2271 {
2273 if (name == NIL)
2274 ereport(ERROR,
2276 errmsg("name list length must be at least %d", 1)));
2277 }
2278
2279 /*
2280 * If args are given, decode them according to the object type.
2281 */
2282 if (type == OBJECT_AGGREGATE ||
2283 type == OBJECT_FUNCTION ||
2285 type == OBJECT_ROUTINE ||
2286 type == OBJECT_OPERATOR ||
2287 type == OBJECT_CAST ||
2288 type == OBJECT_AMOP ||
2290 {
2291 /* in these cases, the args list must be of TypeName */
2292 Datum *elems;
2293 bool *nulls;
2294 int nelems;
2295 int i;
2296
2297 deconstruct_array_builtin(argsarr, TEXTOID, &elems, &nulls, &nelems);
2298
2299 args = NIL;
2300 for (i = 0; i < nelems; i++)
2301 {
2302 if (nulls[i])
2303 ereport(ERROR,
2305 errmsg("name or argument lists may not contain nulls")));
2306 args = lappend(args,
2308 NULL));
2309 }
2310 }
2311 else
2312 {
2313 /* For all other object types, use string Values */
2315 }
2316
2317 /*
2318 * get_object_address is pretty sensitive to the length of its input
2319 * lists; check that they're what it wants.
2320 */
2321 switch (type)
2322 {
2325 if (list_length(name) != 1)
2326 ereport(ERROR,
2328 errmsg("name list length must be exactly %d", 1)));
2329 /* fall through to check args length */
2332 case OBJECT_CAST:
2334 case OBJECT_DEFACL:
2335 case OBJECT_TRANSFORM:
2336 if (list_length(args) != 1)
2337 ereport(ERROR,
2339 errmsg("argument list length must be exactly %d", 1)));
2340 break;
2341 case OBJECT_OPFAMILY:
2342 case OBJECT_OPCLASS:
2343 if (list_length(name) < 2)
2344 ereport(ERROR,
2346 errmsg("name list length must be at least %d", 2)));
2347 break;
2348 case OBJECT_AMOP:
2349 case OBJECT_AMPROC:
2350 if (list_length(name) < 3)
2351 ereport(ERROR,
2353 errmsg("name list length must be at least %d", 3)));
2354 /* fall through to check args length */
2356 case OBJECT_OPERATOR:
2357 if (list_length(args) != 2)
2358 ereport(ERROR,
2360 errmsg("argument list length must be exactly %d", 2)));
2361 break;
2362 default:
2363 break;
2364 }
2365
2366 /*
2367 * Now build the Node type that get_object_address() expects for the given
2368 * type.
2369 */
2370 switch (type)
2371 {
2372 case OBJECT_TABLE:
2373 case OBJECT_SEQUENCE:
2374 case OBJECT_VIEW:
2375 case OBJECT_MATVIEW:
2376 case OBJECT_INDEX:
2378 case OBJECT_PROPGRAPH:
2379 case OBJECT_COLUMN:
2380 case OBJECT_ATTRIBUTE:
2381 case OBJECT_COLLATION:
2382 case OBJECT_CONVERSION:
2384 case OBJECT_TSPARSER:
2386 case OBJECT_TSTEMPLATE:
2388 case OBJECT_DEFAULT:
2389 case OBJECT_POLICY:
2390 case OBJECT_RULE:
2391 case OBJECT_TRIGGER:
2393 case OBJECT_OPCLASS:
2394 case OBJECT_OPFAMILY:
2395 objnode = (Node *) name;
2396 break;
2398 case OBJECT_DATABASE:
2400 case OBJECT_EXTENSION:
2401 case OBJECT_FDW:
2403 case OBJECT_LANGUAGE:
2405 case OBJECT_PUBLICATION:
2406 case OBJECT_ROLE:
2407 case OBJECT_SCHEMA:
2409 case OBJECT_TABLESPACE:
2410 if (list_length(name) != 1)
2411 ereport(ERROR,
2413 errmsg("name list length must be exactly %d", 1)));
2415 break;
2416 case OBJECT_TYPE:
2417 case OBJECT_DOMAIN:
2418 objnode = (Node *) typename;
2419 break;
2420 case OBJECT_CAST:
2422 case OBJECT_TRANSFORM:
2423 objnode = (Node *) list_make2(typename, linitial(args));
2424 break;
2426 objnode = (Node *) list_make2(name, linitial(args));
2427 break;
2431 break;
2432 case OBJECT_DEFACL:
2433 objnode = (Node *) lcons(linitial(args), name);
2434 break;
2435 case OBJECT_AMOP:
2436 case OBJECT_AMPROC:
2437 objnode = (Node *) list_make2(name, args);
2438 break;
2439 case OBJECT_FUNCTION:
2440 case OBJECT_PROCEDURE:
2441 case OBJECT_ROUTINE:
2442 case OBJECT_AGGREGATE:
2443 case OBJECT_OPERATOR:
2444 {
2446
2447 owa->objname = name;
2448 owa->objargs = args;
2449 objnode = (Node *) owa;
2450 break;
2451 }
2452 case OBJECT_LARGEOBJECT:
2453 /* already handled above */
2454 break;
2455 /* no default, to let compiler warn about missing case */
2456 }
2457
2458 if (objnode == NULL)
2459 elog(ERROR, "unrecognized object type: %d", type);
2460
2462 &relation, AccessShareLock, false);
2463
2464 /* We don't need the relcache entry, thank you very much */
2465 if (relation)
2467
2468 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2469 elog(ERROR, "return type must be a row type");
2470
2471 values[0] = ObjectIdGetDatum(addr.classId);
2472 values[1] = ObjectIdGetDatum(addr.objectId);
2473 values[2] = Int32GetDatum(addr.objectSubId);
2474 nulls[0] = false;
2475 nulls[1] = false;
2476 nulls[2] = false;
2477
2478 htup = heap_form_tuple(tupdesc, values, nulls);
2479
2481}
2482
2483/*
2484 * Check ownership of an object previously identified by get_object_address.
2485 */
2486void
2488 Node *object, Relation relation)
2489{
2490 switch (objtype)
2491 {
2492 case OBJECT_INDEX:
2493 case OBJECT_SEQUENCE:
2494 case OBJECT_TABLE:
2495 case OBJECT_VIEW:
2496 case OBJECT_MATVIEW:
2498 case OBJECT_PROPGRAPH:
2499 case OBJECT_COLUMN:
2500 case OBJECT_RULE:
2501 case OBJECT_TRIGGER:
2502 case OBJECT_POLICY:
2504 if (!object_ownercheck(RelationRelationId, RelationGetRelid(relation), roleid))
2506 RelationGetRelationName(relation));
2507 break;
2508 case OBJECT_TYPE:
2509 case OBJECT_DOMAIN:
2510 case OBJECT_ATTRIBUTE:
2511 if (!object_ownercheck(address.classId, address.objectId, roleid))
2513 break;
2515 {
2516 HeapTuple tuple;
2517 Oid contypid;
2518
2519 tuple = SearchSysCache1(CONSTROID,
2520 ObjectIdGetDatum(address.objectId));
2521 if (!HeapTupleIsValid(tuple))
2522 elog(ERROR, "constraint with OID %u does not exist",
2523 address.objectId);
2524
2526
2527 ReleaseSysCache(tuple);
2528
2529 /*
2530 * Fallback to type ownership check in this case as this is
2531 * what domain constraints rely on.
2532 */
2535 }
2536 break;
2537 case OBJECT_AGGREGATE:
2538 case OBJECT_FUNCTION:
2539 case OBJECT_PROCEDURE:
2540 case OBJECT_ROUTINE:
2541 case OBJECT_OPERATOR:
2542 if (!object_ownercheck(address.classId, address.objectId, roleid))
2544 NameListToString((castNode(ObjectWithArgs, object))->objname));
2545 break;
2546 case OBJECT_DATABASE:
2548 case OBJECT_EXTENSION:
2549 case OBJECT_FDW:
2551 case OBJECT_LANGUAGE:
2552 case OBJECT_PUBLICATION:
2553 case OBJECT_SCHEMA:
2555 case OBJECT_TABLESPACE:
2556 if (!object_ownercheck(address.classId, address.objectId, roleid))
2558 strVal(object));
2559 break;
2560 case OBJECT_COLLATION:
2561 case OBJECT_CONVERSION:
2562 case OBJECT_OPCLASS:
2563 case OBJECT_OPFAMILY:
2567 if (!object_ownercheck(address.classId, address.objectId, roleid))
2569 NameListToString(castNode(List, object)));
2570 break;
2571 case OBJECT_LARGEOBJECT:
2572 if (!lo_compat_privileges &&
2573 !object_ownercheck(address.classId, address.objectId, roleid))
2574 ereport(ERROR,
2576 errmsg("must be owner of large object %u",
2577 address.objectId)));
2578 break;
2579 case OBJECT_CAST:
2580 {
2581 /* We can only check permissions on the source/target types */
2582 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
2583 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
2584 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
2585 Oid targettypeid = typenameTypeId(NULL, targettype);
2586
2589 ereport(ERROR,
2591 errmsg("must be owner of type %s or type %s",
2594 }
2595 break;
2596 case OBJECT_TRANSFORM:
2597 {
2598 TypeName *typename = linitial_node(TypeName, castNode(List, object));
2599 Oid typeid = typenameTypeId(NULL, typename);
2600
2601 if (!object_ownercheck(TypeRelationId, typeid, roleid))
2603 }
2604 break;
2605 case OBJECT_ROLE:
2606
2607 /*
2608 * We treat roles as being "owned" by those with CREATEROLE priv,
2609 * provided that they also have admin option on the role.
2610 *
2611 * However, superusers are only owned by superusers.
2612 */
2613 if (superuser_arg(address.objectId))
2614 {
2615 if (!superuser_arg(roleid))
2616 ereport(ERROR,
2618 errmsg("permission denied"),
2619 errdetail("The current user must have the %s attribute.",
2620 "SUPERUSER")));
2621 }
2622 else
2623 {
2624 if (!has_createrole_privilege(roleid))
2625 ereport(ERROR,
2627 errmsg("permission denied"),
2628 errdetail("The current user must have the %s attribute.",
2629 "CREATEROLE")));
2630 if (!is_admin_of_role(roleid, address.objectId))
2631 ereport(ERROR,
2633 errmsg("permission denied"),
2634 errdetail("The current user must have the %s option on role \"%s\".",
2635 "ADMIN",
2637 true))));
2638 }
2639 break;
2640 case OBJECT_TSPARSER:
2641 case OBJECT_TSTEMPLATE:
2644 /* We treat these object types as being owned by superusers */
2645 if (!superuser_arg(roleid))
2646 ereport(ERROR,
2648 errmsg("must be superuser")));
2649 break;
2650 case OBJECT_AMOP:
2651 case OBJECT_AMPROC:
2652 case OBJECT_DEFAULT:
2653 case OBJECT_DEFACL:
2657 /* These are currently not supported or don't make sense here. */
2658 elog(ERROR, "unsupported object type: %d", (int) objtype);
2659 break;
2660 }
2661}
2662
2663/*
2664 * get_object_namespace
2665 *
2666 * Find the schema containing the specified object. For non-schema objects,
2667 * this function returns InvalidOid.
2668 */
2669Oid
2671{
2672 SysCacheIdentifier cache;
2673 HeapTuple tuple;
2674 Oid oid;
2676
2677 /* If not owned by a namespace, just return InvalidOid. */
2678 property = get_object_property_data(address->classId);
2679 if (property->attnum_namespace == InvalidAttrNumber)
2680 return InvalidOid;
2681
2682 /* Currently, we can only handle object types with system caches. */
2683 cache = property->oid_catcache_id;
2684 Assert(cache != SYSCACHEID_INVALID);
2685
2686 /* Fetch tuple from syscache and extract namespace attribute. */
2687 tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
2688 if (!HeapTupleIsValid(tuple))
2689 elog(ERROR, "cache lookup failed for cache %d oid %u",
2690 cache, address->objectId);
2692 tuple,
2693 property->attnum_namespace));
2694 ReleaseSysCache(tuple);
2695
2696 return oid;
2697}
2698
2699/*
2700 * Return ObjectType for the given object type as given by
2701 * getObjectTypeDescription; if no valid ObjectType code exists, but it's a
2702 * possible output type from getObjectTypeDescription, return -1.
2703 * Otherwise, an error is thrown.
2704 */
2705int
2706read_objtype_from_string(const char *objtype)
2707{
2708 int i;
2709
2710 for (i = 0; i < lengthof(ObjectTypeMap); i++)
2711 {
2712 if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
2713 return ObjectTypeMap[i].tm_type;
2714 }
2715 ereport(ERROR,
2717 errmsg("unrecognized object type \"%s\"", objtype)));
2718
2719 return -1; /* keep compiler quiet */
2720}
2721
2722/*
2723 * Interfaces to reference fields of ObjectPropertyType
2724 */
2725const char *
2732
2733Oid
2740
2748
2756
2759{
2761
2762 return prop->attnum_oid;
2763}
2764
2772
2780
2788
2791{
2793
2794 return prop->attnum_acl;
2795}
2796
2797/*
2798 * get_object_type
2799 *
2800 * Return the object type associated with a given object. This routine
2801 * is primarily used to determine the object type to mention in ACL check
2802 * error messages, so it's desirable for it to avoid failing.
2803 */
2806{
2808
2809 if (prop->objtype == OBJECT_TABLE)
2810 {
2811 /*
2812 * If the property data says it's a table, dig a little deeper to get
2813 * the real relation kind, so that callers can produce more precise
2814 * error messages.
2815 */
2816 return get_relkind_objtype(get_rel_relkind(object_id));
2817 }
2818 else
2819 return prop->objtype;
2820}
2821
2822bool
2829
2830/*
2831 * Return whether we have useful data for the given object class in the
2832 * ObjectProperty table.
2833 */
2834bool
2836{
2837 int index;
2838
2839 for (index = 0; index < lengthof(ObjectProperty); index++)
2840 {
2841 if (ObjectProperty[index].class_oid == class_id)
2842 return true;
2843 }
2844
2845 return false;
2846}
2847
2848/*
2849 * Find ObjectProperty structure by class_id.
2850 */
2851static const ObjectPropertyType *
2853{
2854 static const ObjectPropertyType *prop_last = NULL;
2855 int index;
2856
2857 /*
2858 * A shortcut to speed up multiple consecutive lookups of a particular
2859 * object class.
2860 */
2861 if (prop_last && prop_last->class_oid == class_id)
2862 return prop_last;
2863
2864 for (index = 0; index < lengthof(ObjectProperty); index++)
2865 {
2866 if (ObjectProperty[index].class_oid == class_id)
2867 {
2869 return &ObjectProperty[index];
2870 }
2871 }
2872
2873 ereport(ERROR,
2874 (errmsg_internal("unrecognized class ID: %u", class_id)));
2875
2876 return NULL; /* keep MSC compiler happy */
2877}
2878
2879/*
2880 * Return a copy of the tuple for the object with the given object OID, from
2881 * the given catalog (which must have been opened by the caller and suitably
2882 * locked). NULL is returned if the OID is not found.
2883 *
2884 * We try a syscache first, if available.
2885 */
2892
2893/*
2894 * Same as get_catalog_object_by_oid(), but with an additional "locktup"
2895 * argument controlling whether to acquire a LOCKTAG_TUPLE at mode
2896 * InplaceUpdateTupleLock. See README.tuplock section "Locking to write
2897 * inplace-updated tables".
2898 */
2902 Oid objectId,
2903 bool locktup)
2904{
2905 HeapTuple tuple;
2906 Oid classId = RelationGetRelid(catalog);
2908
2909 if (oidCacheId >= 0)
2910 {
2911 if (locktup)
2913 ObjectIdGetDatum(objectId));
2914 else
2916 ObjectIdGetDatum(objectId));
2917 if (!HeapTupleIsValid(tuple)) /* should not happen */
2918 return NULL;
2919 }
2920 else
2921 {
2923 SysScanDesc scan;
2925
2927
2929 oidcol,
2931 ObjectIdGetDatum(objectId));
2932
2934 NULL, 1, &skey);
2935 tuple = systable_getnext(scan);
2936 if (!HeapTupleIsValid(tuple))
2937 {
2938 systable_endscan(scan);
2939 return NULL;
2940 }
2941
2942 if (locktup)
2944
2945 tuple = heap_copytuple(tuple);
2946
2947 systable_endscan(scan);
2948 }
2949
2950 return tuple;
2951}
2952
2953/*
2954 * getPublicationSchemaInfo
2955 *
2956 * Get publication name and schema name from the object address into pubname and
2957 * nspname. Both pubname and nspname are palloc'd strings which will be freed by
2958 * the caller.
2959 */
2960static bool
2961getPublicationSchemaInfo(const ObjectAddress *object, bool missing_ok,
2962 char **pubname, char **nspname)
2963{
2964 HeapTuple tup;
2966
2968 ObjectIdGetDatum(object->objectId));
2969 if (!HeapTupleIsValid(tup))
2970 {
2971 if (!missing_ok)
2972 elog(ERROR, "cache lookup failed for publication schema %u",
2973 object->objectId);
2974 return false;
2975 }
2976
2978 *pubname = get_publication_name(pnform->pnpubid, missing_ok);
2979 if (!(*pubname))
2980 {
2982 return false;
2983 }
2984
2985 *nspname = get_namespace_name(pnform->pnnspid);
2986 if (!(*nspname))
2987 {
2988 Oid schemaid = pnform->pnnspid;
2989
2990 pfree(*pubname);
2992 if (!missing_ok)
2993 elog(ERROR, "cache lookup failed for schema %u",
2994 schemaid);
2995 return false;
2996 }
2997
2999 return true;
3000}
3001
3002/*
3003 * getObjectDescription: build an object description for messages
3004 *
3005 * The result is a palloc'd string. NULL is returned for an undefined
3006 * object if missing_ok is true, else an error is generated.
3007 */
3008char *
3009getObjectDescription(const ObjectAddress *object, bool missing_ok)
3010{
3011 StringInfoData buffer;
3012
3013 initStringInfo(&buffer);
3014
3015 switch (object->classId)
3016 {
3017 case RelationRelationId:
3018 if (object->objectSubId == 0)
3019 getRelationDescription(&buffer, object->objectId, missing_ok);
3020 else
3021 {
3022 /* column, not whole relation */
3023 StringInfoData rel;
3024 char *attname = get_attname(object->objectId,
3025 object->objectSubId,
3026 missing_ok);
3027
3028 if (!attname)
3029 break;
3030
3031 initStringInfo(&rel);
3032 getRelationDescription(&rel, object->objectId, missing_ok);
3033 /* translator: second %s is, e.g., "table %s" */
3034 appendStringInfo(&buffer, _("column %s of %s"),
3035 attname, rel.data);
3036 pfree(rel.data);
3037 }
3038 break;
3039
3041 {
3044 flags);
3045
3046 if (proname == NULL)
3047 break;
3048
3049 appendStringInfo(&buffer, _("function %s"), proname);
3050 break;
3051 }
3052
3053 case TypeRelationId:
3054 {
3056 char *typname = format_type_extended(object->objectId, -1,
3057 flags);
3058
3059 if (typname == NULL)
3060 break;
3061
3062 appendStringInfo(&buffer, _("type %s"), typname);
3063 break;
3064 }
3065
3066 case CastRelationId:
3067 {
3069 ScanKeyData skey[1];
3071 HeapTuple tup;
3073
3075
3076 ScanKeyInit(&skey[0],
3079 ObjectIdGetDatum(object->objectId));
3080
3082 NULL, 1, skey);
3083
3085
3086 if (!HeapTupleIsValid(tup))
3087 {
3088 if (!missing_ok)
3089 elog(ERROR, "could not find tuple for cast %u",
3090 object->objectId);
3091
3094 break;
3095 }
3096
3098
3099 appendStringInfo(&buffer, _("cast from %s to %s"),
3100 format_type_be(castForm->castsource),
3101 format_type_be(castForm->casttarget));
3102
3105 break;
3106 }
3107
3109 {
3112 char *nspname;
3113
3115 ObjectIdGetDatum(object->objectId));
3117 {
3118 if (!missing_ok)
3119 elog(ERROR, "cache lookup failed for collation %u",
3120 object->objectId);
3121 break;
3122 }
3123
3125
3126 /* Qualify the name if not visible in search path */
3127 if (CollationIsVisible(object->objectId))
3128 nspname = NULL;
3129 else
3130 nspname = get_namespace_name(coll->collnamespace);
3131
3132 appendStringInfo(&buffer, _("collation %s"),
3134 NameStr(coll->collname)));
3136 break;
3137 }
3138
3140 {
3143
3145 ObjectIdGetDatum(object->objectId));
3147 {
3148 if (!missing_ok)
3149 elog(ERROR, "cache lookup failed for constraint %u",
3150 object->objectId);
3151 break;
3152 }
3153
3155
3156 if (OidIsValid(con->conrelid))
3157 {
3158 StringInfoData rel;
3159
3160 initStringInfo(&rel);
3161 getRelationDescription(&rel, con->conrelid, false);
3162 /* translator: second %s is, e.g., "table %s" */
3163 appendStringInfo(&buffer, _("constraint %s on %s"),
3164 NameStr(con->conname), rel.data);
3165 pfree(rel.data);
3166 }
3167 else
3168 {
3169 appendStringInfo(&buffer, _("constraint %s"),
3170 NameStr(con->conname));
3171 }
3172
3174 break;
3175 }
3176
3178 {
3181 char *nspname;
3182
3184 ObjectIdGetDatum(object->objectId));
3186 {
3187 if (!missing_ok)
3188 elog(ERROR, "cache lookup failed for conversion %u",
3189 object->objectId);
3190 break;
3191 }
3192
3194
3195 /* Qualify the name if not visible in search path */
3196 if (ConversionIsVisible(object->objectId))
3197 nspname = NULL;
3198 else
3199 nspname = get_namespace_name(conv->connamespace);
3200
3201 appendStringInfo(&buffer, _("conversion %s"),
3203 NameStr(conv->conname)));
3205 break;
3206 }
3207
3209 {
3211
3213
3214 if (!OidIsValid(colobject.objectId))
3215 {
3216 if (!missing_ok)
3217 elog(ERROR, "could not find tuple for attrdef %u",
3218 object->objectId);
3219 break;
3220 }
3221
3222 /* translator: %s is typically "column %s of table %s" */
3223 appendStringInfo(&buffer, _("default value for %s"),
3225 break;
3226 }
3227
3228 case LanguageRelationId:
3229 {
3230 char *langname = get_language_name(object->objectId,
3231 missing_ok);
3232
3233 if (langname)
3234 appendStringInfo(&buffer, _("language %s"),
3235 get_language_name(object->objectId, false));
3236 break;
3237 }
3238
3240 if (!LargeObjectExists(object->objectId))
3241 break;
3242 appendStringInfo(&buffer, _("large object %u"),
3243 object->objectId);
3244 break;
3245
3246 case OperatorRelationId:
3247 {
3249 char *oprname = format_operator_extended(object->objectId,
3250 flags);
3251
3252 if (oprname == NULL)
3253 break;
3254
3255 appendStringInfo(&buffer, _("operator %s"), oprname);
3256 break;
3257 }
3258
3260 {
3265 char *nspname;
3266
3268 ObjectIdGetDatum(object->objectId));
3270 {
3271 if (!missing_ok)
3272 elog(ERROR, "cache lookup failed for opclass %u",
3273 object->objectId);
3274 break;
3275 }
3276
3278
3280 ObjectIdGetDatum(opcForm->opcmethod));
3281 if (!HeapTupleIsValid(amTup))
3282 elog(ERROR, "cache lookup failed for access method %u",
3283 opcForm->opcmethod);
3285
3286 /* Qualify the name if not visible in search path */
3287 if (OpclassIsVisible(object->objectId))
3288 nspname = NULL;
3289 else
3290 nspname = get_namespace_name(opcForm->opcnamespace);
3291
3292 appendStringInfo(&buffer, _("operator class %s for access method %s"),
3294 NameStr(opcForm->opcname)),
3295 NameStr(amForm->amname));
3296
3299 break;
3300 }
3301
3303 getOpFamilyDescription(&buffer, object->objectId, missing_ok);
3304 break;
3305
3307 {
3308 HeapTuple tup;
3309
3311 ObjectIdGetDatum(object->objectId));
3312 if (!HeapTupleIsValid(tup))
3313 {
3314 if (!missing_ok)
3315 elog(ERROR, "cache lookup failed for access method %u",
3316 object->objectId);
3317 break;
3318 }
3319
3320 appendStringInfo(&buffer, _("access method %s"),
3321 NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
3323 break;
3324 }
3325
3327 {
3329 HeapTuple tup;
3330 ScanKeyData skey[1];
3333 StringInfoData opfam;
3334
3337
3338 ScanKeyInit(&skey[0],
3341 ObjectIdGetDatum(object->objectId));
3342
3344 NULL, 1, skey);
3345
3347
3348 if (!HeapTupleIsValid(tup))
3349 {
3350 if (!missing_ok)
3351 elog(ERROR, "could not find tuple for amop entry %u",
3352 object->objectId);
3353
3356 break;
3357 }
3358
3360
3361 initStringInfo(&opfam);
3362 getOpFamilyDescription(&opfam, amopForm->amopfamily, false);
3363
3364 /*
3365 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3366 * completely if the type links are dangling, which is a form
3367 * of catalog corruption that could occur due to old bugs.
3368 */
3369
3370 /*------
3371 translator: %d is the operator strategy (a number), the
3372 first two %s's are data type names, the third %s is the
3373 description of the operator family, and the last %s is the
3374 textual form of the operator with arguments. */
3375 appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
3376 amopForm->amopstrategy,
3377 format_type_extended(amopForm->amoplefttype,
3379 format_type_extended(amopForm->amoprighttype,
3381 opfam.data,
3382 format_operator(amopForm->amopopr));
3383
3384 pfree(opfam.data);
3385
3388 break;
3389 }
3390
3392 {
3394 ScanKeyData skey[1];
3396 HeapTuple tup;
3398 StringInfoData opfam;
3399
3402
3403 ScanKeyInit(&skey[0],
3406 ObjectIdGetDatum(object->objectId));
3407
3409 NULL, 1, skey);
3410
3412
3413 if (!HeapTupleIsValid(tup))
3414 {
3415 if (!missing_ok)
3416 elog(ERROR, "could not find tuple for amproc entry %u",
3417 object->objectId);
3418
3421 break;
3422 }
3423
3425
3426 initStringInfo(&opfam);
3427 getOpFamilyDescription(&opfam, amprocForm->amprocfamily, false);
3428
3429 /*
3430 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3431 * completely if the type links are dangling, which is a form
3432 * of catalog corruption that could occur due to old bugs.
3433 */
3434
3435 /*------
3436 translator: %d is the function number, the first two %s's
3437 are data type names, the third %s is the description of the
3438 operator family, and the last %s is the textual form of the
3439 function with arguments. */
3440 appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
3441 amprocForm->amprocnum,
3442 format_type_extended(amprocForm->amproclefttype,
3444 format_type_extended(amprocForm->amprocrighttype,
3446 opfam.data,
3447 format_procedure(amprocForm->amproc));
3448
3449 pfree(opfam.data);
3450
3453 break;
3454 }
3455
3456 case RewriteRelationId:
3457 {
3459 ScanKeyData skey[1];
3461 HeapTuple tup;
3463 StringInfoData rel;
3464
3466
3467 ScanKeyInit(&skey[0],
3470 ObjectIdGetDatum(object->objectId));
3471
3473 NULL, 1, skey);
3474
3476
3477 if (!HeapTupleIsValid(tup))
3478 {
3479 if (!missing_ok)
3480 elog(ERROR, "could not find tuple for rule %u",
3481 object->objectId);
3482
3485 break;
3486 }
3487
3489
3490 initStringInfo(&rel);
3491 getRelationDescription(&rel, rule->ev_class, false);
3492
3493 /* translator: second %s is, e.g., "table %s" */
3494 appendStringInfo(&buffer, _("rule %s on %s"),
3495 NameStr(rule->rulename), rel.data);
3496 pfree(rel.data);
3499 break;
3500 }
3501
3502 case TriggerRelationId:
3503 {
3505 ScanKeyData skey[1];
3507 HeapTuple tup;
3509 StringInfoData rel;
3510
3512
3513 ScanKeyInit(&skey[0],
3516 ObjectIdGetDatum(object->objectId));
3517
3519 NULL, 1, skey);
3520
3522
3523 if (!HeapTupleIsValid(tup))
3524 {
3525 if (!missing_ok)
3526 elog(ERROR, "could not find tuple for trigger %u",
3527 object->objectId);
3528
3531 break;
3532 }
3533
3535
3536 initStringInfo(&rel);
3537 getRelationDescription(&rel, trig->tgrelid, false);
3538
3539 /* translator: second %s is, e.g., "table %s" */
3540 appendStringInfo(&buffer, _("trigger %s on %s"),
3541 NameStr(trig->tgname), rel.data);
3542 pfree(rel.data);
3545 break;
3546 }
3547
3549 {
3550 char *nspname;
3551
3552 nspname = get_namespace_name(object->objectId);
3553 if (!nspname)
3554 {
3555 if (!missing_ok)
3556 elog(ERROR, "cache lookup failed for namespace %u",
3557 object->objectId);
3558 break;
3559 }
3560 appendStringInfo(&buffer, _("schema %s"), nspname);
3561 break;
3562 }
3563
3565 {
3568 char *nspname;
3569
3571 ObjectIdGetDatum(object->objectId));
3573 {
3574 if (!missing_ok)
3575 elog(ERROR, "could not find tuple for statistics object %u",
3576 object->objectId);
3577 break;
3578 }
3579
3581
3582 /* Qualify the name if not visible in search path */
3583 if (StatisticsObjIsVisible(object->objectId))
3584 nspname = NULL;
3585 else
3586 nspname = get_namespace_name(stxForm->stxnamespace);
3587
3588 appendStringInfo(&buffer, _("statistics object %s"),
3590 NameStr(stxForm->stxname)));
3591
3593 break;
3594 }
3595
3596 case TSParserRelationId:
3597 {
3598 HeapTuple tup;
3600 char *nspname;
3601
3603 ObjectIdGetDatum(object->objectId));
3604 if (!HeapTupleIsValid(tup))
3605 {
3606 if (!missing_ok)
3607 elog(ERROR, "cache lookup failed for text search parser %u",
3608 object->objectId);
3609 break;
3610 }
3612
3613 /* Qualify the name if not visible in search path */
3614 if (TSParserIsVisible(object->objectId))
3615 nspname = NULL;
3616 else
3617 nspname = get_namespace_name(prsForm->prsnamespace);
3618
3619 appendStringInfo(&buffer, _("text search parser %s"),
3621 NameStr(prsForm->prsname)));
3623 break;
3624 }
3625
3627 {
3628 HeapTuple tup;
3630 char *nspname;
3631
3633 ObjectIdGetDatum(object->objectId));
3634 if (!HeapTupleIsValid(tup))
3635 {
3636 if (!missing_ok)
3637 elog(ERROR, "cache lookup failed for text search dictionary %u",
3638 object->objectId);
3639 break;
3640 }
3641
3643
3644 /* Qualify the name if not visible in search path */
3645 if (TSDictionaryIsVisible(object->objectId))
3646 nspname = NULL;
3647 else
3648 nspname = get_namespace_name(dictForm->dictnamespace);
3649
3650 appendStringInfo(&buffer, _("text search dictionary %s"),
3652 NameStr(dictForm->dictname)));
3654 break;
3655 }
3656
3658 {
3659 HeapTuple tup;
3661 char *nspname;
3662
3664 ObjectIdGetDatum(object->objectId));
3665 if (!HeapTupleIsValid(tup))
3666 {
3667 if (!missing_ok)
3668 elog(ERROR, "cache lookup failed for text search template %u",
3669 object->objectId);
3670 break;
3671 }
3672
3674
3675 /* Qualify the name if not visible in search path */
3676 if (TSTemplateIsVisible(object->objectId))
3677 nspname = NULL;
3678 else
3679 nspname = get_namespace_name(tmplForm->tmplnamespace);
3680
3681 appendStringInfo(&buffer, _("text search template %s"),
3683 NameStr(tmplForm->tmplname)));
3685 break;
3686 }
3687
3688 case TSConfigRelationId:
3689 {
3690 HeapTuple tup;
3692 char *nspname;
3693
3695 ObjectIdGetDatum(object->objectId));
3696 if (!HeapTupleIsValid(tup))
3697 {
3698 if (!missing_ok)
3699 elog(ERROR, "cache lookup failed for text search configuration %u",
3700 object->objectId);
3701 break;
3702 }
3703
3705
3706 /* Qualify the name if not visible in search path */
3707 if (TSConfigIsVisible(object->objectId))
3708 nspname = NULL;
3709 else
3710 nspname = get_namespace_name(cfgForm->cfgnamespace);
3711
3712 appendStringInfo(&buffer, _("text search configuration %s"),
3714 NameStr(cfgForm->cfgname)));
3716 break;
3717 }
3718
3719 case AuthIdRelationId:
3720 {
3721 char *username = GetUserNameFromId(object->objectId,
3722 missing_ok);
3723
3724 if (username)
3725 appendStringInfo(&buffer, _("role %s"), username);
3726 break;
3727 }
3728
3729 case AuthMemRelationId:
3730 {
3732 ScanKeyData skey[1];
3734 HeapTuple tup;
3736
3738
3739 ScanKeyInit(&skey[0],
3742 ObjectIdGetDatum(object->objectId));
3743
3745 NULL, 1, skey);
3746
3748
3749 if (!HeapTupleIsValid(tup))
3750 {
3751 if (!missing_ok)
3752 elog(ERROR, "could not find tuple for role membership %u",
3753 object->objectId);
3754
3757 break;
3758 }
3759
3761
3762 appendStringInfo(&buffer, _("membership of role %s in role %s"),
3763 GetUserNameFromId(amForm->member, false),
3764 GetUserNameFromId(amForm->roleid, false));
3765
3768 break;
3769 }
3770
3771 case DatabaseRelationId:
3772 {
3773 char *datname;
3774
3776 if (!datname)
3777 {
3778 if (!missing_ok)
3779 elog(ERROR, "cache lookup failed for database %u",
3780 object->objectId);
3781 break;
3782 }
3783 appendStringInfo(&buffer, _("database %s"), datname);
3784 break;
3785 }
3786
3788 {
3789 char *tblspace;
3790
3792 if (!tblspace)
3793 {
3794 if (!missing_ok)
3795 elog(ERROR, "cache lookup failed for tablespace %u",
3796 object->objectId);
3797 break;
3798 }
3799 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
3800 break;
3801 }
3802
3804 {
3806
3808 missing_ok);
3809 if (fdw)
3810 appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
3811 break;
3812 }
3813
3815 {
3817
3818 srv = GetForeignServerExtended(object->objectId, missing_ok);
3819 if (srv)
3820 appendStringInfo(&buffer, _("server %s"), srv->servername);
3821 break;
3822 }
3823
3825 {
3826 HeapTuple tup;
3827 Oid useid;
3828 char *usename;
3831
3833 ObjectIdGetDatum(object->objectId));
3834 if (!HeapTupleIsValid(tup))
3835 {
3836 if (!missing_ok)
3837 elog(ERROR, "cache lookup failed for user mapping %u",
3838 object->objectId);
3839 break;
3840 }
3841
3843 useid = umform->umuser;
3844 srv = GetForeignServer(umform->umserver);
3845
3847
3848 if (OidIsValid(useid))
3850 else
3851 usename = "public";
3852
3853 appendStringInfo(&buffer, _("user mapping for %s on server %s"), usename,
3854 srv->servername);
3855 break;
3856 }
3857
3859 {
3861 ScanKeyData skey[1];
3863 HeapTuple tup;
3865 char *rolename;
3866 char *nspname;
3867
3869
3870 ScanKeyInit(&skey[0],
3873 ObjectIdGetDatum(object->objectId));
3874
3876 true, NULL, 1, skey);
3877
3879
3880 if (!HeapTupleIsValid(tup))
3881 {
3882 if (!missing_ok)
3883 elog(ERROR, "could not find tuple for default ACL %u",
3884 object->objectId);
3885
3888 break;
3889 }
3890
3892
3893 rolename = GetUserNameFromId(defacl->defaclrole, false);
3894
3895 if (OidIsValid(defacl->defaclnamespace))
3896 nspname = get_namespace_name(defacl->defaclnamespace);
3897 else
3898 nspname = NULL;
3899
3900 switch (defacl->defaclobjtype)
3901 {
3902 case DEFACLOBJ_RELATION:
3903 if (nspname)
3904 appendStringInfo(&buffer,
3905 _("default privileges on new relations belonging to role %s in schema %s"),
3906 rolename, nspname);
3907 else
3908 appendStringInfo(&buffer,
3909 _("default privileges on new relations belonging to role %s"),
3910 rolename);
3911 break;
3912 case DEFACLOBJ_SEQUENCE:
3913 if (nspname)
3914 appendStringInfo(&buffer,
3915 _("default privileges on new sequences belonging to role %s in schema %s"),
3916 rolename, nspname);
3917 else
3918 appendStringInfo(&buffer,
3919 _("default privileges on new sequences belonging to role %s"),
3920 rolename);
3921 break;
3922 case DEFACLOBJ_FUNCTION:
3923 if (nspname)
3924 appendStringInfo(&buffer,
3925 _("default privileges on new functions belonging to role %s in schema %s"),
3926 rolename, nspname);
3927 else
3928 appendStringInfo(&buffer,
3929 _("default privileges on new functions belonging to role %s"),
3930 rolename);
3931 break;
3932 case DEFACLOBJ_TYPE:
3933 if (nspname)
3934 appendStringInfo(&buffer,
3935 _("default privileges on new types belonging to role %s in schema %s"),
3936 rolename, nspname);
3937 else
3938 appendStringInfo(&buffer,
3939 _("default privileges on new types belonging to role %s"),
3940 rolename);
3941 break;
3943 Assert(!nspname);
3944 appendStringInfo(&buffer,
3945 _("default privileges on new schemas belonging to role %s"),
3946 rolename);
3947 break;
3949 Assert(!nspname);
3950 appendStringInfo(&buffer,
3951 _("default privileges on new large objects belonging to role %s"),
3952 rolename);
3953 break;
3954 default:
3955 /* shouldn't get here */
3956 if (nspname)
3957 appendStringInfo(&buffer,
3958 _("default privileges belonging to role %s in schema %s"),
3959 rolename, nspname);
3960 else
3961 appendStringInfo(&buffer,
3962 _("default privileges belonging to role %s"),
3963 rolename);
3964 break;
3965 }
3966
3969 break;
3970 }
3971
3973 {
3974 char *extname;
3975
3976 extname = get_extension_name(object->objectId);
3977 if (!extname)
3978 {
3979 if (!missing_ok)
3980 elog(ERROR, "cache lookup failed for extension %u",
3981 object->objectId);
3982 break;
3983 }
3984 appendStringInfo(&buffer, _("extension %s"), extname);
3985 break;
3986 }
3987
3989 {
3990 HeapTuple tup;
3991
3993 ObjectIdGetDatum(object->objectId));
3994 if (!HeapTupleIsValid(tup))
3995 {
3996 if (!missing_ok)
3997 elog(ERROR, "cache lookup failed for event trigger %u",
3998 object->objectId);
3999 break;
4000 }
4001 appendStringInfo(&buffer, _("event trigger %s"),
4004 break;
4005 }
4006
4008 {
4009 HeapTuple tup;
4011 char *parname;
4012
4014 ObjectIdGetDatum(object->objectId));
4015 if (!HeapTupleIsValid(tup))
4016 {
4017 if (!missing_ok)
4018 elog(ERROR, "cache lookup failed for parameter ACL %u",
4019 object->objectId);
4020 break;
4021 }
4025 appendStringInfo(&buffer, _("parameter %s"), parname);
4027 break;
4028 }
4029
4030 case PolicyRelationId:
4031 {
4033 ScanKeyData skey[1];
4035 HeapTuple tuple;
4037 StringInfoData rel;
4038
4040
4041 ScanKeyInit(&skey[0],
4044 ObjectIdGetDatum(object->objectId));
4045
4047 true, NULL, 1, skey);
4048
4049 tuple = systable_getnext(sscan);
4050
4051 if (!HeapTupleIsValid(tuple))
4052 {
4053 if (!missing_ok)
4054 elog(ERROR, "could not find tuple for policy %u",
4055 object->objectId);
4056
4059 break;
4060 }
4061
4063
4064 initStringInfo(&rel);
4065 getRelationDescription(&rel, form_policy->polrelid, false);
4066
4067 /* translator: second %s is, e.g., "table %s" */
4068 appendStringInfo(&buffer, _("policy %s on %s"),
4069 NameStr(form_policy->polname), rel.data);
4070 pfree(rel.data);
4073 break;
4074 }
4075
4077 {
4078 HeapTuple tup;
4080
4082 if (!HeapTupleIsValid(tup))
4083 {
4084 if (!missing_ok)
4085 elog(ERROR, "cache lookup failed for property graph element %u",
4086 object->objectId);
4087 break;
4088 }
4089
4091
4092 if (pgeform->pgekind == PGEKIND_VERTEX)
4093 /* translator: followed by, e.g., "property graph %s" */
4094 appendStringInfo(&buffer, _("vertex %s of "), NameStr(pgeform->pgealias));
4095 else if (pgeform->pgekind == PGEKIND_EDGE)
4096 /* translator: followed by, e.g., "property graph %s" */
4097 appendStringInfo(&buffer, _("edge %s of "), NameStr(pgeform->pgealias));
4098 else
4099 appendStringInfo(&buffer, "??? element %s of ", NameStr(pgeform->pgealias));
4100 getRelationDescription(&buffer, pgeform->pgepgid, false);
4101
4103 break;
4104 }
4105
4107 {
4108 Relation rel;
4109 SysScanDesc scan;
4110 ScanKeyData key[1];
4111 HeapTuple tuple;
4114
4116 ScanKeyInit(&key[0],
4119 ObjectIdGetDatum(object->objectId));
4120
4122 tuple = systable_getnext(scan);
4123 if (!HeapTupleIsValid(tuple))
4124 {
4125 if (!missing_ok)
4126 elog(ERROR, "could not find tuple for element label %u", object->objectId);
4127
4128 systable_endscan(scan);
4130 break;
4131 }
4132
4134
4135 appendStringInfo(&buffer, _("label %s of "), get_propgraph_label_name(pgelform->pgellabelid));
4138
4139 systable_endscan(scan);
4141 break;
4142 }
4143
4145 {
4146 HeapTuple tuple;
4148
4149 tuple = SearchSysCache1(PROPGRAPHLABELOID, object->objectId);
4150 if (!HeapTupleIsValid(tuple))
4151 {
4152 if (!missing_ok)
4153 elog(ERROR, "could not find tuple for label %u", object->objectId);
4154 break;
4155 }
4156
4158
4159 /* translator: followed by, e.g., "property graph %s" */
4160 appendStringInfo(&buffer, _("label %s of "), NameStr(pglform->pgllabel));
4161 getRelationDescription(&buffer, pglform->pglpgid, false);
4162 ReleaseSysCache(tuple);
4163 break;
4164 }
4165
4167 {
4168 Relation rel;
4169 SysScanDesc scan;
4170 ScanKeyData key[1];
4171 HeapTuple tuple;
4174
4176 ScanKeyInit(&key[0],
4179 ObjectIdGetDatum(object->objectId));
4180
4182 tuple = systable_getnext(scan);
4183 if (!HeapTupleIsValid(tuple))
4184 {
4185 if (!missing_ok)
4186 elog(ERROR, "could not find tuple for label property %u", object->objectId);
4187
4188 systable_endscan(scan);
4190 break;
4191 }
4192
4194
4195 appendStringInfo(&buffer, _("property %s of "), get_propgraph_property_name(plpform->plppropid));
4198
4199 systable_endscan(scan);
4201 break;
4202 }
4203
4205 {
4206 HeapTuple tuple;
4208
4209 tuple = SearchSysCache1(PROPGRAPHPROPOID, object->objectId);
4210 if (!HeapTupleIsValid(tuple))
4211 {
4212 if (!missing_ok)
4213 elog(ERROR, "could not find tuple for property %u", object->objectId);
4214 break;
4215 }
4216
4218
4219 /* translator: followed by, e.g., "property graph %s" */
4220 appendStringInfo(&buffer, _("property %s of "), NameStr(pgpform->pgpname));
4221 getRelationDescription(&buffer, pgpform->pgppgid, false);
4222 ReleaseSysCache(tuple);
4223 break;
4224 }
4225
4227 {
4228 char *pubname = get_publication_name(object->objectId,
4229 missing_ok);
4230
4231 if (pubname)
4232 appendStringInfo(&buffer, _("publication %s"), pubname);
4233 break;
4234 }
4235
4237 {
4238 char *pubname;
4239 char *nspname;
4240
4241 if (!getPublicationSchemaInfo(object, missing_ok,
4242 &pubname, &nspname))
4243 break;
4244
4245 appendStringInfo(&buffer, _("publication of schema %s in publication %s"),
4246 nspname, pubname);
4247 pfree(pubname);
4248 pfree(nspname);
4249 break;
4250 }
4251
4253 {
4254 HeapTuple tup;
4255 char *pubname;
4257 StringInfoData rel;
4258
4260 ObjectIdGetDatum(object->objectId));
4261 if (!HeapTupleIsValid(tup))
4262 {
4263 if (!missing_ok)
4264 elog(ERROR, "cache lookup failed for publication table %u",
4265 object->objectId);
4266 break;
4267 }
4268
4270 pubname = get_publication_name(prform->prpubid, false);
4271
4272 initStringInfo(&rel);
4273 getRelationDescription(&rel, prform->prrelid, false);
4274
4275 /* translator: first %s is, e.g., "table %s" */
4276 appendStringInfo(&buffer, _("publication of %s in publication %s"),
4277 rel.data, pubname);
4278 pfree(rel.data);
4280 break;
4281 }
4282
4284 {
4285 char *subname = get_subscription_name(object->objectId,
4286 missing_ok);
4287
4288 if (subname)
4289 appendStringInfo(&buffer, _("subscription %s"), subname);
4290 break;
4291 }
4292
4294 {
4297
4299 ObjectIdGetDatum(object->objectId));
4301 {
4302 if (!missing_ok)
4303 elog(ERROR, "could not find tuple for transform %u",
4304 object->objectId);
4305 break;
4306 }
4307
4309
4310 appendStringInfo(&buffer, _("transform for %s language %s"),
4311 format_type_be(trfForm->trftype),
4312 get_language_name(trfForm->trflang, false));
4313
4315 break;
4316 }
4317
4318 default:
4319 elog(ERROR, "unsupported object class: %u", object->classId);
4320 }
4321
4322 /* an empty buffer is equivalent to no object found */
4323 if (buffer.len == 0)
4324 return NULL;
4325
4326 return buffer.data;
4327}
4328
4329/*
4330 * getObjectDescriptionOids: as above, except the object is specified by Oids
4331 */
4332char *
4334{
4335 ObjectAddress address;
4336
4337 address.classId = classid;
4338 address.objectId = objid;
4339 address.objectSubId = 0;
4340
4341 return getObjectDescription(&address, false);
4342}
4343
4344/*
4345 * subroutine for getObjectDescription: describe a relation
4346 *
4347 * The result is appended to "buffer".
4348 */
4349static void
4350getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok)
4351{
4354 char *nspname;
4355 char *relname;
4356
4358 ObjectIdGetDatum(relid));
4360 {
4361 if (!missing_ok)
4362 elog(ERROR, "cache lookup failed for relation %u", relid);
4363 return;
4364 }
4366
4367 /* Qualify the name if not visible in search path */
4368 if (RelationIsVisible(relid))
4369 nspname = NULL;
4370 else
4371 nspname = get_namespace_name(relForm->relnamespace);
4372
4373 relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
4374
4375 switch (relForm->relkind)
4376 {
4377 case RELKIND_RELATION:
4379 appendStringInfo(buffer, _("table %s"),
4380 relname);
4381 break;
4382 case RELKIND_INDEX:
4384 appendStringInfo(buffer, _("index %s"),
4385 relname);
4386 break;
4387 case RELKIND_SEQUENCE:
4388 appendStringInfo(buffer, _("sequence %s"),
4389 relname);
4390 break;
4391 case RELKIND_TOASTVALUE:
4392 appendStringInfo(buffer, _("toast table %s"),
4393 relname);
4394 break;
4395 case RELKIND_VIEW:
4396 appendStringInfo(buffer, _("view %s"),
4397 relname);
4398 break;
4399 case RELKIND_MATVIEW:
4400 appendStringInfo(buffer, _("materialized view %s"),
4401 relname);
4402 break;
4404 appendStringInfo(buffer, _("composite type %s"),
4405 relname);
4406 break;
4408 appendStringInfo(buffer, _("foreign table %s"),
4409 relname);
4410 break;
4411 case RELKIND_PROPGRAPH:
4412 appendStringInfo(buffer, _("property graph %s"),
4413 relname);
4414 break;
4415 default:
4416 /* shouldn't get here */
4417 appendStringInfo(buffer, _("relation %s"),
4418 relname);
4419 break;
4420 }
4421
4423}
4424
4425/*
4426 * subroutine for getObjectDescription: describe an operator family
4427 */
4428static void
4430{
4435 char *nspname;
4436
4439 {
4440 if (!missing_ok)
4441 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
4442 return;
4443 }
4445
4447 if (!HeapTupleIsValid(amTup))
4448 elog(ERROR, "cache lookup failed for access method %u",
4449 opfForm->opfmethod);
4451
4452 /* Qualify the name if not visible in search path */
4454 nspname = NULL;
4455 else
4456 nspname = get_namespace_name(opfForm->opfnamespace);
4457
4458 appendStringInfo(buffer, _("operator family %s for access method %s"),
4460 NameStr(opfForm->opfname)),
4461 NameStr(amForm->amname));
4462
4465}
4466
4467/*
4468 * SQL-level callable version of getObjectDescription
4469 */
4470Datum
4472{
4473 Oid classid = PG_GETARG_OID(0);
4474 Oid objid = PG_GETARG_OID(1);
4475 int32 objsubid = PG_GETARG_INT32(2);
4476 char *description;
4477 ObjectAddress address;
4478
4479 /* for "pinned" items in pg_depend, return null */
4480 if (!OidIsValid(classid) && !OidIsValid(objid))
4482
4483 address.classId = classid;
4484 address.objectId = objid;
4485 address.objectSubId = objsubid;
4486
4487 description = getObjectDescription(&address, true);
4488
4489 if (description == NULL)
4491
4493}
4494
4495/*
4496 * SQL-level callable function to obtain object type + identity
4497 */
4498Datum
4500{
4501 Oid classid = PG_GETARG_OID(0);
4502 Oid objid = PG_GETARG_OID(1);
4503 int32 objsubid = PG_GETARG_INT32(2);
4505 const char *objname = NULL;
4506 char *objidentity;
4507 ObjectAddress address;
4508 Datum values[4];
4509 bool nulls[4];
4510 TupleDesc tupdesc;
4511 HeapTuple htup;
4512
4513 address.classId = classid;
4514 address.objectId = objid;
4515 address.objectSubId = objsubid;
4516
4517 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4518 elog(ERROR, "return type must be a row type");
4519
4520 if (is_objectclass_supported(address.classId))
4521 {
4524
4527 address.objectId);
4528 if (objtup != NULL)
4529 {
4530 bool isnull;
4533
4536 {
4538 RelationGetDescr(catalog), &isnull));
4539 if (isnull)
4540 elog(ERROR, "invalid null namespace in object %u/%u/%d",
4541 address.classId, address.objectId, address.objectSubId);
4542 }
4543
4544 /*
4545 * We only return the object name if it can be used (together with
4546 * the schema name, if any) as a unique identifier.
4547 */
4549 {
4552 {
4554
4556 RelationGetDescr(catalog), &isnull);
4557 if (isnull)
4558 elog(ERROR, "invalid null name in object %u/%u/%d",
4559 address.classId, address.objectId, address.objectSubId);
4561 }
4562 }
4563 }
4564
4566 }
4567
4568 /* object type, which can never be NULL */
4570 nulls[0] = false;
4571
4572 /*
4573 * Before doing anything, extract the object identity. If the identity
4574 * could not be found, set all the fields except the object type to NULL.
4575 */
4576 objidentity = getObjectIdentity(&address, true);
4577
4578 /* schema name */
4579 if (OidIsValid(schema_oid) && objidentity)
4580 {
4581 const char *schema = quote_identifier(get_namespace_name(schema_oid));
4582
4583 values[1] = CStringGetTextDatum(schema);
4584 nulls[1] = false;
4585 }
4586 else
4587 nulls[1] = true;
4588
4589 /* object name */
4590 if (objname && objidentity)
4591 {
4592 values[2] = CStringGetTextDatum(objname);
4593 nulls[2] = false;
4594 }
4595 else
4596 nulls[2] = true;
4597
4598 /* object identity */
4599 if (objidentity)
4600 {
4601 values[3] = CStringGetTextDatum(objidentity);
4602 nulls[3] = false;
4603 }
4604 else
4605 nulls[3] = true;
4606
4607 htup = heap_form_tuple(tupdesc, values, nulls);
4608
4610}
4611
4612/*
4613 * SQL-level callable function to obtain object type + identity
4614 */
4615Datum
4617{
4618 Oid classid = PG_GETARG_OID(0);
4619 Oid objid = PG_GETARG_OID(1);
4620 int32 objsubid = PG_GETARG_INT32(2);
4621 ObjectAddress address;
4622 char *identity;
4623 List *names;
4624 List *args;
4625 Datum values[3];
4626 bool nulls[3];
4627 TupleDesc tupdesc;
4628 HeapTuple htup;
4629
4630 address.classId = classid;
4631 address.objectId = objid;
4632 address.objectSubId = objsubid;
4633
4634 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4635 elog(ERROR, "return type must be a row type");
4636
4637 /* object type, which can never be NULL */
4639 nulls[0] = false;
4640
4641 /* object identity */
4642 identity = getObjectIdentityParts(&address, &names, &args, true);
4643 if (identity == NULL)
4644 {
4645 nulls[1] = true;
4646 nulls[2] = true;
4647 }
4648 else
4649 {
4650 pfree(identity);
4651
4652 /* object_names */
4653 if (names != NIL)
4655 else
4657 nulls[1] = false;
4658
4659 /* object_args */
4660 if (args)
4662 else
4664 nulls[2] = false;
4665 }
4666
4667 htup = heap_form_tuple(tupdesc, values, nulls);
4668
4670}
4671
4672/*
4673 * SQL-level callable function to obtain the ACL of a specified object, given
4674 * its catalog OID, object OID and sub-object ID.
4675 */
4676Datum
4678{
4679 Oid classId = PG_GETARG_OID(0);
4680 Oid objectId = PG_GETARG_OID(1);
4681 int32 objsubid = PG_GETARG_INT32(2);
4682 Oid catalogId;
4684 Datum datum;
4685 bool isnull;
4686 HeapTuple tup;
4687
4688 /* for "pinned" items in pg_depend, return null */
4689 if (!OidIsValid(classId) && !OidIsValid(objectId))
4691
4692 /* for large objects, the catalog to look at is pg_largeobject_metadata */
4693 catalogId = (classId == LargeObjectRelationId) ?
4695 Anum_acl = get_object_attnum_acl(catalogId);
4696
4697 /* return NULL if no ACL field for this catalog */
4700
4701 /*
4702 * If dealing with a relation's attribute (objsubid is set), the ACL is
4703 * retrieved from pg_attribute.
4704 */
4705 if (classId == RelationRelationId && objsubid != 0)
4706 {
4707 AttrNumber attnum = (AttrNumber) objsubid;
4708
4709 tup = SearchSysCacheCopyAttNum(objectId, attnum);
4710
4711 if (!HeapTupleIsValid(tup))
4713
4715 &isnull);
4716 }
4717 else
4718 {
4719 Relation rel;
4720
4721 rel = table_open(catalogId, AccessShareLock);
4722
4724 objectId);
4725 if (!HeapTupleIsValid(tup))
4726 {
4729 }
4730
4731 datum = heap_getattr(tup, Anum_acl, RelationGetDescr(rel), &isnull);
4733 }
4734
4735 if (isnull)
4737
4738 PG_RETURN_DATUM(datum);
4739}
4740
4741/*
4742 * Return a palloc'ed string that describes the type of object that the
4743 * passed address is for.
4744 *
4745 * Keep ObjectTypeMap in sync with this.
4746 */
4747char *
4748getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
4749{
4750 StringInfoData buffer;
4751
4752 initStringInfo(&buffer);
4753
4754 switch (object->classId)
4755 {
4756 case RelationRelationId:
4757 getRelationTypeDescription(&buffer, object->objectId,
4758 object->objectSubId,
4759 missing_ok);
4760 break;
4761
4763 getProcedureTypeDescription(&buffer, object->objectId,
4764 missing_ok);
4765 break;
4766
4767 case TypeRelationId:
4768 appendStringInfoString(&buffer, "type");
4769 break;
4770
4771 case CastRelationId:
4772 appendStringInfoString(&buffer, "cast");
4773 break;
4774
4776 appendStringInfoString(&buffer, "collation");
4777 break;
4778
4780 getConstraintTypeDescription(&buffer, object->objectId,
4781 missing_ok);
4782 break;
4783
4785 appendStringInfoString(&buffer, "conversion");
4786 break;
4787
4789 appendStringInfoString(&buffer, "default value");
4790 break;
4791
4792 case LanguageRelationId:
4793 appendStringInfoString(&buffer, "language");
4794 break;
4795
4797 appendStringInfoString(&buffer, "large object");
4798 break;
4799
4800 case OperatorRelationId:
4801 appendStringInfoString(&buffer, "operator");
4802 break;
4803
4805 appendStringInfoString(&buffer, "operator class");
4806 break;
4807
4809 appendStringInfoString(&buffer, "operator family");
4810 break;
4811
4813 appendStringInfoString(&buffer, "access method");
4814 break;
4815
4817 appendStringInfoString(&buffer, "operator of access method");
4818 break;
4819
4821 appendStringInfoString(&buffer, "function of access method");
4822 break;
4823
4824 case RewriteRelationId:
4825 appendStringInfoString(&buffer, "rule");
4826 break;
4827
4828 case TriggerRelationId:
4829 appendStringInfoString(&buffer, "trigger");
4830 break;
4831
4833 appendStringInfoString(&buffer, "schema");
4834 break;
4835
4837 appendStringInfoString(&buffer, "statistics object");
4838 break;
4839
4840 case TSParserRelationId:
4841 appendStringInfoString(&buffer, "text search parser");
4842 break;
4843
4845 appendStringInfoString(&buffer, "text search dictionary");
4846 break;
4847
4849 appendStringInfoString(&buffer, "text search template");
4850 break;
4851
4852 case TSConfigRelationId:
4853 appendStringInfoString(&buffer, "text search configuration");
4854 break;
4855
4856 case AuthIdRelationId:
4857 appendStringInfoString(&buffer, "role");
4858 break;
4859
4860 case AuthMemRelationId:
4861 appendStringInfoString(&buffer, "role membership");
4862 break;
4863
4864 case DatabaseRelationId:
4865 appendStringInfoString(&buffer, "database");
4866 break;
4867
4869 appendStringInfoString(&buffer, "tablespace");
4870 break;
4871
4873 appendStringInfoString(&buffer, "foreign-data wrapper");
4874 break;
4875
4877 appendStringInfoString(&buffer, "server");
4878 break;
4879
4881 appendStringInfoString(&buffer, "user mapping");
4882 break;
4883
4885 appendStringInfoString(&buffer, "default acl");
4886 break;
4887
4889 appendStringInfoString(&buffer, "extension");
4890 break;
4891
4893 appendStringInfoString(&buffer, "event trigger");
4894 break;
4895
4897 appendStringInfoString(&buffer, "parameter ACL");
4898 break;
4899
4900 case PolicyRelationId:
4901 appendStringInfoString(&buffer, "policy");
4902 break;
4903
4905 appendStringInfoString(&buffer, "property graph element");
4906 break;
4907
4909 appendStringInfoString(&buffer, "property graph label");
4910 break;
4911
4913 appendStringInfoString(&buffer, "property graph property");
4914 break;
4915
4917 appendStringInfoString(&buffer, "publication");
4918 break;
4919
4921 appendStringInfoString(&buffer, "publication namespace");
4922 break;
4923
4925 appendStringInfoString(&buffer, "publication relation");
4926 break;
4927
4929 appendStringInfoString(&buffer, "subscription");
4930 break;
4931
4933 appendStringInfoString(&buffer, "transform");
4934 break;
4935
4936 default:
4937 elog(ERROR, "unsupported object class: %u", object->classId);
4938 }
4939
4940 /* the result can never be empty */
4941 Assert(buffer.len > 0);
4942
4943 return buffer.data;
4944}
4945
4946/*
4947 * subroutine for getObjectTypeDescription: describe a relation type
4948 */
4949static void
4951 bool missing_ok)
4952{
4955
4957 ObjectIdGetDatum(relid));
4959 {
4960 if (!missing_ok)
4961 elog(ERROR, "cache lookup failed for relation %u", relid);
4962
4963 /* fallback to "relation" for an undefined object */
4964 appendStringInfoString(buffer, "relation");
4965 return;
4966 }
4968
4969 switch (relForm->relkind)
4970 {
4971 case RELKIND_RELATION:
4973 appendStringInfoString(buffer, "table");
4974 break;
4975 case RELKIND_INDEX:
4977 appendStringInfoString(buffer, "index");
4978 break;
4979 case RELKIND_SEQUENCE:
4980 appendStringInfoString(buffer, "sequence");
4981 break;
4982 case RELKIND_TOASTVALUE:
4983 appendStringInfoString(buffer, "toast table");
4984 break;
4985 case RELKIND_VIEW:
4986 appendStringInfoString(buffer, "view");
4987 break;
4988 case RELKIND_MATVIEW:
4989 appendStringInfoString(buffer, "materialized view");
4990 break;
4992 appendStringInfoString(buffer, "composite type");
4993 break;
4995 appendStringInfoString(buffer, "foreign table");
4996 break;
4997 case RELKIND_PROPGRAPH:
4998 appendStringInfoString(buffer, "property graph");
4999 break;
5000 default:
5001 /* shouldn't get here */
5002 appendStringInfoString(buffer, "relation");
5003 break;
5004 }
5005
5006 if (objectSubId != 0)
5007 appendStringInfoString(buffer, " column");
5008
5010}
5011
5012/*
5013 * subroutine for getObjectTypeDescription: describe a constraint type
5014 */
5015static void
5017{
5021
5024 constroid);
5026 {
5027 if (!missing_ok)
5028 elog(ERROR, "cache lookup failed for constraint %u", constroid);
5029
5031
5032 /* fallback to "constraint" for an undefined object */
5033 appendStringInfoString(buffer, "constraint");
5034 return;
5035 }
5036
5038
5039 if (OidIsValid(constrForm->conrelid))
5040 appendStringInfoString(buffer, "table constraint");
5041 else if (OidIsValid(constrForm->contypid))
5042 appendStringInfoString(buffer, "domain constraint");
5043 else
5044 elog(ERROR, "invalid constraint %u", constrForm->oid);
5045
5047}
5048
5049/*
5050 * subroutine for getObjectTypeDescription: describe a procedure type
5051 */
5052static void
5054 bool missing_ok)
5055{
5058
5060 ObjectIdGetDatum(procid));
5062 {
5063 if (!missing_ok)
5064 elog(ERROR, "cache lookup failed for procedure %u", procid);
5065
5066 /* fallback to "procedure" for an undefined object */
5067 appendStringInfoString(buffer, "routine");
5068 return;
5069 }
5071
5072 if (procForm->prokind == PROKIND_AGGREGATE)
5073 appendStringInfoString(buffer, "aggregate");
5074 else if (procForm->prokind == PROKIND_PROCEDURE)
5075 appendStringInfoString(buffer, "procedure");
5076 else /* function or window function */
5077 appendStringInfoString(buffer, "function");
5078
5080}
5081
5082/*
5083 * Obtain a given object's identity, as a palloc'ed string.
5084 *
5085 * This is for machine consumption, so it's not translated. All elements are
5086 * schema-qualified when appropriate. Returns NULL if the object could not
5087 * be found.
5088 */
5089char *
5090getObjectIdentity(const ObjectAddress *object, bool missing_ok)
5091{
5092 return getObjectIdentityParts(object, NULL, NULL, missing_ok);
5093}
5094
5095/*
5096 * As above, but more detailed.
5097 *
5098 * There are two sets of return values: the identity itself as a palloc'd
5099 * string is returned. objname and objargs, if not NULL, are output parameters
5100 * that receive lists of C-strings that are useful to give back to
5101 * get_object_address() to reconstruct the ObjectAddress. Returns NULL if
5102 * the object could not be found.
5103 */
5104char *
5106 List **objname, List **objargs,
5107 bool missing_ok)
5108{
5109 StringInfoData buffer;
5110
5111 initStringInfo(&buffer);
5112
5113 /*
5114 * Make sure that both objname and objargs were passed, or none was; and
5115 * initialize them to empty lists. For objname this is useless because it
5116 * will be initialized in all cases inside the switch; but we do it anyway
5117 * so that we can test below that no branch leaves it unset.
5118 */
5119 Assert((objname != NULL) == (objargs != NULL));
5120 if (objname)
5121 {
5122 *objname = NIL;
5123 *objargs = NIL;
5124 }
5125
5126 switch (object->classId)
5127 {
5128 case RelationRelationId:
5129 {
5130 char *attr = NULL;
5131
5132 /*
5133 * Check for the attribute first, so as if it is missing we
5134 * can skip the entire relation description.
5135 */
5136 if (object->objectSubId != 0)
5137 {
5138 attr = get_attname(object->objectId,
5139 object->objectSubId,
5140 missing_ok);
5141
5142 if (missing_ok && attr == NULL)
5143 break;
5144 }
5145
5146 getRelationIdentity(&buffer, object->objectId, objname,
5147 missing_ok);
5148 if (objname && *objname == NIL)
5149 break;
5150
5151 if (attr)
5152 {
5153 appendStringInfo(&buffer, ".%s",
5154 quote_identifier(attr));
5155 if (objname)
5156 *objname = lappend(*objname, attr);
5157 }
5158 }
5159 break;
5160
5162 {
5165 flags);
5166
5167 if (proname == NULL)
5168 break;
5169
5171 if (objname)
5172 format_procedure_parts(object->objectId, objname, objargs,
5173 missing_ok);
5174 break;
5175 }
5176
5177 case TypeRelationId:
5178 {
5180 char *typeout;
5181
5182 typeout = format_type_extended(object->objectId, -1, flags);
5183
5184 if (typeout == NULL)
5185 break;
5186
5188 if (objname)
5189 *objname = list_make1(typeout);
5190 }
5191 break;
5192
5193 case CastRelationId:
5194 {
5196 HeapTuple tup;
5198
5200
5202 object->objectId);
5203
5204 if (!HeapTupleIsValid(tup))
5205 {
5206 if (!missing_ok)
5207 elog(ERROR, "could not find tuple for cast %u",
5208 object->objectId);
5209
5211 break;
5212 }
5213
5215
5216 appendStringInfo(&buffer, "(%s AS %s)",
5218 format_type_be_qualified(castForm->casttarget));
5219
5220 if (objname)
5221 {
5222 *objname = list_make1(format_type_be_qualified(castForm->castsource));
5223 *objargs = list_make1(format_type_be_qualified(castForm->casttarget));
5224 }
5225
5227 break;
5228 }
5229
5231 {
5234 char *schema;
5235
5237 ObjectIdGetDatum(object->objectId));
5239 {
5240 if (!missing_ok)
5241 elog(ERROR, "cache lookup failed for collation %u",
5242 object->objectId);
5243 break;
5244 }
5246 schema = get_namespace_name_or_temp(coll->collnamespace);
5247 appendStringInfoString(&buffer,
5249 NameStr(coll->collname)));
5250 if (objname)
5251 *objname = list_make2(schema,
5252 pstrdup(NameStr(coll->collname)));
5254 break;
5255 }
5256
5258 {
5261
5263 ObjectIdGetDatum(object->objectId));
5265 {
5266 if (!missing_ok)
5267 elog(ERROR, "cache lookup failed for constraint %u",
5268 object->objectId);
5269 break;
5270 }
5272
5273 if (OidIsValid(con->conrelid))
5274 {
5275 appendStringInfo(&buffer, "%s on ",
5276 quote_identifier(NameStr(con->conname)));
5277 getRelationIdentity(&buffer, con->conrelid, objname,
5278 false);
5279 if (objname)
5280 *objname = lappend(*objname, pstrdup(NameStr(con->conname)));
5281 }
5282 else
5283 {
5284 ObjectAddress domain;
5285
5286 Assert(OidIsValid(con->contypid));
5287 domain.classId = TypeRelationId;
5288 domain.objectId = con->contypid;
5289 domain.objectSubId = 0;
5290
5291 appendStringInfo(&buffer, "%s on %s",
5292 quote_identifier(NameStr(con->conname)),
5293 getObjectIdentityParts(&domain, objname,
5294 objargs, false));
5295
5296 if (objname)
5297 *objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
5298 }
5299
5301 break;
5302 }
5303
5305 {
5308 char *schema;
5309
5311 ObjectIdGetDatum(object->objectId));
5313 {
5314 if (!missing_ok)
5315 elog(ERROR, "cache lookup failed for conversion %u",
5316 object->objectId);
5317 break;
5318 }
5320 schema = get_namespace_name_or_temp(conForm->connamespace);
5321 appendStringInfoString(&buffer,
5323 NameStr(conForm->conname)));
5324 if (objname)
5325 *objname = list_make2(schema,
5326 pstrdup(NameStr(conForm->conname)));
5328 break;
5329 }
5330
5332 {
5334
5336
5337 if (!OidIsValid(colobject.objectId))
5338 {
5339 if (!missing_ok)
5340 elog(ERROR, "could not find tuple for attrdef %u",
5341 object->objectId);
5342 break;
5343 }
5344
5345 appendStringInfo(&buffer, "for %s",
5347 objname, objargs,
5348 false));
5349 break;
5350 }
5351
5352 case LanguageRelationId:
5353 {
5356
5358 ObjectIdGetDatum(object->objectId));
5360 {
5361 if (!missing_ok)
5362 elog(ERROR, "cache lookup failed for language %u",
5363 object->objectId);
5364 break;
5365 }
5367 appendStringInfoString(&buffer,
5368 quote_identifier(NameStr(langForm->lanname)));
5369 if (objname)
5370 *objname = list_make1(pstrdup(NameStr(langForm->lanname)));
5372 break;
5373 }
5374
5376 if (!LargeObjectExists(object->objectId))
5377 break;
5378 appendStringInfo(&buffer, "%u",
5379 object->objectId);
5380 if (objname)
5381 *objname = list_make1(psprintf("%u", object->objectId));
5382 break;
5383
5384 case OperatorRelationId:
5385 {
5387 char *oprname = format_operator_extended(object->objectId,
5388 flags);
5389
5390 if (oprname == NULL)
5391 break;
5392
5393 appendStringInfoString(&buffer, oprname);
5394 if (objname)
5395 format_operator_parts(object->objectId, objname, objargs, missing_ok);
5396 break;
5397 }
5398
5400 {
5405 char *schema;
5406
5408 ObjectIdGetDatum(object->objectId));
5410 {
5411 if (!missing_ok)
5412 elog(ERROR, "cache lookup failed for opclass %u",
5413 object->objectId);
5414 break;
5415 }
5417 schema = get_namespace_name_or_temp(opcForm->opcnamespace);
5418
5420 ObjectIdGetDatum(opcForm->opcmethod));
5421 if (!HeapTupleIsValid(amTup))
5422 elog(ERROR, "cache lookup failed for access method %u",
5423 opcForm->opcmethod);
5425
5426 appendStringInfo(&buffer, "%s USING %s",
5428 NameStr(opcForm->opcname)),
5429 quote_identifier(NameStr(amForm->amname)));
5430 if (objname)
5431 *objname = list_make3(pstrdup(NameStr(amForm->amname)),
5432 schema,
5433 pstrdup(NameStr(opcForm->opcname)));
5434
5437 break;
5438 }
5439
5441 getOpFamilyIdentity(&buffer, object->objectId, objname,
5442 missing_ok);
5443 break;
5444
5446 {
5447 char *amname;
5448
5449 amname = get_am_name(object->objectId);
5450 if (!amname)
5451 {
5452 if (!missing_ok)
5453 elog(ERROR, "cache lookup failed for access method %u",
5454 object->objectId);
5455 break;
5456 }
5457 appendStringInfoString(&buffer, quote_identifier(amname));
5458 if (objname)
5459 *objname = list_make1(amname);
5460 }
5461 break;
5462
5464 {
5466 HeapTuple tup;
5467 ScanKeyData skey[1];
5470 StringInfoData opfam;
5471 char *ltype;
5472 char *rtype;
5473
5476
5477 ScanKeyInit(&skey[0],
5480 ObjectIdGetDatum(object->objectId));
5481
5483 NULL, 1, skey);
5484
5486
5487 if (!HeapTupleIsValid(tup))
5488 {
5489 if (!missing_ok)
5490 elog(ERROR, "could not find tuple for amop entry %u",
5491 object->objectId);
5492
5495 break;
5496 }
5497
5499
5500 initStringInfo(&opfam);
5501 getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname,
5502 false);
5503
5504 ltype = format_type_be_qualified(amopForm->amoplefttype);
5505 rtype = format_type_be_qualified(amopForm->amoprighttype);
5506
5507 if (objname)
5508 {
5509 *objname = lappend(*objname,
5510 psprintf("%d", amopForm->amopstrategy));
5511 *objargs = list_make2(ltype, rtype);
5512 }
5513
5514 appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
5515 amopForm->amopstrategy,
5516 ltype, rtype, opfam.data);
5517
5518 pfree(opfam.data);
5519
5522 break;
5523 }
5524
5526 {
5528 ScanKeyData skey[1];
5530 HeapTuple tup;
5532 StringInfoData opfam;
5533 char *ltype;
5534 char *rtype;
5535
5538
5539 ScanKeyInit(&skey[0],
5542 ObjectIdGetDatum(object->objectId));
5543
5545 NULL, 1, skey);
5546
5548
5549 if (!HeapTupleIsValid(tup))
5550 {
5551 if (!missing_ok)
5552 elog(ERROR, "could not find tuple for amproc entry %u",
5553 object->objectId);
5554
5557 break;
5558 }
5559
5561
5562 initStringInfo(&opfam);
5563 getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname,
5564 false);
5565
5566 ltype = format_type_be_qualified(amprocForm->amproclefttype);
5567 rtype = format_type_be_qualified(amprocForm->amprocrighttype);
5568
5569 if (objname)
5570 {
5571 *objname = lappend(*objname,
5572 psprintf("%d", amprocForm->amprocnum));
5573 *objargs = list_make2(ltype, rtype);
5574 }
5575
5576 appendStringInfo(&buffer, "function %d (%s, %s) of %s",
5577 amprocForm->amprocnum,
5578 ltype, rtype, opfam.data);
5579
5580 pfree(opfam.data);
5581
5584 break;
5585 }
5586
5587 case RewriteRelationId:
5588 {
5590 HeapTuple tup;
5592
5594
5596 object->objectId);
5597
5598 if (!HeapTupleIsValid(tup))
5599 {
5600 if (!missing_ok)
5601 elog(ERROR, "could not find tuple for rule %u",
5602 object->objectId);
5603
5605 break;
5606 }
5607
5609
5610 appendStringInfo(&buffer, "%s on ",
5611 quote_identifier(NameStr(rule->rulename)));
5612 getRelationIdentity(&buffer, rule->ev_class, objname, false);
5613 if (objname)
5614 *objname = lappend(*objname, pstrdup(NameStr(rule->rulename)));
5615
5617 break;
5618 }
5619
5620 case TriggerRelationId:
5621 {
5623 HeapTuple tup;
5625
5627
5629 object->objectId);
5630
5631 if (!HeapTupleIsValid(tup))
5632 {
5633 if (!missing_ok)
5634 elog(ERROR, "could not find tuple for trigger %u",
5635 object->objectId);
5636
5638 break;
5639 }
5640
5642
5643 appendStringInfo(&buffer, "%s on ",
5644 quote_identifier(NameStr(trig->tgname)));
5645 getRelationIdentity(&buffer, trig->tgrelid, objname, false);
5646 if (objname)
5647 *objname = lappend(*objname, pstrdup(NameStr(trig->tgname)));
5648
5650 break;
5651 }
5652
5654 {
5655 char *nspname;
5656
5657 nspname = get_namespace_name_or_temp(object->objectId);
5658 if (!nspname)
5659 {
5660 if (!missing_ok)
5661 elog(ERROR, "cache lookup failed for namespace %u",
5662 object->objectId);
5663 break;
5664 }
5665 appendStringInfoString(&buffer,
5666 quote_identifier(nspname));
5667 if (objname)
5668 *objname = list_make1(nspname);
5669 break;
5670 }
5671
5673 {
5674 HeapTuple tup;
5676 char *schema;
5677
5679 ObjectIdGetDatum(object->objectId));
5680 if (!HeapTupleIsValid(tup))
5681 {
5682 if (!missing_ok)
5683 elog(ERROR, "cache lookup failed for statistics object %u",
5684 object->objectId);
5685 break;
5686 }
5688 schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
5689 appendStringInfoString(&buffer,
5691 NameStr(formStatistic->stxname)));
5692 if (objname)
5693 *objname = list_make2(schema,
5694 pstrdup(NameStr(formStatistic->stxname)));
5696 }
5697 break;
5698
5699 case TSParserRelationId:
5700 {
5701 HeapTuple tup;
5703 char *schema;
5704
5706 ObjectIdGetDatum(object->objectId));
5707 if (!HeapTupleIsValid(tup))
5708 {
5709 if (!missing_ok)
5710 elog(ERROR, "cache lookup failed for text search parser %u",
5711 object->objectId);
5712 break;
5713 }
5715 schema = get_namespace_name_or_temp(formParser->prsnamespace);
5716 appendStringInfoString(&buffer,
5718 NameStr(formParser->prsname)));
5719 if (objname)
5720 *objname = list_make2(schema,
5721 pstrdup(NameStr(formParser->prsname)));
5723 break;
5724 }
5725
5727 {
5728 HeapTuple tup;
5730 char *schema;
5731
5733 ObjectIdGetDatum(object->objectId));
5734 if (!HeapTupleIsValid(tup))
5735 {
5736 if (!missing_ok)
5737 elog(ERROR, "cache lookup failed for text search dictionary %u",
5738 object->objectId);
5739 break;
5740 }
5742 schema = get_namespace_name_or_temp(formDict->dictnamespace);
5743 appendStringInfoString(&buffer,
5745 NameStr(formDict->dictname)));
5746 if (objname)
5747 *objname = list_make2(schema,
5748 pstrdup(NameStr(formDict->dictname)));
5750 break;
5751 }
5752
5754 {
5755 HeapTuple tup;
5757 char *schema;
5758
5760 ObjectIdGetDatum(object->objectId));
5761 if (!HeapTupleIsValid(tup))
5762 {
5763 if (!missing_ok)
5764 elog(ERROR, "cache lookup failed for text search template %u",
5765 object->objectId);
5766 break;
5767 }
5769 schema = get_namespace_name_or_temp(formTmpl->tmplnamespace);
5770 appendStringInfoString(&buffer,
5772 NameStr(formTmpl->tmplname)));
5773 if (objname)
5774 *objname = list_make2(schema,
5775 pstrdup(NameStr(formTmpl->tmplname)));
5777 break;
5778 }
5779
5780 case TSConfigRelationId:
5781 {
5782 HeapTuple tup;
5784 char *schema;
5785
5787 ObjectIdGetDatum(object->objectId));
5788 if (!HeapTupleIsValid(tup))
5789 {
5790 if (!missing_ok)
5791 elog(ERROR, "cache lookup failed for text search configuration %u",
5792 object->objectId);
5793 break;
5794 }
5796 schema = get_namespace_name_or_temp(formCfg->cfgnamespace);
5797 appendStringInfoString(&buffer,
5799 NameStr(formCfg->cfgname)));
5800 if (objname)
5801 *objname = list_make2(schema,
5802 pstrdup(NameStr(formCfg->cfgname)));
5804 break;
5805 }
5806
5807 case AuthIdRelationId:
5808 {
5809 char *username;
5810
5811 username = GetUserNameFromId(object->objectId, missing_ok);
5812 if (!username)
5813 break;
5814 if (objname)
5815 *objname = list_make1(username);
5816 appendStringInfoString(&buffer,
5818 break;
5819 }
5820
5821 case AuthMemRelationId:
5822 {
5824 ScanKeyData skey[1];
5826 HeapTuple tup;
5828
5831
5832 ScanKeyInit(&skey[0],
5835 ObjectIdGetDatum(object->objectId));
5836
5838 NULL, 1, skey);
5839
5841
5842 if (!HeapTupleIsValid(tup))
5843 {
5844 if (!missing_ok)
5845 elog(ERROR, "could not find tuple for pg_auth_members entry %u",
5846 object->objectId);
5847
5850 break;
5851 }
5852
5854
5855 appendStringInfo(&buffer, _("membership of role %s in role %s"),
5856 GetUserNameFromId(amForm->member, false),
5857 GetUserNameFromId(amForm->roleid, false));
5858
5861 break;
5862 }
5863
5864 case DatabaseRelationId:
5865 {
5866 char *datname;
5867
5869 if (!datname)
5870 {
5871 if (!missing_ok)
5872 elog(ERROR, "cache lookup failed for database %u",
5873 object->objectId);
5874 break;
5875 }
5876 if (objname)
5877 *objname = list_make1(datname);
5878 appendStringInfoString(&buffer,
5880 break;
5881 }
5882
5884 {
5885 char *tblspace;
5886
5888 if (!tblspace)
5889 {
5890 if (!missing_ok)
5891 elog(ERROR, "cache lookup failed for tablespace %u",
5892 object->objectId);
5893 break;
5894 }
5895 if (objname)
5896 *objname = list_make1(tblspace);
5897 appendStringInfoString(&buffer,
5899 break;
5900 }
5901
5903 {
5905
5907 missing_ok);
5908 if (fdw)
5909 {
5910 appendStringInfoString(&buffer, quote_identifier(fdw->fdwname));
5911 if (objname)
5912 *objname = list_make1(pstrdup(fdw->fdwname));
5913 }
5914 break;
5915 }
5916
5918 {
5920
5922 missing_ok);
5923 if (srv)
5924 {
5925 appendStringInfoString(&buffer,
5926 quote_identifier(srv->servername));
5927 if (objname)
5928 *objname = list_make1(pstrdup(srv->servername));
5929 }
5930 break;
5931 }
5932
5934 {
5935 HeapTuple tup;
5936 Oid useid;
5939 const char *usename;
5940
5942 ObjectIdGetDatum(object->objectId));
5943 if (!HeapTupleIsValid(tup))
5944 {
5945 if (!missing_ok)
5946 elog(ERROR, "cache lookup failed for user mapping %u",
5947 object->objectId);
5948 break;
5949 }
5951 useid = umform->umuser;
5952 srv = GetForeignServer(umform->umserver);
5953
5955
5956 if (OidIsValid(useid))
5958 else
5959 usename = "public";
5960
5961 if (objname)
5962 {
5963 *objname = list_make1(pstrdup(usename));
5964 *objargs = list_make1(pstrdup(srv->servername));
5965 }
5966
5967 appendStringInfo(&buffer, "%s on server %s",
5969 srv->servername);
5970 break;
5971 }
5972
5974 {
5976 ScanKeyData skey[1];
5978 HeapTuple tup;
5980 char *schema;
5981 char *username;
5982
5984
5985 ScanKeyInit(&skey[0],
5988 ObjectIdGetDatum(object->objectId));
5989
5991 true, NULL, 1, skey);
5992
5994
5995 if (!HeapTupleIsValid(tup))
5996 {
5997 if (!missing_ok)
5998 elog(ERROR, "could not find tuple for default ACL %u",
5999 object->objectId);
6000
6003 break;
6004 }
6005
6007
6008 username = GetUserNameFromId(defacl->defaclrole, false);
6009 appendStringInfo(&buffer,
6010 "for role %s",
6012
6013 if (OidIsValid(defacl->defaclnamespace))
6014 {
6015 schema = get_namespace_name_or_temp(defacl->defaclnamespace);
6016 appendStringInfo(&buffer,
6017 " in schema %s",
6018 quote_identifier(schema));
6019 }
6020 else
6021 schema = NULL;
6022
6023 switch (defacl->defaclobjtype)
6024 {
6025 case DEFACLOBJ_RELATION:
6026 appendStringInfoString(&buffer,
6027 " on tables");
6028 break;
6029 case DEFACLOBJ_SEQUENCE:
6030 appendStringInfoString(&buffer,
6031 " on sequences");
6032 break;
6033 case DEFACLOBJ_FUNCTION:
6034 appendStringInfoString(&buffer,
6035 " on functions");
6036 break;
6037 case DEFACLOBJ_TYPE:
6038 appendStringInfoString(&buffer,
6039 " on types");
6040 break;
6042 appendStringInfoString(&buffer,
6043 " on schemas");
6044 break;
6046 appendStringInfoString(&buffer,
6047 " on large objects");
6048 break;
6049 }
6050
6051 if (objname)
6052 {
6053 *objname = list_make1(username);
6054 if (schema)
6055 *objname = lappend(*objname, schema);
6056 *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
6057 }
6058
6061 break;
6062 }
6063
6065 {
6066 char *extname;
6067
6068 extname = get_extension_name(object->objectId);
6069 if (!extname)
6070 {
6071 if (!missing_ok)
6072 elog(ERROR, "cache lookup failed for extension %u",
6073 object->objectId);
6074 break;
6075 }
6076 appendStringInfoString(&buffer, quote_identifier(extname));
6077 if (objname)
6078 *objname = list_make1(extname);
6079 break;
6080 }
6081
6083 {
6084 HeapTuple tup;
6086 char *evtname;
6087
6089 ObjectIdGetDatum(object->objectId));
6090 if (!HeapTupleIsValid(tup))
6091 {
6092 if (!missing_ok)
6093 elog(ERROR, "cache lookup failed for event trigger %u",
6094 object->objectId);
6095 break;
6096 }
6098 evtname = pstrdup(NameStr(trigForm->evtname));
6099 appendStringInfoString(&buffer, quote_identifier(evtname));
6100 if (objname)
6101 *objname = list_make1(evtname);
6103 break;
6104 }
6105
6107 {
6108 HeapTuple tup;
6110 char *parname;
6111
6113 ObjectIdGetDatum(object->objectId));
6114 if (!HeapTupleIsValid(tup))
6115 {
6116 if (!missing_ok)
6117 elog(ERROR, "cache lookup failed for parameter ACL %u",
6118 object->objectId);
6119 break;
6120 }
6125 if (objname)
6126 *objname = list_make1(parname);
6128 break;
6129 }
6130
6131 case PolicyRelationId:
6132 {
6134 HeapTuple tup;
6136
6138
6140 object->objectId);
6141
6142 if (!HeapTupleIsValid(tup))
6143 {
6144 if (!missing_ok)
6145 elog(ERROR, "could not find tuple for policy %u",
6146 object->objectId);
6147
6149 break;
6150 }
6151
6153
6154 appendStringInfo(&buffer, "%s on ",
6155 quote_identifier(NameStr(policy->polname)));
6156 getRelationIdentity(&buffer, policy->polrelid, objname, false);
6157 if (objname)
6158 *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
6159
6161 break;
6162 }
6163
6165 {
6166 HeapTuple tup;
6168
6170 if (!HeapTupleIsValid(tup))
6171 {
6172 if (!missing_ok)
6173 elog(ERROR, "cache lookup failed for property graph element %u", object->objectId);
6174 break;
6175 }
6177 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pge->pgealias)));
6178
6179 getRelationIdentity(&buffer, pge->pgepgid, objname, false);
6180 if (objname)
6181 *objname = lappend(*objname, pstrdup(NameStr(pge->pgealias)));
6182
6184 break;
6185 }
6186
6188 {
6189 HeapTuple tup;
6191
6193 if (!HeapTupleIsValid(tup))
6194 {
6195 if (!missing_ok)
6196 elog(ERROR, "cache lookup failed for property graph label %u", object->objectId);
6197 break;
6198 }
6199
6201 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pgl->pgllabel)));
6202 getRelationIdentity(&buffer, pgl->pglpgid, objname, false);
6203 if (objname)
6204 *objname = lappend(*objname, pstrdup(NameStr(pgl->pgllabel)));
6206 break;
6207 }
6208
6210 {
6211 HeapTuple tup;
6213
6215 if (!HeapTupleIsValid(tup))
6216 {
6217 if (!missing_ok)
6218 elog(ERROR, "cache lookup failed for property graph property %u", object->objectId);
6219 break;
6220 }
6221
6223 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pgp->pgpname)));
6224 getRelationIdentity(&buffer, pgp->pgppgid, objname, false);
6225 if (objname)
6226 *objname = lappend(*objname, pstrdup(NameStr(pgp->pgpname)));
6228 break;
6229 }
6230
6232 {
6233 char *pubname;
6234
6235 pubname = get_publication_name(object->objectId, missing_ok);
6236 if (pubname)
6237 {
6238 appendStringInfoString(&buffer,
6239 quote_identifier(pubname));
6240 if (objname)
6241 *objname = list_make1(pubname);
6242 }
6243 break;
6244 }
6245
6247 {
6248 char *pubname;
6249 char *nspname;
6250
6251 if (!getPublicationSchemaInfo(object, missing_ok, &pubname,
6252 &nspname))
6253 break;
6254 appendStringInfo(&buffer, "%s in publication %s",
6255 nspname, pubname);
6256
6257 if (objargs)
6258 *objargs = list_make1(pubname);
6259 else
6260 pfree(pubname);
6261
6262 if (objname)
6263 *objname = list_make1(nspname);
6264 else
6265 pfree(nspname);
6266
6267 break;
6268 }
6269
6271 {
6272 HeapTuple tup;
6273 char *pubname;
6275
6277 ObjectIdGetDatum(object->objectId));
6278 if (!HeapTupleIsValid(tup))
6279 {
6280 if (!missing_ok)
6281 elog(ERROR, "cache lookup failed for publication table %u",
6282 object->objectId);
6283 break;
6284 }
6285
6287 pubname = get_publication_name(prform->prpubid, false);
6288
6289 getRelationIdentity(&buffer, prform->prrelid, objname, false);
6290 appendStringInfo(&buffer, " in publication %s", pubname);
6291
6292 if (objargs)
6293 *objargs = list_make1(pubname);
6294
6296 break;
6297 }
6298
6300 {
6301 char *subname;
6302
6303 subname = get_subscription_name(object->objectId, missing_ok);
6304 if (subname)
6305 {
6306 appendStringInfoString(&buffer,
6308 if (objname)
6309 *objname = list_make1(subname);
6310 }
6311 break;
6312 }
6313
6315 {
6317 HeapTuple tup;
6318 Form_pg_transform transform;
6319 char *transformLang;
6320 char *transformType;
6321
6323
6326 object->objectId);
6327
6328 if (!HeapTupleIsValid(tup))
6329 {
6330 if (!missing_ok)
6331 elog(ERROR, "could not find tuple for transform %u",
6332 object->objectId);
6333
6335 break;
6336 }
6337
6338 transform = (Form_pg_transform) GETSTRUCT(tup);
6339
6340 transformType = format_type_be_qualified(transform->trftype);
6341 transformLang = get_language_name(transform->trflang, false);
6342
6343 appendStringInfo(&buffer, "for %s language %s",
6346 if (objname)
6347 {
6348 *objname = list_make1(transformType);
6349 *objargs = list_make1(pstrdup(transformLang));
6350 }
6351
6353 }
6354 break;
6355
6356 default:
6357 elog(ERROR, "unsupported object class: %u", object->classId);
6358 }
6359
6360 if (!missing_ok)
6361 {
6362 /*
6363 * If a get_object_address() representation was requested, make sure
6364 * we are providing one. We don't check objargs, because many of the
6365 * cases above leave it as NIL.
6366 */
6367 if (objname && *objname == NIL)
6368 elog(ERROR, "requested object address for unsupported object class %u: text result \"%s\"",
6369 object->classId, buffer.data);
6370 }
6371 else
6372 {
6373 /* an empty buffer is equivalent to no object found */
6374 if (buffer.len == 0)
6375 {
6376 Assert((objname == NULL || *objname == NIL) &&
6377 (objargs == NULL || *objargs == NIL));
6378 return NULL;
6379 }
6380 }
6381
6382 return buffer.data;
6383}
6384
6385static void
6387 bool missing_ok)
6388{
6393 char *schema;
6394
6397 {
6398 if (!missing_ok)
6399 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
6400 return;
6401 }
6403
6405 if (!HeapTupleIsValid(amTup))
6406 elog(ERROR, "cache lookup failed for access method %u",
6407 opfForm->opfmethod);
6409
6410 schema = get_namespace_name_or_temp(opfForm->opfnamespace);
6411 appendStringInfo(buffer, "%s USING %s",
6413 NameStr(opfForm->opfname)),
6414 NameStr(amForm->amname));
6415
6416 if (object)
6417 *object = list_make3(pstrdup(NameStr(amForm->amname)),
6418 pstrdup(schema),
6419 pstrdup(NameStr(opfForm->opfname)));
6420
6423}
6424
6425/*
6426 * Append the relation identity (quoted qualified name) to the given
6427 * StringInfo.
6428 */
6429static void
6430getRelationIdentity(StringInfo buffer, Oid relid, List **object,
6431 bool missing_ok)
6432{
6435 char *schema;
6436
6438 ObjectIdGetDatum(relid));
6440 {
6441 if (!missing_ok)
6442 elog(ERROR, "cache lookup failed for relation %u", relid);
6443
6444 if (object)
6445 *object = NIL;
6446 return;
6447 }
6449
6450 schema = get_namespace_name_or_temp(relForm->relnamespace);
6453 NameStr(relForm->relname)));
6454 if (object)
6455 *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
6456
6458}
6459
6460/*
6461 * Auxiliary function to build a TEXT array out of a list of C-strings.
6462 */
6463ArrayType *
6465{
6466 ArrayType *arr;
6467 Datum *datums;
6468 bool *nulls;
6469 int j = 0;
6470 ListCell *cell;
6471 MemoryContext memcxt;
6473 int lb[1];
6474
6475 /* Work in a temp context; easier than individually pfree'ing the Datums */
6477 "strlist to array",
6479 oldcxt = MemoryContextSwitchTo(memcxt);
6480
6481 datums = palloc_array(Datum, list_length(list));
6482 nulls = palloc_array(bool, list_length(list));
6483
6484 foreach(cell, list)
6485 {
6486 char *name = lfirst(cell);
6487
6488 if (name)
6489 {
6490 nulls[j] = false;
6491 datums[j++] = CStringGetTextDatum(name);
6492 }
6493 else
6494 nulls[j] = true;
6495 }
6496
6498
6499 lb[0] = 1;
6500 arr = construct_md_array(datums, nulls, 1, &j,
6501 lb, TEXTOID, -1, false, TYPALIGN_INT);
6502
6503 MemoryContextDelete(memcxt);
6504
6505 return arr;
6506}
6507
6508/*
6509 * get_relkind_objtype
6510 *
6511 * Return the object type for the relkind given by the caller.
6512 *
6513 * If an unexpected relkind is passed, we say OBJECT_TABLE rather than
6514 * failing. That's because this is mostly used for generating error messages
6515 * for failed ACL checks on relations, and we'd rather produce a generic
6516 * message saying "table" than fail entirely.
6517 */
6520{
6521 switch (relkind)
6522 {
6523 case RELKIND_RELATION:
6525 return OBJECT_TABLE;
6526 case RELKIND_INDEX:
6528 return OBJECT_INDEX;
6529 case RELKIND_SEQUENCE:
6530 return OBJECT_SEQUENCE;
6531 case RELKIND_VIEW:
6532 return OBJECT_VIEW;
6533 case RELKIND_MATVIEW:
6534 return OBJECT_MATVIEW;
6536 return OBJECT_FOREIGN_TABLE;
6537 case RELKIND_PROPGRAPH:
6538 return OBJECT_PROPGRAPH;
6539 case RELKIND_TOASTVALUE:
6540 return OBJECT_TABLE;
6541 default:
6542 /* Per above, don't raise an error */
6543 return OBJECT_TABLE;
6544 }
6545}
bool is_admin_of_role(Oid member, Oid role)
Definition acl.c:5444
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition acl.c:5605
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4133
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition aclchk.c:2997
bool has_createrole_privilege(Oid roleid)
Definition aclchk.c:4212
Oid get_index_am_oid(const char *amname, bool missing_ok)
Definition amcmds.c:163
char * get_am_name(Oid amOid)
Definition amcmds.c:192
Oid get_am_oid(const char *amname, bool missing_ok)
Definition amcmds.c:183
#define PG_GETARG_ARRAYTYPE_P(n)
Definition array.h:263
ArrayType * construct_empty_array(Oid elmtype)
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
char * get_tablespace_name(Oid spc_oid)
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define FORMAT_TYPE_ALLOW_INVALID
Definition builtins.h:126
#define TextDatumGetCString(d)
Definition builtins.h:99
#define FORMAT_TYPE_INVALID_AS_NULL
Definition builtins.h:128
#define FORMAT_TYPE_FORCE_QUALIFY
Definition builtins.h:127
#define NameStr(name)
Definition c.h:837
uint16 bits16
Definition c.h:626
#define Assert(condition)
Definition c.h:945
int32_t int32
Definition c.h:614
uint64_t uint64
Definition c.h:619
#define lengthof(array)
Definition c.h:875
#define pg_fallthrough
Definition c.h:152
#define OidIsValid(objectId)
Definition c.h:860
bool IsSharedRelation(Oid relationId)
Definition catalog.c:304
Oid get_database_oid(const char *dbname, bool missing_ok)
int errcode(int sqlerrcode)
Definition elog.c:874
#define _(x)
Definition elog.c:95
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
Oid get_event_trigger_oid(const char *trigname, bool missing_ok)
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition extension.c:229
char * get_extension_name(Oid ext_oid)
Definition extension.c:251
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_RETURN_TEXT_P(x)
Definition fmgr.h:374
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition foreign.c:210
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition foreign.c:793
ForeignServer * GetForeignServer(Oid serverid)
Definition foreign.c:114
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
Definition foreign.c:51
ForeignServer * GetForeignServerExtended(Oid serverid, bits16 flags)
Definition foreign.c:126
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition foreign.c:770
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
char * format_type_be_qualified(Oid type_oid)
char * format_type_be(Oid type_oid)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
static char * username
Definition initdb.c:153
bool lo_compat_privileges
Definition inv_api.c:56
int j
Definition isn.c:78
int i
Definition isn.c:77
const char ** typenames
Definition lexi.c:115
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_copy_tail(const List *oldlist, int nskip)
Definition list.c:1613
List * lcons(void *datum, List *list)
Definition list.c:495
List * list_copy_head(const List *oldlist, int len)
Definition list.c:1593
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1088
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1008
void LockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
Definition lmgr.c:562
void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1148
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1068
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessShareLock
Definition lockdefs.h:36
#define InplaceUpdateTupleLock
Definition lockdefs.h:48
char * get_propgraph_property_name(Oid propoid)
Definition lsyscache.c:3959
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1153
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:977
char * get_database_name(Oid dbid)
Definition lsyscache.c:1312
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2223
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3847
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1333
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3612
char * get_propgraph_label_name(Oid labeloid)
Definition lsyscache.c:3941
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:946
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:3897
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:3917
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:3867
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:989
char * NameListToString(const List *names)
Definition namespace.c:3666
bool TSTemplateIsVisible(Oid tmplId)
Definition namespace.c:3137
bool OpfamilyIsVisible(Oid opfid)
Definition namespace.c:2325
bool CollationIsVisible(Oid collid)
Definition namespace.c:2476
bool ConversionIsVisible(Oid conid)
Definition namespace.c:2578
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition namespace.c:2644
Oid get_collation_oid(List *collname, bool missing_ok)
Definition namespace.c:4043
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3607
bool RelationIsVisible(Oid relid)
Definition namespace.c:914
bool OpclassIsVisible(Oid opcid)
Definition namespace.c:2223
bool TSParserIsVisible(Oid prsId)
Definition namespace.c:2846
Oid get_conversion_oid(List *conname, bool missing_ok)
Definition namespace.c:4097
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition namespace.c:2933
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition namespace.c:2788
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3626
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition namespace.c:3224
bool TSConfigIsVisible(Oid cfgid)
Definition namespace.c:3282
bool StatisticsObjIsVisible(Oid stxid)
Definition namespace.c:2701
bool TSDictionaryIsVisible(Oid dictId)
Definition namespace.c:2991
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition namespace.c:3079
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
static char * errmsg
static void getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok)
char * getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
ArrayType * strlist_to_textarray(List *list)
bool get_object_namensp_unique(Oid class_id)
ObjectAddress get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
AttrNumber get_object_attnum_owner(Oid class_id)
Datum pg_identify_object(PG_FUNCTION_ARGS)
HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
AttrNumber get_object_attnum_oid(Oid class_id)
static const ObjectPropertyType ObjectProperty[]
ObjectType get_relkind_objtype(char relkind)
AttrNumber get_object_attnum_namespace(Oid class_id)
void check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, Node *object, Relation relation)
SysCacheIdentifier get_object_catcache_name(Oid class_id)
char * getObjectDescriptionOids(Oid classid, Oid objid)
char * getObjectIdentityParts(const ObjectAddress *object, List **objname, List **objargs, bool missing_ok)
static ObjectAddress get_object_address_publication_schema(List *object, bool missing_ok)
AttrNumber get_object_attnum_name(Oid class_id)
static ObjectAddress get_object_address_relobject(ObjectType objtype, List *object, Relation *relp, bool missing_ok)
static void getConstraintTypeDescription(StringInfo buffer, Oid constroid, bool missing_ok)
const char * get_object_class_descr(Oid class_id)
static void getProcedureTypeDescription(StringInfo buffer, Oid procid, bool missing_ok)
static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object, bool missing_ok)
static ObjectAddress get_object_address_defacl(List *object, bool missing_ok)
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
Datum pg_get_acl(PG_FUNCTION_ARGS)
static bool getPublicationSchemaInfo(const ObjectAddress *object, bool missing_ok, char **pubname, char **nspname)
AttrNumber get_object_attnum_acl(Oid class_id)
static void getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId, bool missing_ok)
static void getOpFamilyDescription(StringInfo buffer, Oid opfid, bool missing_ok)
Oid get_object_oid_index(Oid class_id)
static ObjectAddress get_object_address_unqualified(ObjectType objtype, String *strval, bool missing_ok)
int read_objtype_from_string(const char *objtype)
SysCacheIdentifier get_object_catcache_oid(Oid class_id)
const ObjectAddress InvalidObjectAddress
ObjectType get_object_type(Oid class_id, Oid object_id)
static ObjectAddress get_object_address_publication_rel(List *object, Relation *relp, bool missing_ok)
static ObjectAddress get_object_address_opf_member(ObjectType objtype, List *object, bool missing_ok)
static const ObjectPropertyType * get_object_property_data(Oid class_id)
static ObjectAddress get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
static ObjectAddress get_object_address_usermapping(List *object, bool missing_ok)
static const struct object_type_map ObjectTypeMap[]
static void getRelationIdentity(StringInfo buffer, Oid relid, List **object, bool missing_ok)
static ObjectAddress get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
Datum pg_identify_object_as_address(PG_FUNCTION_ARGS)
ObjectAddress get_object_address(ObjectType objtype, Node *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
Datum pg_describe_object(PG_FUNCTION_ARGS)
Datum pg_get_object_address(PG_FUNCTION_ARGS)
static ObjectAddress get_object_address_attribute(ObjectType objtype, List *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
static ObjectAddress get_relation_by_qualified_name(ObjectType objtype, List *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
char * getObjectIdentity(const ObjectAddress *object, bool missing_ok)
Oid get_object_namespace(const ObjectAddress *address)
HeapTuple get_catalog_object_by_oid_extended(Relation catalog, AttrNumber oidcol, Oid objectId, bool locktup)
static ObjectAddress get_object_address_attrdef(ObjectType objtype, List *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
bool is_objectclass_supported(Oid class_id)
static List * textarray_to_strvaluelist(ArrayType *arr)
#define ObjectAddressSet(addr, class_id, object_id)
Oid oidparse(Node *node)
Definition oid.c:264
Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition parse_oper.c:135
char * TypeNameToString(const TypeName *typeName)
Definition parse_type.c:478
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition parse_type.c:38
TypeName * typeStringToTypeName(const char *str, Node *escontext)
Definition parse_type.c:738
Oid typeTypeId(Type tp)
Definition parse_type.c:590
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition parse_type.c:291
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition parse_type.c:232
ObjectType
@ OBJECT_EVENT_TRIGGER
@ OBJECT_FDW
@ OBJECT_TSPARSER
@ OBJECT_COLLATION
@ OBJECT_USER_MAPPING
@ OBJECT_PROPGRAPH
@ OBJECT_ACCESS_METHOD
@ OBJECT_OPCLASS
@ OBJECT_DEFACL
@ OBJECT_AGGREGATE
@ OBJECT_MATVIEW
@ OBJECT_SCHEMA
@ OBJECT_POLICY
@ OBJECT_OPERATOR
@ OBJECT_FOREIGN_TABLE
@ OBJECT_TSCONFIGURATION
@ OBJECT_OPFAMILY
@ OBJECT_DOMAIN
@ OBJECT_COLUMN
@ OBJECT_TABLESPACE
@ OBJECT_ROLE
@ OBJECT_ROUTINE
@ OBJECT_LARGEOBJECT
@ OBJECT_PUBLICATION_NAMESPACE
@ OBJECT_PROCEDURE
@ OBJECT_EXTENSION
@ OBJECT_INDEX
@ OBJECT_DEFAULT
@ OBJECT_DATABASE
@ OBJECT_SEQUENCE
@ OBJECT_TSTEMPLATE
@ OBJECT_LANGUAGE
@ OBJECT_AMOP
@ OBJECT_PUBLICATION_REL
@ OBJECT_FOREIGN_SERVER
@ OBJECT_TSDICTIONARY
@ OBJECT_ATTRIBUTE
@ OBJECT_PUBLICATION
@ OBJECT_RULE
@ OBJECT_CONVERSION
@ OBJECT_AMPROC
@ OBJECT_TABLE
@ OBJECT_VIEW
@ OBJECT_PARAMETER_ACL
@ OBJECT_TYPE
@ OBJECT_FUNCTION
@ OBJECT_TABCONSTRAINT
@ OBJECT_DOMCONSTRAINT
@ OBJECT_SUBSCRIPTION
@ OBJECT_STATISTIC_EXT
@ OBJECT_CAST
@ OBJECT_TRIGGER
@ OBJECT_TRANSFORM
END_CATALOG_STRUCT typedef FormData_pg_am * Form_pg_am
Definition pg_am.h:52
END_CATALOG_STRUCT typedef FormData_pg_amop * Form_pg_amop
Definition pg_amop.h:92
END_CATALOG_STRUCT typedef FormData_pg_amproc * Form_pg_amproc
Definition pg_amproc.h:72
Oid GetAttrDefaultOid(Oid relid, AttrNumber attnum)
Definition pg_attrdef.c:280
ObjectAddress GetAttrDefaultColumnAddress(Oid attrdefoid)
Definition pg_attrdef.c:322
NameData attname
int16 attnum
END_CATALOG_STRUCT typedef FormData_pg_auth_members * Form_pg_auth_members
END_CATALOG_STRUCT typedef FormData_pg_authid * Form_pg_authid
Definition pg_authid.h:60
END_CATALOG_STRUCT typedef FormData_pg_cast * Form_pg_cast
Definition pg_cast.h:61
NameData relname
Definition pg_class.h:40
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
END_CATALOG_STRUCT typedef FormData_pg_collation * Form_pg_collation
Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
END_CATALOG_STRUCT typedef FormData_pg_conversion * Form_pg_conversion
NameData datname
Definition pg_database.h:37
END_CATALOG_STRUCT typedef FormData_pg_default_acl * Form_pg_default_acl
END_CATALOG_STRUCT typedef FormData_pg_event_trigger * Form_pg_event_trigger
END_CATALOG_STRUCT typedef FormData_pg_language * Form_pg_language
Definition pg_language.h:69
bool LargeObjectExists(Oid loid)
#define lfirst(lc)
Definition pg_list.h:172
#define llast(l)
Definition pg_list.h:198
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define NIL
Definition pg_list.h:68
#define lsecond_node(type, l)
Definition pg_list.h:186
#define lthird(l)
Definition pg_list.h:188
#define list_make1(x1)
Definition pg_list.h:212
#define linitial(l)
Definition pg_list.h:178
#define list_make3(x1, x2, x3)
Definition pg_list.h:216
#define lsecond(l)
Definition pg_list.h:183
#define list_make2(x1, x2)
Definition pg_list.h:214
END_CATALOG_STRUCT typedef FormData_pg_opclass * Form_pg_opclass
Definition pg_opclass.h:87
END_CATALOG_STRUCT typedef FormData_pg_opfamily * Form_pg_opfamily
Definition pg_opfamily.h:55
Oid ParameterAclLookup(const char *parameter, bool missing_ok)
END_CATALOG_STRUCT typedef FormData_pg_policy * Form_pg_policy
Definition pg_policy.h:55
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
NameData proname
Definition pg_proc.h:37
END_CATALOG_STRUCT typedef FormData_pg_propgraph_element * Form_pg_propgraph_element
END_CATALOG_STRUCT typedef FormData_pg_propgraph_element_label * Form_pg_propgraph_element_label
END_CATALOG_STRUCT typedef FormData_pg_propgraph_label * Form_pg_propgraph_label
END_CATALOG_STRUCT typedef FormData_pg_propgraph_label_property * Form_pg_propgraph_label_property
END_CATALOG_STRUCT typedef FormData_pg_propgraph_property * Form_pg_propgraph_property
Publication * GetPublicationByName(const char *pubname, bool missing_ok)
END_CATALOG_STRUCT typedef FormData_pg_publication_namespace * Form_pg_publication_namespace
END_CATALOG_STRUCT typedef FormData_pg_publication_rel * Form_pg_publication_rel
END_CATALOG_STRUCT typedef FormData_pg_rewrite * Form_pg_rewrite
Definition pg_rewrite.h:56
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
NameData subname
END_CATALOG_STRUCT typedef FormData_pg_transform * Form_pg_transform
END_CATALOG_STRUCT typedef FormData_pg_trigger * Form_pg_trigger
Definition pg_trigger.h:84
END_CATALOG_STRUCT typedef FormData_pg_ts_config * Form_pg_ts_config
END_CATALOG_STRUCT typedef FormData_pg_ts_dict * Form_pg_ts_dict
Definition pg_ts_dict.h:56
END_CATALOG_STRUCT typedef FormData_pg_ts_parser * Form_pg_ts_parser
END_CATALOG_STRUCT typedef FormData_pg_ts_template * Form_pg_ts_template
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
NameData typname
Definition pg_type.h:43
END_CATALOG_STRUCT typedef FormData_pg_user_mapping * Form_pg_user_mapping
Oid get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
Definition policy.c:1204
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Name DatumGetName(Datum X)
Definition postgres.h:380
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
static int fb(int x)
Oid get_language_oid(const char *langname, bool missing_ok)
Definition proclang.c:227
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
char * format_procedure_extended(Oid procedure_oid, bits16 flags)
Definition regproc.c:332
char * format_procedure(Oid procedure_oid)
Definition regproc.c:305
char * format_operator_extended(Oid operator_oid, bits16 flags)
Definition regproc.c:730
void format_operator_parts(Oid operator_oid, List **objnames, List **objargs, bool missing_ok)
Definition regproc.c:814
void format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs, bool missing_ok)
Definition regproc.c:404
char * format_operator(Oid operator_oid)
Definition regproc.c:801
#define FORMAT_OPERATOR_INVALID_AS_NULL
Definition regproc.h:24
#define FORMAT_OPERATOR_FORCE_QUALIFY
Definition regproc.h:25
#define FORMAT_PROC_FORCE_QUALIFY
Definition regproc.h:20
#define FORMAT_PROC_INVALID_AS_NULL
Definition regproc.h:19
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
Oid get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
char * quote_qualified_identifier(const char *qualifier, const char *ident)
const char * quote_identifier(const char *ident)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
uint64 SharedInvalidMessageCounter
Definition sinval.c:24
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition relation.c:172
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:137
#define BTEqualStrategyNumber
Definition stratnum.h:31
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
ItemPointerData t_self
Definition htup.h:65
Definition pg_list.h:54
Definition nodes.h:135
const char * class_descr
AttrNumber attnum_owner
AttrNumber attnum_namespace
SysCacheIdentifier oid_catcache_id
SysCacheIdentifier name_catcache_id
char * relname
Definition primnodes.h:84
char * catalogname
Definition primnodes.h:78
char * schemaname
Definition primnodes.h:81
Form_pg_class rd_rel
Definition rel.h:111
Definition value.h:64
TupleConstr * constr
Definition tupdesc.h:159
Definition type.h:96
ObjectType tm_type
const char * tm_name
bool superuser_arg(Oid roleid)
Definition superuser.c:57
HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
Definition syscache.c:561
HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:399
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230
HeapTuple SearchSysCache3(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3)
Definition syscache.c:240
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:625
HeapTuple SearchSysCache4(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition syscache.c:250
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
Relation table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition table.c:103
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
Definition trigger.c:1372
String * makeString(char *str)
Definition value.c:63
Float * makeFloat(char *numericStr)
Definition value.c:37
#define strVal(v)
Definition value.h:82
text * cstring_to_text(const char *s)
Definition varlena.c:184
const char * description
const char * type
const char * name