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 element label", -1
900 },
901 {
902 "property graph label", -1
903 },
904 {
905 "property graph label property", -1
906 },
907 {
908 "property graph property", -1
909 },
910 {
911 "publication", OBJECT_PUBLICATION
912 },
913 {
914 "publication namespace", OBJECT_PUBLICATION_NAMESPACE
915 },
916 {
917 "publication relation", OBJECT_PUBLICATION_REL
918 },
919 {
920 "subscription", OBJECT_SUBSCRIPTION
921 },
922 {
923 "transform", OBJECT_TRANSFORM
924 },
925 {
926 "statistics object", OBJECT_STATISTIC_EXT
927 }
929
931{
934 0
935};
936
938 String *strval, bool missing_ok);
940 List *object, Relation *relp,
941 LOCKMODE lockmode, bool missing_ok);
943 List *object, Relation *relp, bool missing_ok);
945 List *object, Relation *relp,
946 LOCKMODE lockmode, bool missing_ok);
948 List *object, Relation *relp, LOCKMODE lockmode,
949 bool missing_ok);
951 TypeName *typename, bool missing_ok);
953 bool missing_ok);
955 List *object, bool missing_ok);
956
958 bool missing_ok);
960 Relation *relp,
961 bool missing_ok);
963 bool missing_ok);
965 bool missing_ok);
967
968static void getRelationDescription(StringInfo buffer, Oid relid,
969 bool missing_ok);
970static void getOpFamilyDescription(StringInfo buffer, Oid opfid,
971 bool missing_ok);
972static void getRelationTypeDescription(StringInfo buffer, Oid relid,
973 int32 objectSubId, bool missing_ok);
974static void getProcedureTypeDescription(StringInfo buffer, Oid procid,
975 bool missing_ok);
977 bool missing_ok);
978static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object,
979 bool missing_ok);
980static void getRelationIdentity(StringInfo buffer, Oid relid, List **object,
981 bool missing_ok);
982
983/*
984 * Translate an object name and arguments (as passed by the parser) to an
985 * ObjectAddress.
986 *
987 * The returned object will be locked using the specified lockmode. If a
988 * sub-object is looked up, the parent object will be locked instead.
989 *
990 * If the object is a relation or a child object of a relation (e.g. an
991 * attribute or constraint), the relation is also opened and *relp receives
992 * the open relcache entry pointer; otherwise, *relp is set to NULL.
993 * (relp can be NULL if the caller never passes a relation-related object.) This
994 * is a bit grotty but it makes life simpler, since the caller will
995 * typically need the relcache entry too. Caller must close the relcache
996 * entry when done with it. The relation is locked with the specified lockmode
997 * if the target object is the relation itself or an attribute, but for other
998 * child objects, only AccessShareLock is acquired on the relation.
999 *
1000 * If the object is not found, an error is thrown, unless missing_ok is
1001 * true. In this case, no lock is acquired, relp is set to NULL, and the
1002 * returned address has objectId set to InvalidOid.
1003 *
1004 * We don't currently provide a function to release the locks acquired here;
1005 * typically, the lock must be held until commit to guard against a concurrent
1006 * drop operation.
1007 *
1008 * Note: If the object is not found, we don't give any indication of the
1009 * reason. (It might have been a missing schema if the name was qualified, or
1010 * a nonexistent type name in case of a cast, function or operator; etc).
1011 * Currently there is only one caller that might be interested in such info, so
1012 * we don't spend much effort here. If more callers start to care, it might be
1013 * better to add some support for that in this function.
1014 */
1017 Relation *relp, LOCKMODE lockmode, bool missing_ok)
1018{
1019 ObjectAddress address = {InvalidOid, InvalidOid, 0};
1021 Relation relation = NULL;
1023
1024 /* Some kind of lock must be taken. */
1025 Assert(lockmode != NoLock);
1026
1027 for (;;)
1028 {
1029 /*
1030 * Remember this value, so that, after looking up the object name and
1031 * locking it, we can check whether any invalidation messages have
1032 * been processed that might require a do-over.
1033 */
1035
1036 /* Look up object address. */
1037 switch (objtype)
1038 {
1039 case OBJECT_INDEX:
1040 case OBJECT_SEQUENCE:
1041 case OBJECT_TABLE:
1042 case OBJECT_VIEW:
1043 case OBJECT_MATVIEW:
1045 case OBJECT_PROPGRAPH:
1046 address =
1048 &relation, lockmode,
1049 missing_ok);
1050 break;
1051 case OBJECT_ATTRIBUTE:
1052 case OBJECT_COLUMN:
1053 address =
1054 get_object_address_attribute(objtype, castNode(List, object),
1055 &relation, lockmode,
1056 missing_ok);
1057 break;
1058 case OBJECT_DEFAULT:
1059 address =
1060 get_object_address_attrdef(objtype, castNode(List, object),
1061 &relation, lockmode,
1062 missing_ok);
1063 break;
1064 case OBJECT_RULE:
1065 case OBJECT_TRIGGER:
1067 case OBJECT_POLICY:
1068 address = get_object_address_relobject(objtype, castNode(List, object),
1069 &relation, missing_ok);
1070 break;
1072 {
1073 List *objlist;
1075 char *constrname;
1076
1077 objlist = castNode(List, object);
1080 missing_ok);
1082
1083 address.classId = ConstraintRelationId;
1084 address.objectId = get_domain_constraint_oid(domaddr.objectId,
1085 constrname, missing_ok);
1086 address.objectSubId = 0;
1087 }
1088 break;
1089 case OBJECT_DATABASE:
1090 case OBJECT_EXTENSION:
1091 case OBJECT_TABLESPACE:
1092 case OBJECT_ROLE:
1093 case OBJECT_SCHEMA:
1094 case OBJECT_LANGUAGE:
1095 case OBJECT_FDW:
1100 case OBJECT_PUBLICATION:
1102 address = get_object_address_unqualified(objtype,
1103 castNode(String, object), missing_ok);
1104 break;
1105 case OBJECT_TYPE:
1106 case OBJECT_DOMAIN:
1107 address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
1108 break;
1109 case OBJECT_AGGREGATE:
1110 case OBJECT_FUNCTION:
1111 case OBJECT_PROCEDURE:
1112 case OBJECT_ROUTINE:
1113 address.classId = ProcedureRelationId;
1114 address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
1115 address.objectSubId = 0;
1116 break;
1117 case OBJECT_OPERATOR:
1118 address.classId = OperatorRelationId;
1119 address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
1120 address.objectSubId = 0;
1121 break;
1122 case OBJECT_COLLATION:
1123 address.classId = CollationRelationId;
1124 address.objectId = get_collation_oid(castNode(List, object), missing_ok);
1125 address.objectSubId = 0;
1126 break;
1127 case OBJECT_CONVERSION:
1128 address.classId = ConversionRelationId;
1129 address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
1130 address.objectSubId = 0;
1131 break;
1132 case OBJECT_OPCLASS:
1133 case OBJECT_OPFAMILY:
1134 address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
1135 break;
1136 case OBJECT_AMOP:
1137 case OBJECT_AMPROC:
1138 address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
1139 break;
1140 case OBJECT_LARGEOBJECT:
1142 address.objectId = oidparse(object);
1143 address.objectSubId = 0;
1144 if (!LargeObjectExists(address.objectId))
1145 {
1146 if (!missing_ok)
1147 ereport(ERROR,
1149 errmsg("large object %u does not exist",
1150 address.objectId)));
1151 }
1152 break;
1153 case OBJECT_CAST:
1154 {
1155 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
1156 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
1159
1160 sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
1161 targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
1162 address.classId = CastRelationId;
1163 address.objectId =
1165 address.objectSubId = 0;
1166 }
1167 break;
1168 case OBJECT_TRANSFORM:
1169 {
1170 TypeName *typename = linitial_node(TypeName, castNode(List, object));
1171 char *langname = strVal(lsecond(castNode(List, object)));
1172 Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
1173 Oid lang_id = get_language_oid(langname, missing_ok);
1174
1175 address.classId = TransformRelationId;
1176 address.objectId =
1177 get_transform_oid(type_id, lang_id, missing_ok);
1178 address.objectSubId = 0;
1179 }
1180 break;
1181 case OBJECT_TSPARSER:
1182 address.classId = TSParserRelationId;
1183 address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
1184 address.objectSubId = 0;
1185 break;
1188 address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
1189 address.objectSubId = 0;
1190 break;
1191 case OBJECT_TSTEMPLATE:
1192 address.classId = TSTemplateRelationId;
1193 address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
1194 address.objectSubId = 0;
1195 break;
1197 address.classId = TSConfigRelationId;
1198 address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
1199 address.objectSubId = 0;
1200 break;
1202 address = get_object_address_usermapping(castNode(List, object),
1203 missing_ok);
1204 break;
1207 missing_ok);
1208 break;
1211 &relation,
1212 missing_ok);
1213 break;
1214 case OBJECT_DEFACL:
1215 address = get_object_address_defacl(castNode(List, object),
1216 missing_ok);
1217 break;
1221 missing_ok);
1222 address.objectSubId = 0;
1223 break;
1224 /* no default, to let compiler warn about missing case */
1225 }
1226
1227 if (!address.classId)
1228 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1229
1230 /*
1231 * If we could not find the supplied object, return without locking.
1232 */
1233 if (!OidIsValid(address.objectId))
1234 {
1235 Assert(missing_ok);
1236 return address;
1237 }
1238
1239 /*
1240 * If we're retrying, see if we got the same answer as last time. If
1241 * so, we're done; if not, we locked the wrong thing, so give up our
1242 * lock.
1243 */
1244 if (OidIsValid(old_address.classId))
1245 {
1246 if (old_address.classId == address.classId
1247 && old_address.objectId == address.objectId
1248 && old_address.objectSubId == address.objectSubId)
1249 break;
1250 if (old_address.classId != RelationRelationId)
1251 {
1252 if (IsSharedRelation(old_address.classId))
1254 old_address.objectId,
1255 0, lockmode);
1256 else
1258 old_address.objectId,
1259 0, lockmode);
1260 }
1261 }
1262
1263 /*
1264 * If we're dealing with a relation or attribute, then the relation is
1265 * already locked. Otherwise, we lock it now.
1266 */
1267 if (address.classId != RelationRelationId)
1268 {
1269 if (IsSharedRelation(address.classId))
1270 LockSharedObject(address.classId, address.objectId, 0,
1271 lockmode);
1272 else
1273 LockDatabaseObject(address.classId, address.objectId, 0,
1274 lockmode);
1275 }
1276
1277 /*
1278 * At this point, we've resolved the name to an OID and locked the
1279 * corresponding database object. However, it's possible that by the
1280 * time we acquire the lock on the object, concurrent DDL has modified
1281 * the database in such a way that the name we originally looked up no
1282 * longer resolves to that OID.
1283 *
1284 * We can be certain that this isn't an issue if (a) no shared
1285 * invalidation messages have been processed or (b) we've locked a
1286 * relation somewhere along the line. All the relation name lookups
1287 * in this module ultimately use RangeVarGetRelid() to acquire a
1288 * relation lock, and that function protects against the same kinds of
1289 * races we're worried about here. Even when operating on a
1290 * constraint, rule, or trigger, we still acquire AccessShareLock on
1291 * the relation, which is enough to freeze out any concurrent DDL.
1292 *
1293 * In all other cases, however, it's possible that the name we looked
1294 * up no longer refers to the object we locked, so we retry the lookup
1295 * and see whether we get the same answer.
1296 */
1297 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
1298 break;
1299 old_address = address;
1300 }
1301
1302 /* relp must be given if it's a relation */
1303 Assert(!relation || relp);
1304
1305 /* Return the object address and the relation. */
1306 if (relp)
1307 *relp = relation;
1308 return address;
1309}
1310
1311/*
1312 * Return an ObjectAddress based on a RangeVar and an object name. The
1313 * name of the relation identified by the RangeVar is prepended to the
1314 * (possibly empty) list passed in as object. This is useful to find
1315 * the ObjectAddress of objects that depend on a relation. All other
1316 * considerations are exactly as for get_object_address above.
1317 */
1320 Relation *relp, LOCKMODE lockmode,
1321 bool missing_ok)
1322{
1323 if (rel)
1324 {
1325 object = lcons(makeString(rel->relname), object);
1326 if (rel->schemaname)
1327 object = lcons(makeString(rel->schemaname), object);
1328 if (rel->catalogname)
1329 object = lcons(makeString(rel->catalogname), object);
1330 }
1331
1332 return get_object_address(objtype, (Node *) object,
1333 relp, lockmode, missing_ok);
1334}
1335
1336/*
1337 * Find an ObjectAddress for a type of object that is identified by an
1338 * unqualified name.
1339 */
1340static ObjectAddress
1342 String *strval, bool missing_ok)
1343{
1344 const char *name;
1345 ObjectAddress address;
1346
1347 name = strVal(strval);
1348
1349 /* Translate name to OID. */
1350 switch (objtype)
1351 {
1354 address.objectId = get_am_oid(name, missing_ok);
1355 address.objectSubId = 0;
1356 break;
1357 case OBJECT_DATABASE:
1358 address.classId = DatabaseRelationId;
1359 address.objectId = get_database_oid(name, missing_ok);
1360 address.objectSubId = 0;
1361 break;
1362 case OBJECT_EXTENSION:
1363 address.classId = ExtensionRelationId;
1364 address.objectId = get_extension_oid(name, missing_ok);
1365 address.objectSubId = 0;
1366 break;
1367 case OBJECT_TABLESPACE:
1368 address.classId = TableSpaceRelationId;
1369 address.objectId = get_tablespace_oid(name, missing_ok);
1370 address.objectSubId = 0;
1371 break;
1372 case OBJECT_ROLE:
1373 address.classId = AuthIdRelationId;
1374 address.objectId = get_role_oid(name, missing_ok);
1375 address.objectSubId = 0;
1376 break;
1377 case OBJECT_SCHEMA:
1378 address.classId = NamespaceRelationId;
1379 address.objectId = get_namespace_oid(name, missing_ok);
1380 address.objectSubId = 0;
1381 break;
1382 case OBJECT_LANGUAGE:
1383 address.classId = LanguageRelationId;
1384 address.objectId = get_language_oid(name, missing_ok);
1385 address.objectSubId = 0;
1386 break;
1387 case OBJECT_FDW:
1389 address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
1390 address.objectSubId = 0;
1391 break;
1394 address.objectId = get_foreign_server_oid(name, missing_ok);
1395 address.objectSubId = 0;
1396 break;
1399 address.objectId = get_event_trigger_oid(name, missing_ok);
1400 address.objectSubId = 0;
1401 break;
1404 address.objectId = ParameterAclLookup(name, missing_ok);
1405 address.objectSubId = 0;
1406 break;
1407 case OBJECT_PUBLICATION:
1409 address.objectId = get_publication_oid(name, missing_ok);
1410 address.objectSubId = 0;
1411 break;
1414 address.objectId = get_subscription_oid(name, missing_ok);
1415 address.objectSubId = 0;
1416 break;
1417 default:
1418 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1419 /* placate compiler, which doesn't know elog won't return */
1420 address.classId = InvalidOid;
1421 address.objectId = InvalidOid;
1422 address.objectSubId = 0;
1423 }
1424
1425 return address;
1426}
1427
1428/*
1429 * Locate a relation by qualified name.
1430 */
1431static ObjectAddress
1433 Relation *relp, LOCKMODE lockmode,
1434 bool missing_ok)
1435{
1436 Relation relation;
1437 ObjectAddress address;
1438
1439 address.classId = RelationRelationId;
1440 address.objectId = InvalidOid;
1441 address.objectSubId = 0;
1442
1444 lockmode, missing_ok);
1445 if (!relation)
1446 return address;
1447
1448 switch (objtype)
1449 {
1450 case OBJECT_INDEX:
1451 if (relation->rd_rel->relkind != RELKIND_INDEX &&
1452 relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
1453 ereport(ERROR,
1455 errmsg("\"%s\" is not an index",
1456 RelationGetRelationName(relation))));
1457 break;
1458 case OBJECT_PROPGRAPH:
1459 if (relation->rd_rel->relkind != RELKIND_PROPGRAPH)
1460 ereport(ERROR,
1462 errmsg("\"%s\" is not a property graph",
1463 RelationGetRelationName(relation))));
1464 break;
1465 case OBJECT_SEQUENCE:
1466 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
1467 ereport(ERROR,
1469 errmsg("\"%s\" is not a sequence",
1470 RelationGetRelationName(relation))));
1471 break;
1472 case OBJECT_TABLE:
1473 if (relation->rd_rel->relkind != RELKIND_RELATION &&
1474 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1475 ereport(ERROR,
1477 errmsg("\"%s\" is not a table",
1478 RelationGetRelationName(relation))));
1479 break;
1480 case OBJECT_VIEW:
1481 if (relation->rd_rel->relkind != RELKIND_VIEW)
1482 ereport(ERROR,
1484 errmsg("\"%s\" is not a view",
1485 RelationGetRelationName(relation))));
1486 break;
1487 case OBJECT_MATVIEW:
1488 if (relation->rd_rel->relkind != RELKIND_MATVIEW)
1489 ereport(ERROR,
1491 errmsg("\"%s\" is not a materialized view",
1492 RelationGetRelationName(relation))));
1493 break;
1495 if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1496 ereport(ERROR,
1498 errmsg("\"%s\" is not a foreign table",
1499 RelationGetRelationName(relation))));
1500 break;
1501 default:
1502 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1503 break;
1504 }
1505
1506 /* Done. */
1507 address.objectId = RelationGetRelid(relation);
1508 *relp = relation;
1509
1510 return address;
1511}
1512
1513/*
1514 * Find object address for an object that is attached to a relation.
1515 *
1516 * Note that we take only an AccessShareLock on the relation. We need not
1517 * pass down the LOCKMODE from get_object_address(), because that is the lock
1518 * mode for the object itself, not the relation to which it is attached.
1519 */
1520static ObjectAddress
1522 Relation *relp, bool missing_ok)
1523{
1524 ObjectAddress address;
1525 Relation relation = NULL;
1526 int nnames;
1527 const char *depname;
1528 List *relname;
1529 Oid reloid;
1530
1531 /* Extract name of dependent object. */
1532 depname = strVal(llast(object));
1533
1534 /* Separate relation name from dependent object name. */
1535 nnames = list_length(object);
1536 if (nnames < 2)
1537 ereport(ERROR,
1539 errmsg("must specify relation and object name")));
1540
1541 /* Extract relation name and open relation. */
1542 relname = list_copy_head(object, nnames - 1);
1545 missing_ok);
1546
1547 reloid = relation ? RelationGetRelid(relation) : InvalidOid;
1548
1549 switch (objtype)
1550 {
1551 case OBJECT_RULE:
1552 address.classId = RewriteRelationId;
1553 address.objectId = relation ?
1554 get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
1555 address.objectSubId = 0;
1556 break;
1557 case OBJECT_TRIGGER:
1558 address.classId = TriggerRelationId;
1559 address.objectId = relation ?
1560 get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
1561 address.objectSubId = 0;
1562 break;
1564 address.classId = ConstraintRelationId;
1565 address.objectId = relation ?
1566 get_relation_constraint_oid(reloid, depname, missing_ok) :
1567 InvalidOid;
1568 address.objectSubId = 0;
1569 break;
1570 case OBJECT_POLICY:
1571 address.classId = PolicyRelationId;
1572 address.objectId = relation ?
1573 get_relation_policy_oid(reloid, depname, missing_ok) :
1574 InvalidOid;
1575 address.objectSubId = 0;
1576 break;
1577 default:
1578 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1579 }
1580
1581 /* Avoid relcache leak when object not found. */
1582 if (!OidIsValid(address.objectId))
1583 {
1584 if (relation != NULL)
1585 table_close(relation, AccessShareLock);
1586
1587 relation = NULL; /* department of accident prevention */
1588 return address;
1589 }
1590
1591 /* Done. */
1592 *relp = relation;
1593 return address;
1594}
1595
1596/*
1597 * Find the ObjectAddress for an attribute.
1598 */
1599static ObjectAddress
1601 Relation *relp, LOCKMODE lockmode,
1602 bool missing_ok)
1603{
1604 ObjectAddress address;
1605 List *relname;
1606 Oid reloid;
1607 Relation relation;
1608 const char *attname;
1610
1611 /* Extract relation name and open relation. */
1612 if (list_length(object) < 2)
1613 ereport(ERROR,
1615 errmsg("column name must be qualified")));
1616 attname = strVal(llast(object));
1617 relname = list_copy_head(object, list_length(object) - 1);
1618 /* XXX no missing_ok support here */
1619 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1620 reloid = RelationGetRelid(relation);
1621
1622 /* Look up attribute and construct return value. */
1623 attnum = get_attnum(reloid, attname);
1625 {
1626 if (!missing_ok)
1627 ereport(ERROR,
1629 errmsg("column \"%s\" of relation \"%s\" does not exist",
1631
1632 address.classId = RelationRelationId;
1633 address.objectId = InvalidOid;
1635 relation_close(relation, lockmode);
1636 return address;
1637 }
1638
1639 address.classId = RelationRelationId;
1640 address.objectId = reloid;
1641 address.objectSubId = attnum;
1642
1643 *relp = relation;
1644 return address;
1645}
1646
1647/*
1648 * Find the ObjectAddress for an attribute's default value.
1649 */
1650static ObjectAddress
1652 Relation *relp, LOCKMODE lockmode,
1653 bool missing_ok)
1654{
1655 ObjectAddress address;
1656 List *relname;
1657 Oid reloid;
1658 Relation relation;
1659 const char *attname;
1661 TupleDesc tupdesc;
1662 Oid defoid;
1663
1664 /* Extract relation name and open relation. */
1665 if (list_length(object) < 2)
1666 ereport(ERROR,
1668 errmsg("column name must be qualified")));
1669 attname = strVal(llast(object));
1670 relname = list_copy_head(object, list_length(object) - 1);
1671 /* XXX no missing_ok support here */
1672 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1673 reloid = RelationGetRelid(relation);
1674
1675 tupdesc = RelationGetDescr(relation);
1676
1677 /* Look up attribute number and fetch the pg_attrdef OID */
1678 attnum = get_attnum(reloid, attname);
1680 if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
1681 defoid = GetAttrDefaultOid(reloid, attnum);
1682 if (!OidIsValid(defoid))
1683 {
1684 if (!missing_ok)
1685 ereport(ERROR,
1687 errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
1689
1691 address.objectId = InvalidOid;
1693 relation_close(relation, lockmode);
1694 return address;
1695 }
1696
1698 address.objectId = defoid;
1699 address.objectSubId = 0;
1700
1701 *relp = relation;
1702 return address;
1703}
1704
1705/*
1706 * Find the ObjectAddress for a type or domain
1707 */
1708static ObjectAddress
1709get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
1710{
1711 ObjectAddress address;
1712 Type tup;
1713
1714 address.classId = TypeRelationId;
1715 address.objectId = InvalidOid;
1716 address.objectSubId = 0;
1717
1718 tup = LookupTypeName(NULL, typename, NULL, missing_ok);
1719 if (!HeapTupleIsValid(tup))
1720 {
1721 if (!missing_ok)
1722 ereport(ERROR,
1724 errmsg("type \"%s\" does not exist",
1725 TypeNameToString(typename))));
1726 return address;
1727 }
1728 address.objectId = typeTypeId(tup);
1729
1730 if (objtype == OBJECT_DOMAIN)
1731 {
1732 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
1733 ereport(ERROR,
1735 errmsg("\"%s\" is not a domain",
1736 TypeNameToString(typename))));
1737 }
1738
1740
1741 return address;
1742}
1743
1744/*
1745 * Find the ObjectAddress for an opclass or opfamily.
1746 */
1747static ObjectAddress
1748get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
1749{
1750 Oid amoid;
1751 ObjectAddress address;
1752
1753 /* XXX no missing_ok support here */
1754 amoid = get_index_am_oid(strVal(linitial(object)), false);
1755 object = list_copy_tail(object, 1);
1756
1757 switch (objtype)
1758 {
1759 case OBJECT_OPCLASS:
1761 address.objectId = get_opclass_oid(amoid, object, missing_ok);
1762 address.objectSubId = 0;
1763 break;
1764 case OBJECT_OPFAMILY:
1766 address.objectId = get_opfamily_oid(amoid, object, missing_ok);
1767 address.objectSubId = 0;
1768 break;
1769 default:
1770 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1771 /* placate compiler, which doesn't know elog won't return */
1772 address.classId = InvalidOid;
1773 address.objectId = InvalidOid;
1774 address.objectSubId = 0;
1775 }
1776
1777 return address;
1778}
1779
1780/*
1781 * Find the ObjectAddress for an opclass/opfamily member.
1782 *
1783 * (The returned address corresponds to a pg_amop/pg_amproc object).
1784 */
1785static ObjectAddress
1787 List *object, bool missing_ok)
1788{
1790 ObjectAddress address;
1791 ListCell *cell;
1792 List *copy;
1793 TypeName *typenames[2];
1794 Oid typeoids[2];
1795 int membernum;
1796 int i;
1797
1798 /*
1799 * The last element of the object list contains the strategy or procedure
1800 * number. We need to strip that out before getting the opclass/family
1801 * address. The rest can be used directly by get_object_address_opcf().
1802 */
1803 membernum = atoi(strVal(llast(linitial(object))));
1804 copy = list_copy_head(linitial(object), list_length(linitial(object)) - 1);
1805
1806 /* no missing_ok support here */
1808
1809 /* find out left/right type names and OIDs */
1810 typenames[0] = typenames[1] = NULL;
1811 typeoids[0] = typeoids[1] = InvalidOid;
1812 i = 0;
1813 foreach(cell, lsecond(object))
1814 {
1816
1817 typenames[i] = lfirst_node(TypeName, cell);
1819 typeoids[i] = typaddr.objectId;
1820 if (++i >= 2)
1821 break;
1822 }
1823
1824 switch (objtype)
1825 {
1826 case OBJECT_AMOP:
1827 {
1828 HeapTuple tp;
1829
1831 InvalidOid);
1832
1834 ObjectIdGetDatum(famaddr.objectId),
1838 if (!HeapTupleIsValid(tp))
1839 {
1840 if (!missing_ok)
1841 ereport(ERROR,
1843 errmsg("operator %d (%s, %s) of %s does not exist",
1844 membernum,
1847 getObjectDescription(&famaddr, false))));
1848 }
1849 else
1850 {
1851 address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
1852 ReleaseSysCache(tp);
1853 }
1854 }
1855 break;
1856
1857 case OBJECT_AMPROC:
1858 {
1859 HeapTuple tp;
1860
1862 InvalidOid);
1863
1865 ObjectIdGetDatum(famaddr.objectId),
1869 if (!HeapTupleIsValid(tp))
1870 {
1871 if (!missing_ok)
1872 ereport(ERROR,
1874 errmsg("function %d (%s, %s) of %s does not exist",
1875 membernum,
1878 getObjectDescription(&famaddr, false))));
1879 }
1880 else
1881 {
1882 address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
1883 ReleaseSysCache(tp);
1884 }
1885 }
1886 break;
1887 default:
1888 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1889 }
1890
1891 return address;
1892}
1893
1894/*
1895 * Find the ObjectAddress for a user mapping.
1896 */
1897static ObjectAddress
1898get_object_address_usermapping(List *object, bool missing_ok)
1899{
1900 ObjectAddress address;
1901 Oid userid;
1902 char *username;
1903 char *servername;
1904 ForeignServer *server;
1905 HeapTuple tp;
1906
1908
1909 /* fetch string names from input lists, for error messages */
1910 username = strVal(linitial(object));
1911 servername = strVal(lsecond(object));
1912
1913 /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
1914 if (strcmp(username, "public") == 0)
1915 userid = InvalidOid;
1916 else
1917 {
1920 if (!HeapTupleIsValid(tp))
1921 {
1922 if (!missing_ok)
1923 ereport(ERROR,
1925 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1926 username, servername)));
1927 return address;
1928 }
1929 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
1930 ReleaseSysCache(tp);
1931 }
1932
1933 /* Now look up the pg_user_mapping tuple */
1934 server = GetForeignServerByName(servername, true);
1935 if (!server)
1936 {
1937 if (!missing_ok)
1938 ereport(ERROR,
1940 errmsg("server \"%s\" does not exist", servername)));
1941 return address;
1942 }
1944 ObjectIdGetDatum(userid),
1945 ObjectIdGetDatum(server->serverid));
1946 if (!HeapTupleIsValid(tp))
1947 {
1948 if (!missing_ok)
1949 ereport(ERROR,
1951 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1952 username, servername)));
1953 return address;
1954 }
1955
1956 address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
1957
1958 ReleaseSysCache(tp);
1959
1960 return address;
1961}
1962
1963/*
1964 * Find the ObjectAddress for a publication relation. The first element of
1965 * the object parameter is the relation name, the second is the
1966 * publication name.
1967 */
1968static ObjectAddress
1970 Relation *relp, bool missing_ok)
1971{
1972 ObjectAddress address;
1973 Relation relation;
1974 List *relname;
1975 char *pubname;
1976 Publication *pub;
1977
1979
1980 relname = linitial(object);
1982 AccessShareLock, missing_ok);
1983 if (!relation)
1984 return address;
1985
1986 /* fetch publication name from input list */
1987 pubname = strVal(lsecond(object));
1988
1989 /* Now look up the pg_publication tuple */
1990 pub = GetPublicationByName(pubname, missing_ok);
1991 if (!pub)
1992 {
1994 return address;
1995 }
1996
1997 /* Find the publication relation mapping in syscache. */
1998 address.objectId =
2001 ObjectIdGetDatum(pub->oid));
2002 if (!OidIsValid(address.objectId))
2003 {
2004 if (!missing_ok)
2005 ereport(ERROR,
2007 errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
2008 RelationGetRelationName(relation), pubname)));
2010 return address;
2011 }
2012
2013 *relp = relation;
2014 return address;
2015}
2016
2017/*
2018 * Find the ObjectAddress for a publication schema. The first element of the
2019 * object parameter is the schema name, the second is the publication name.
2020 */
2021static ObjectAddress
2023{
2024 ObjectAddress address;
2025 Publication *pub;
2026 char *pubname;
2027 char *schemaname;
2028 Oid schemaid;
2029
2031
2032 /* Fetch schema name and publication name from input list */
2033 schemaname = strVal(linitial(object));
2034 pubname = strVal(lsecond(object));
2035
2036 schemaid = get_namespace_oid(schemaname, missing_ok);
2037 if (!OidIsValid(schemaid))
2038 return address;
2039
2040 /* Now look up the pg_publication tuple */
2041 pub = GetPublicationByName(pubname, missing_ok);
2042 if (!pub)
2043 return address;
2044
2045 /* Find the publication schema mapping in syscache */
2046 address.objectId =
2050 ObjectIdGetDatum(pub->oid));
2051 if (!OidIsValid(address.objectId) && !missing_ok)
2052 ereport(ERROR,
2054 errmsg("publication schema \"%s\" in publication \"%s\" does not exist",
2055 schemaname, pubname)));
2056
2057 return address;
2058}
2059
2060/*
2061 * Find the ObjectAddress for a default ACL.
2062 */
2063static ObjectAddress
2064get_object_address_defacl(List *object, bool missing_ok)
2065{
2066 HeapTuple tp;
2067 Oid userid;
2068 Oid schemaid;
2069 char *username;
2070 char *schema;
2071 char objtype;
2072 char *objtype_str;
2073 ObjectAddress address;
2074
2076
2077 /*
2078 * First figure out the textual attributes so that they can be used for
2079 * error reporting.
2080 */
2081 username = strVal(lsecond(object));
2082 if (list_length(object) >= 3)
2083 schema = (char *) strVal(lthird(object));
2084 else
2085 schema = NULL;
2086
2087 /*
2088 * Decode defaclobjtype. Only first char is considered; the rest of the
2089 * string, if any, is blissfully ignored.
2090 */
2091 objtype = ((char *) strVal(linitial(object)))[0];
2092 switch (objtype)
2093 {
2094 case DEFACLOBJ_RELATION:
2095 objtype_str = "tables";
2096 break;
2097 case DEFACLOBJ_SEQUENCE:
2098 objtype_str = "sequences";
2099 break;
2100 case DEFACLOBJ_FUNCTION:
2101 objtype_str = "functions";
2102 break;
2103 case DEFACLOBJ_TYPE:
2104 objtype_str = "types";
2105 break;
2107 objtype_str = "schemas";
2108 break;
2110 objtype_str = "large objects";
2111 break;
2112 default:
2113 ereport(ERROR,
2115 errmsg("unrecognized default ACL object type \"%c\"", objtype),
2116 errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
2123 }
2124
2125 /*
2126 * Look up user ID. Behave as "default ACL not found" if the user doesn't
2127 * exist.
2128 */
2131 if (!HeapTupleIsValid(tp))
2132 goto not_found;
2133 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
2134 ReleaseSysCache(tp);
2135
2136 /*
2137 * If a schema name was given, look up its OID. If it doesn't exist,
2138 * behave as "default ACL not found".
2139 */
2140 if (schema)
2141 {
2142 schemaid = get_namespace_oid(schema, true);
2143 if (schemaid == InvalidOid)
2144 goto not_found;
2145 }
2146 else
2148
2149 /* Finally, look up the pg_default_acl object */
2151 ObjectIdGetDatum(userid),
2153 CharGetDatum(objtype));
2154 if (!HeapTupleIsValid(tp))
2155 goto not_found;
2156
2157 address.objectId = ((Form_pg_default_acl) GETSTRUCT(tp))->oid;
2158 ReleaseSysCache(tp);
2159
2160 return address;
2161
2162not_found:
2163 if (!missing_ok)
2164 {
2165 if (schema)
2166 ereport(ERROR,
2168 errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
2169 username, schema, objtype_str)));
2170 else
2171 ereport(ERROR,
2173 errmsg("default ACL for user \"%s\" on %s does not exist",
2175 }
2176 return address;
2177}
2178
2179/*
2180 * Convert an array of TEXT into a List of string Values, as emitted by the
2181 * parser, which is what get_object_address uses as input.
2182 */
2183static List *
2185{
2186 Datum *elems;
2187 bool *nulls;
2188 int nelems;
2189 List *list = NIL;
2190 int i;
2191
2192 deconstruct_array_builtin(arr, TEXTOID, &elems, &nulls, &nelems);
2193
2194 for (i = 0; i < nelems; i++)
2195 {
2196 if (nulls[i])
2197 ereport(ERROR,
2199 errmsg("name or argument lists may not contain nulls")));
2200 list = lappend(list, makeString(TextDatumGetCString(elems[i])));
2201 }
2202
2203 return list;
2204}
2205
2206/*
2207 * SQL-callable version of get_object_address
2208 */
2209Datum
2211{
2212 char *ttype = TextDatumGetCString(PG_GETARG_DATUM(0));
2215 int itype;
2217 List *name = NIL;
2218 TypeName *typename = NULL;
2219 List *args = NIL;
2220 Node *objnode = NULL;
2221 ObjectAddress addr;
2222 TupleDesc tupdesc;
2223 Datum values[3];
2224 bool nulls[3];
2225 HeapTuple htup;
2226 Relation relation;
2227
2228 /* Decode object type, raise error if unknown */
2230 if (itype < 0)
2231 ereport(ERROR,
2233 errmsg("unsupported object type \"%s\"", ttype)));
2234 type = (ObjectType) itype;
2235
2236 /*
2237 * Convert the text array to the representation appropriate for the given
2238 * object type. Most use a simple string Values list, but there are some
2239 * exceptions.
2240 */
2241 if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
2243 {
2244 Datum *elems;
2245 bool *nulls;
2246 int nelems;
2247
2248 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2249 if (nelems != 1)
2250 ereport(ERROR,
2252 errmsg("name list length must be exactly %d", 1)));
2253 if (nulls[0])
2254 ereport(ERROR,
2256 errmsg("name or argument lists may not contain nulls")));
2257 typename = typeStringToTypeName(TextDatumGetCString(elems[0]), NULL);
2258 }
2259 else if (type == OBJECT_LARGEOBJECT)
2260 {
2261 Datum *elems;
2262 bool *nulls;
2263 int nelems;
2264
2265 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2266 if (nelems != 1)
2267 ereport(ERROR,
2269 errmsg("name list length must be exactly %d", 1)));
2270 if (nulls[0])
2271 ereport(ERROR,
2273 errmsg("large object OID may not be null")));
2274 objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
2275 }
2276 else
2277 {
2279 if (name == NIL)
2280 ereport(ERROR,
2282 errmsg("name list length must be at least %d", 1)));
2283 }
2284
2285 /*
2286 * If args are given, decode them according to the object type.
2287 */
2288 if (type == OBJECT_AGGREGATE ||
2289 type == OBJECT_FUNCTION ||
2291 type == OBJECT_ROUTINE ||
2292 type == OBJECT_OPERATOR ||
2293 type == OBJECT_CAST ||
2294 type == OBJECT_AMOP ||
2296 {
2297 /* in these cases, the args list must be of TypeName */
2298 Datum *elems;
2299 bool *nulls;
2300 int nelems;
2301 int i;
2302
2303 deconstruct_array_builtin(argsarr, TEXTOID, &elems, &nulls, &nelems);
2304
2305 args = NIL;
2306 for (i = 0; i < nelems; i++)
2307 {
2308 if (nulls[i])
2309 ereport(ERROR,
2311 errmsg("name or argument lists may not contain nulls")));
2312 args = lappend(args,
2314 NULL));
2315 }
2316 }
2317 else
2318 {
2319 /* For all other object types, use string Values */
2321 }
2322
2323 /*
2324 * get_object_address is pretty sensitive to the length of its input
2325 * lists; check that they're what it wants.
2326 */
2327 switch (type)
2328 {
2331 if (list_length(name) != 1)
2332 ereport(ERROR,
2334 errmsg("name list length must be exactly %d", 1)));
2335 /* fall through to check args length */
2338 case OBJECT_CAST:
2340 case OBJECT_DEFACL:
2341 case OBJECT_TRANSFORM:
2342 if (list_length(args) != 1)
2343 ereport(ERROR,
2345 errmsg("argument list length must be exactly %d", 1)));
2346 break;
2347 case OBJECT_OPFAMILY:
2348 case OBJECT_OPCLASS:
2349 if (list_length(name) < 2)
2350 ereport(ERROR,
2352 errmsg("name list length must be at least %d", 2)));
2353 break;
2354 case OBJECT_AMOP:
2355 case OBJECT_AMPROC:
2356 if (list_length(name) < 3)
2357 ereport(ERROR,
2359 errmsg("name list length must be at least %d", 3)));
2360 /* fall through to check args length */
2362 case OBJECT_OPERATOR:
2363 if (list_length(args) != 2)
2364 ereport(ERROR,
2366 errmsg("argument list length must be exactly %d", 2)));
2367 break;
2368 default:
2369 break;
2370 }
2371
2372 /*
2373 * Now build the Node type that get_object_address() expects for the given
2374 * type.
2375 */
2376 switch (type)
2377 {
2378 case OBJECT_TABLE:
2379 case OBJECT_SEQUENCE:
2380 case OBJECT_VIEW:
2381 case OBJECT_MATVIEW:
2382 case OBJECT_INDEX:
2384 case OBJECT_PROPGRAPH:
2385 case OBJECT_COLUMN:
2386 case OBJECT_ATTRIBUTE:
2387 case OBJECT_COLLATION:
2388 case OBJECT_CONVERSION:
2390 case OBJECT_TSPARSER:
2392 case OBJECT_TSTEMPLATE:
2394 case OBJECT_DEFAULT:
2395 case OBJECT_POLICY:
2396 case OBJECT_RULE:
2397 case OBJECT_TRIGGER:
2399 case OBJECT_OPCLASS:
2400 case OBJECT_OPFAMILY:
2401 objnode = (Node *) name;
2402 break;
2404 case OBJECT_DATABASE:
2406 case OBJECT_EXTENSION:
2407 case OBJECT_FDW:
2409 case OBJECT_LANGUAGE:
2411 case OBJECT_PUBLICATION:
2412 case OBJECT_ROLE:
2413 case OBJECT_SCHEMA:
2415 case OBJECT_TABLESPACE:
2416 if (list_length(name) != 1)
2417 ereport(ERROR,
2419 errmsg("name list length must be exactly %d", 1)));
2421 break;
2422 case OBJECT_TYPE:
2423 case OBJECT_DOMAIN:
2424 objnode = (Node *) typename;
2425 break;
2426 case OBJECT_CAST:
2428 case OBJECT_TRANSFORM:
2429 objnode = (Node *) list_make2(typename, linitial(args));
2430 break;
2432 objnode = (Node *) list_make2(name, linitial(args));
2433 break;
2437 break;
2438 case OBJECT_DEFACL:
2439 objnode = (Node *) lcons(linitial(args), name);
2440 break;
2441 case OBJECT_AMOP:
2442 case OBJECT_AMPROC:
2443 objnode = (Node *) list_make2(name, args);
2444 break;
2445 case OBJECT_FUNCTION:
2446 case OBJECT_PROCEDURE:
2447 case OBJECT_ROUTINE:
2448 case OBJECT_AGGREGATE:
2449 case OBJECT_OPERATOR:
2450 {
2452
2453 owa->objname = name;
2454 owa->objargs = args;
2455 objnode = (Node *) owa;
2456 break;
2457 }
2458 case OBJECT_LARGEOBJECT:
2459 /* already handled above */
2460 break;
2461 /* no default, to let compiler warn about missing case */
2462 }
2463
2464 if (objnode == NULL)
2465 elog(ERROR, "unrecognized object type: %d", type);
2466
2468 &relation, AccessShareLock, false);
2469
2470 /* We don't need the relcache entry, thank you very much */
2471 if (relation)
2473
2474 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2475 elog(ERROR, "return type must be a row type");
2476
2477 values[0] = ObjectIdGetDatum(addr.classId);
2478 values[1] = ObjectIdGetDatum(addr.objectId);
2479 values[2] = Int32GetDatum(addr.objectSubId);
2480 nulls[0] = false;
2481 nulls[1] = false;
2482 nulls[2] = false;
2483
2484 htup = heap_form_tuple(tupdesc, values, nulls);
2485
2487}
2488
2489/*
2490 * Check ownership of an object previously identified by get_object_address.
2491 */
2492void
2494 Node *object, Relation relation)
2495{
2496 switch (objtype)
2497 {
2498 case OBJECT_INDEX:
2499 case OBJECT_SEQUENCE:
2500 case OBJECT_TABLE:
2501 case OBJECT_VIEW:
2502 case OBJECT_MATVIEW:
2504 case OBJECT_PROPGRAPH:
2505 case OBJECT_COLUMN:
2506 case OBJECT_RULE:
2507 case OBJECT_TRIGGER:
2508 case OBJECT_POLICY:
2510 if (!object_ownercheck(RelationRelationId, RelationGetRelid(relation), roleid))
2512 RelationGetRelationName(relation));
2513 break;
2514 case OBJECT_TYPE:
2515 case OBJECT_DOMAIN:
2516 case OBJECT_ATTRIBUTE:
2517 if (!object_ownercheck(address.classId, address.objectId, roleid))
2519 break;
2521 {
2522 HeapTuple tuple;
2523 Oid contypid;
2524
2525 tuple = SearchSysCache1(CONSTROID,
2526 ObjectIdGetDatum(address.objectId));
2527 if (!HeapTupleIsValid(tuple))
2528 elog(ERROR, "constraint with OID %u does not exist",
2529 address.objectId);
2530
2532
2533 ReleaseSysCache(tuple);
2534
2535 /*
2536 * Fallback to type ownership check in this case as this is
2537 * what domain constraints rely on.
2538 */
2541 }
2542 break;
2543 case OBJECT_AGGREGATE:
2544 case OBJECT_FUNCTION:
2545 case OBJECT_PROCEDURE:
2546 case OBJECT_ROUTINE:
2547 case OBJECT_OPERATOR:
2548 if (!object_ownercheck(address.classId, address.objectId, roleid))
2550 NameListToString((castNode(ObjectWithArgs, object))->objname));
2551 break;
2552 case OBJECT_DATABASE:
2554 case OBJECT_EXTENSION:
2555 case OBJECT_FDW:
2557 case OBJECT_LANGUAGE:
2558 case OBJECT_PUBLICATION:
2559 case OBJECT_SCHEMA:
2561 case OBJECT_TABLESPACE:
2562 if (!object_ownercheck(address.classId, address.objectId, roleid))
2564 strVal(object));
2565 break;
2566 case OBJECT_COLLATION:
2567 case OBJECT_CONVERSION:
2568 case OBJECT_OPCLASS:
2569 case OBJECT_OPFAMILY:
2573 if (!object_ownercheck(address.classId, address.objectId, roleid))
2575 NameListToString(castNode(List, object)));
2576 break;
2577 case OBJECT_LARGEOBJECT:
2578 if (!lo_compat_privileges &&
2579 !object_ownercheck(address.classId, address.objectId, roleid))
2580 ereport(ERROR,
2582 errmsg("must be owner of large object %u",
2583 address.objectId)));
2584 break;
2585 case OBJECT_CAST:
2586 {
2587 /* We can only check permissions on the source/target types */
2588 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
2589 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
2590 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
2591 Oid targettypeid = typenameTypeId(NULL, targettype);
2592
2595 ereport(ERROR,
2597 errmsg("must be owner of type %s or type %s",
2600 }
2601 break;
2602 case OBJECT_TRANSFORM:
2603 {
2604 TypeName *typename = linitial_node(TypeName, castNode(List, object));
2605 Oid typeid = typenameTypeId(NULL, typename);
2606
2607 if (!object_ownercheck(TypeRelationId, typeid, roleid))
2609 }
2610 break;
2611 case OBJECT_ROLE:
2612
2613 /*
2614 * We treat roles as being "owned" by those with CREATEROLE priv,
2615 * provided that they also have admin option on the role.
2616 *
2617 * However, superusers are only owned by superusers.
2618 */
2619 if (superuser_arg(address.objectId))
2620 {
2621 if (!superuser_arg(roleid))
2622 ereport(ERROR,
2624 errmsg("permission denied"),
2625 errdetail("The current user must have the %s attribute.",
2626 "SUPERUSER")));
2627 }
2628 else
2629 {
2630 if (!has_createrole_privilege(roleid))
2631 ereport(ERROR,
2633 errmsg("permission denied"),
2634 errdetail("The current user must have the %s attribute.",
2635 "CREATEROLE")));
2636 if (!is_admin_of_role(roleid, address.objectId))
2637 ereport(ERROR,
2639 errmsg("permission denied"),
2640 errdetail("The current user must have the %s option on role \"%s\".",
2641 "ADMIN",
2643 true))));
2644 }
2645 break;
2646 case OBJECT_TSPARSER:
2647 case OBJECT_TSTEMPLATE:
2650 /* We treat these object types as being owned by superusers */
2651 if (!superuser_arg(roleid))
2652 ereport(ERROR,
2654 errmsg("must be superuser")));
2655 break;
2656 case OBJECT_AMOP:
2657 case OBJECT_AMPROC:
2658 case OBJECT_DEFAULT:
2659 case OBJECT_DEFACL:
2663 /* These are currently not supported or don't make sense here. */
2664 elog(ERROR, "unsupported object type: %d", (int) objtype);
2665 break;
2666 }
2667}
2668
2669/*
2670 * get_object_namespace
2671 *
2672 * Find the schema containing the specified object. For non-schema objects,
2673 * this function returns InvalidOid.
2674 */
2675Oid
2677{
2678 SysCacheIdentifier cache;
2679 HeapTuple tuple;
2680 Oid oid;
2682
2683 /* If not owned by a namespace, just return InvalidOid. */
2684 property = get_object_property_data(address->classId);
2685 if (property->attnum_namespace == InvalidAttrNumber)
2686 return InvalidOid;
2687
2688 /* Currently, we can only handle object types with system caches. */
2689 cache = property->oid_catcache_id;
2690 Assert(cache != SYSCACHEID_INVALID);
2691
2692 /* Fetch tuple from syscache and extract namespace attribute. */
2693 tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
2694 if (!HeapTupleIsValid(tuple))
2695 elog(ERROR, "cache lookup failed for cache %d oid %u",
2696 cache, address->objectId);
2698 tuple,
2699 property->attnum_namespace));
2700 ReleaseSysCache(tuple);
2701
2702 return oid;
2703}
2704
2705/*
2706 * Return ObjectType for the given object type as given by
2707 * getObjectTypeDescription; if no valid ObjectType code exists, but it's a
2708 * possible output type from getObjectTypeDescription, return -1.
2709 * Otherwise, an error is thrown.
2710 */
2711int
2712read_objtype_from_string(const char *objtype)
2713{
2714 int i;
2715
2716 for (i = 0; i < lengthof(ObjectTypeMap); i++)
2717 {
2718 if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
2719 return ObjectTypeMap[i].tm_type;
2720 }
2721 ereport(ERROR,
2723 errmsg("unrecognized object type \"%s\"", objtype)));
2724
2725 return -1; /* keep compiler quiet */
2726}
2727
2728/*
2729 * Interfaces to reference fields of ObjectPropertyType
2730 */
2731const char *
2738
2739Oid
2746
2754
2762
2765{
2767
2768 return prop->attnum_oid;
2769}
2770
2778
2786
2794
2797{
2799
2800 return prop->attnum_acl;
2801}
2802
2803/*
2804 * get_object_type
2805 *
2806 * Return the object type associated with a given object. This routine
2807 * is primarily used to determine the object type to mention in ACL check
2808 * error messages, so it's desirable for it to avoid failing.
2809 */
2812{
2814
2815 if (prop->objtype == OBJECT_TABLE)
2816 {
2817 /*
2818 * If the property data says it's a table, dig a little deeper to get
2819 * the real relation kind, so that callers can produce more precise
2820 * error messages.
2821 */
2822 return get_relkind_objtype(get_rel_relkind(object_id));
2823 }
2824 else
2825 return prop->objtype;
2826}
2827
2828bool
2835
2836/*
2837 * Return whether we have useful data for the given object class in the
2838 * ObjectProperty table.
2839 */
2840bool
2842{
2843 int index;
2844
2845 for (index = 0; index < lengthof(ObjectProperty); index++)
2846 {
2847 if (ObjectProperty[index].class_oid == class_id)
2848 return true;
2849 }
2850
2851 return false;
2852}
2853
2854/*
2855 * Find ObjectProperty structure by class_id.
2856 */
2857static const ObjectPropertyType *
2859{
2860 static const ObjectPropertyType *prop_last = NULL;
2861 int index;
2862
2863 /*
2864 * A shortcut to speed up multiple consecutive lookups of a particular
2865 * object class.
2866 */
2867 if (prop_last && prop_last->class_oid == class_id)
2868 return prop_last;
2869
2870 for (index = 0; index < lengthof(ObjectProperty); index++)
2871 {
2872 if (ObjectProperty[index].class_oid == class_id)
2873 {
2875 return &ObjectProperty[index];
2876 }
2877 }
2878
2879 ereport(ERROR,
2880 (errmsg_internal("unrecognized class ID: %u", class_id)));
2881
2882 return NULL; /* keep MSC compiler happy */
2883}
2884
2885/*
2886 * Return a copy of the tuple for the object with the given object OID, from
2887 * the given catalog (which must have been opened by the caller and suitably
2888 * locked). NULL is returned if the OID is not found.
2889 *
2890 * We try a syscache first, if available.
2891 */
2898
2899/*
2900 * Same as get_catalog_object_by_oid(), but with an additional "locktup"
2901 * argument controlling whether to acquire a LOCKTAG_TUPLE at mode
2902 * InplaceUpdateTupleLock. See README.tuplock section "Locking to write
2903 * inplace-updated tables".
2904 */
2908 Oid objectId,
2909 bool locktup)
2910{
2911 HeapTuple tuple;
2912 Oid classId = RelationGetRelid(catalog);
2914
2915 if (oidCacheId >= 0)
2916 {
2917 if (locktup)
2919 ObjectIdGetDatum(objectId));
2920 else
2922 ObjectIdGetDatum(objectId));
2923 if (!HeapTupleIsValid(tuple)) /* should not happen */
2924 return NULL;
2925 }
2926 else
2927 {
2929 SysScanDesc scan;
2931
2933
2935 oidcol,
2937 ObjectIdGetDatum(objectId));
2938
2940 NULL, 1, &skey);
2941 tuple = systable_getnext(scan);
2942 if (!HeapTupleIsValid(tuple))
2943 {
2944 systable_endscan(scan);
2945 return NULL;
2946 }
2947
2948 if (locktup)
2950
2951 tuple = heap_copytuple(tuple);
2952
2953 systable_endscan(scan);
2954 }
2955
2956 return tuple;
2957}
2958
2959/*
2960 * getPublicationSchemaInfo
2961 *
2962 * Get publication name and schema name from the object address into pubname and
2963 * nspname. Both pubname and nspname are palloc'd strings which will be freed by
2964 * the caller.
2965 */
2966static bool
2967getPublicationSchemaInfo(const ObjectAddress *object, bool missing_ok,
2968 char **pubname, char **nspname)
2969{
2970 HeapTuple tup;
2972
2974 ObjectIdGetDatum(object->objectId));
2975 if (!HeapTupleIsValid(tup))
2976 {
2977 if (!missing_ok)
2978 elog(ERROR, "cache lookup failed for publication schema %u",
2979 object->objectId);
2980 return false;
2981 }
2982
2984 *pubname = get_publication_name(pnform->pnpubid, missing_ok);
2985 if (!(*pubname))
2986 {
2988 return false;
2989 }
2990
2991 *nspname = get_namespace_name(pnform->pnnspid);
2992 if (!(*nspname))
2993 {
2994 Oid schemaid = pnform->pnnspid;
2995
2996 pfree(*pubname);
2998 if (!missing_ok)
2999 elog(ERROR, "cache lookup failed for schema %u",
3000 schemaid);
3001 return false;
3002 }
3003
3005 return true;
3006}
3007
3008/*
3009 * getObjectDescription: build an object description for messages
3010 *
3011 * The result is a palloc'd string. NULL is returned for an undefined
3012 * object if missing_ok is true, else an error is generated.
3013 */
3014char *
3015getObjectDescription(const ObjectAddress *object, bool missing_ok)
3016{
3017 StringInfoData buffer;
3018
3019 initStringInfo(&buffer);
3020
3021 switch (object->classId)
3022 {
3023 case RelationRelationId:
3024 if (object->objectSubId == 0)
3025 getRelationDescription(&buffer, object->objectId, missing_ok);
3026 else
3027 {
3028 /* column, not whole relation */
3029 StringInfoData rel;
3030 char *attname = get_attname(object->objectId,
3031 object->objectSubId,
3032 missing_ok);
3033
3034 if (!attname)
3035 break;
3036
3037 initStringInfo(&rel);
3038 getRelationDescription(&rel, object->objectId, missing_ok);
3039 /* translator: second %s is, e.g., "table %s" */
3040 appendStringInfo(&buffer, _("column %s of %s"),
3041 attname, rel.data);
3042 pfree(rel.data);
3043 }
3044 break;
3045
3047 {
3050 flags);
3051
3052 if (proname == NULL)
3053 break;
3054
3055 appendStringInfo(&buffer, _("function %s"), proname);
3056 break;
3057 }
3058
3059 case TypeRelationId:
3060 {
3062 char *typname = format_type_extended(object->objectId, -1,
3063 flags);
3064
3065 if (typname == NULL)
3066 break;
3067
3068 appendStringInfo(&buffer, _("type %s"), typname);
3069 break;
3070 }
3071
3072 case CastRelationId:
3073 {
3075 ScanKeyData skey[1];
3077 HeapTuple tup;
3079
3081
3082 ScanKeyInit(&skey[0],
3085 ObjectIdGetDatum(object->objectId));
3086
3088 NULL, 1, skey);
3089
3091
3092 if (!HeapTupleIsValid(tup))
3093 {
3094 if (!missing_ok)
3095 elog(ERROR, "could not find tuple for cast %u",
3096 object->objectId);
3097
3100 break;
3101 }
3102
3104
3105 appendStringInfo(&buffer, _("cast from %s to %s"),
3106 format_type_be(castForm->castsource),
3107 format_type_be(castForm->casttarget));
3108
3111 break;
3112 }
3113
3115 {
3117 Form_pg_collation coll;
3118 char *nspname;
3119
3121 ObjectIdGetDatum(object->objectId));
3123 {
3124 if (!missing_ok)
3125 elog(ERROR, "cache lookup failed for collation %u",
3126 object->objectId);
3127 break;
3128 }
3129
3131
3132 /* Qualify the name if not visible in search path */
3133 if (CollationIsVisible(object->objectId))
3134 nspname = NULL;
3135 else
3136 nspname = get_namespace_name(coll->collnamespace);
3137
3138 appendStringInfo(&buffer, _("collation %s"),
3140 NameStr(coll->collname)));
3142 break;
3143 }
3144
3146 {
3149
3151 ObjectIdGetDatum(object->objectId));
3153 {
3154 if (!missing_ok)
3155 elog(ERROR, "cache lookup failed for constraint %u",
3156 object->objectId);
3157 break;
3158 }
3159
3161
3162 if (OidIsValid(con->conrelid))
3163 {
3164 StringInfoData rel;
3165
3166 initStringInfo(&rel);
3167 getRelationDescription(&rel, con->conrelid, false);
3168 /* translator: second %s is, e.g., "table %s" */
3169 appendStringInfo(&buffer, _("constraint %s on %s"),
3170 NameStr(con->conname), rel.data);
3171 pfree(rel.data);
3172 }
3173 else
3174 {
3175 appendStringInfo(&buffer, _("constraint %s"),
3176 NameStr(con->conname));
3177 }
3178
3180 break;
3181 }
3182
3184 {
3187 char *nspname;
3188
3190 ObjectIdGetDatum(object->objectId));
3192 {
3193 if (!missing_ok)
3194 elog(ERROR, "cache lookup failed for conversion %u",
3195 object->objectId);
3196 break;
3197 }
3198
3200
3201 /* Qualify the name if not visible in search path */
3202 if (ConversionIsVisible(object->objectId))
3203 nspname = NULL;
3204 else
3205 nspname = get_namespace_name(conv->connamespace);
3206
3207 appendStringInfo(&buffer, _("conversion %s"),
3209 NameStr(conv->conname)));
3211 break;
3212 }
3213
3215 {
3217
3219
3220 if (!OidIsValid(colobject.objectId))
3221 {
3222 if (!missing_ok)
3223 elog(ERROR, "could not find tuple for attrdef %u",
3224 object->objectId);
3225 break;
3226 }
3227
3228 /* translator: %s is typically "column %s of table %s" */
3229 appendStringInfo(&buffer, _("default value for %s"),
3231 break;
3232 }
3233
3234 case LanguageRelationId:
3235 {
3236 char *langname = get_language_name(object->objectId,
3237 missing_ok);
3238
3239 if (langname)
3240 appendStringInfo(&buffer, _("language %s"),
3241 get_language_name(object->objectId, false));
3242 break;
3243 }
3244
3246 if (!LargeObjectExists(object->objectId))
3247 break;
3248 appendStringInfo(&buffer, _("large object %u"),
3249 object->objectId);
3250 break;
3251
3252 case OperatorRelationId:
3253 {
3255 char *oprname = format_operator_extended(object->objectId,
3256 flags);
3257
3258 if (oprname == NULL)
3259 break;
3260
3261 appendStringInfo(&buffer, _("operator %s"), oprname);
3262 break;
3263 }
3264
3266 {
3271 char *nspname;
3272
3274 ObjectIdGetDatum(object->objectId));
3276 {
3277 if (!missing_ok)
3278 elog(ERROR, "cache lookup failed for opclass %u",
3279 object->objectId);
3280 break;
3281 }
3282
3284
3286 ObjectIdGetDatum(opcForm->opcmethod));
3287 if (!HeapTupleIsValid(amTup))
3288 elog(ERROR, "cache lookup failed for access method %u",
3289 opcForm->opcmethod);
3291
3292 /* Qualify the name if not visible in search path */
3293 if (OpclassIsVisible(object->objectId))
3294 nspname = NULL;
3295 else
3296 nspname = get_namespace_name(opcForm->opcnamespace);
3297
3298 appendStringInfo(&buffer, _("operator class %s for access method %s"),
3300 NameStr(opcForm->opcname)),
3301 NameStr(amForm->amname));
3302
3305 break;
3306 }
3307
3309 getOpFamilyDescription(&buffer, object->objectId, missing_ok);
3310 break;
3311
3313 {
3314 HeapTuple tup;
3315
3317 ObjectIdGetDatum(object->objectId));
3318 if (!HeapTupleIsValid(tup))
3319 {
3320 if (!missing_ok)
3321 elog(ERROR, "cache lookup failed for access method %u",
3322 object->objectId);
3323 break;
3324 }
3325
3326 appendStringInfo(&buffer, _("access method %s"),
3327 NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
3329 break;
3330 }
3331
3333 {
3335 HeapTuple tup;
3336 ScanKeyData skey[1];
3339 StringInfoData opfam;
3340
3343
3344 ScanKeyInit(&skey[0],
3347 ObjectIdGetDatum(object->objectId));
3348
3350 NULL, 1, skey);
3351
3353
3354 if (!HeapTupleIsValid(tup))
3355 {
3356 if (!missing_ok)
3357 elog(ERROR, "could not find tuple for amop entry %u",
3358 object->objectId);
3359
3362 break;
3363 }
3364
3366
3367 initStringInfo(&opfam);
3368 getOpFamilyDescription(&opfam, amopForm->amopfamily, false);
3369
3370 /*
3371 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3372 * completely if the type links are dangling, which is a form
3373 * of catalog corruption that could occur due to old bugs.
3374 */
3375
3376 /*------
3377 translator: %d is the operator strategy (a number), the
3378 first two %s's are data type names, the third %s is the
3379 description of the operator family, and the last %s is the
3380 textual form of the operator with arguments. */
3381 appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
3382 amopForm->amopstrategy,
3383 format_type_extended(amopForm->amoplefttype,
3385 format_type_extended(amopForm->amoprighttype,
3387 opfam.data,
3388 format_operator(amopForm->amopopr));
3389
3390 pfree(opfam.data);
3391
3394 break;
3395 }
3396
3398 {
3400 ScanKeyData skey[1];
3402 HeapTuple tup;
3404 StringInfoData opfam;
3405
3408
3409 ScanKeyInit(&skey[0],
3412 ObjectIdGetDatum(object->objectId));
3413
3415 NULL, 1, skey);
3416
3418
3419 if (!HeapTupleIsValid(tup))
3420 {
3421 if (!missing_ok)
3422 elog(ERROR, "could not find tuple for amproc entry %u",
3423 object->objectId);
3424
3427 break;
3428 }
3429
3431
3432 initStringInfo(&opfam);
3433 getOpFamilyDescription(&opfam, amprocForm->amprocfamily, false);
3434
3435 /*
3436 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3437 * completely if the type links are dangling, which is a form
3438 * of catalog corruption that could occur due to old bugs.
3439 */
3440
3441 /*------
3442 translator: %d is the function number, the first two %s's
3443 are data type names, the third %s is the description of the
3444 operator family, and the last %s is the textual form of the
3445 function with arguments. */
3446 appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
3447 amprocForm->amprocnum,
3448 format_type_extended(amprocForm->amproclefttype,
3450 format_type_extended(amprocForm->amprocrighttype,
3452 opfam.data,
3453 format_procedure(amprocForm->amproc));
3454
3455 pfree(opfam.data);
3456
3459 break;
3460 }
3461
3462 case RewriteRelationId:
3463 {
3465 ScanKeyData skey[1];
3467 HeapTuple tup;
3469 StringInfoData rel;
3470
3472
3473 ScanKeyInit(&skey[0],
3476 ObjectIdGetDatum(object->objectId));
3477
3479 NULL, 1, skey);
3480
3482
3483 if (!HeapTupleIsValid(tup))
3484 {
3485 if (!missing_ok)
3486 elog(ERROR, "could not find tuple for rule %u",
3487 object->objectId);
3488
3491 break;
3492 }
3493
3495
3496 initStringInfo(&rel);
3497 getRelationDescription(&rel, rule->ev_class, false);
3498
3499 /* translator: second %s is, e.g., "table %s" */
3500 appendStringInfo(&buffer, _("rule %s on %s"),
3501 NameStr(rule->rulename), rel.data);
3502 pfree(rel.data);
3505 break;
3506 }
3507
3508 case TriggerRelationId:
3509 {
3511 ScanKeyData skey[1];
3513 HeapTuple tup;
3515 StringInfoData rel;
3516
3518
3519 ScanKeyInit(&skey[0],
3522 ObjectIdGetDatum(object->objectId));
3523
3525 NULL, 1, skey);
3526
3528
3529 if (!HeapTupleIsValid(tup))
3530 {
3531 if (!missing_ok)
3532 elog(ERROR, "could not find tuple for trigger %u",
3533 object->objectId);
3534
3537 break;
3538 }
3539
3541
3542 initStringInfo(&rel);
3543 getRelationDescription(&rel, trig->tgrelid, false);
3544
3545 /* translator: second %s is, e.g., "table %s" */
3546 appendStringInfo(&buffer, _("trigger %s on %s"),
3547 NameStr(trig->tgname), rel.data);
3548 pfree(rel.data);
3551 break;
3552 }
3553
3555 {
3556 char *nspname;
3557
3558 nspname = get_namespace_name(object->objectId);
3559 if (!nspname)
3560 {
3561 if (!missing_ok)
3562 elog(ERROR, "cache lookup failed for namespace %u",
3563 object->objectId);
3564 break;
3565 }
3566 appendStringInfo(&buffer, _("schema %s"), nspname);
3567 break;
3568 }
3569
3571 {
3574 char *nspname;
3575
3577 ObjectIdGetDatum(object->objectId));
3579 {
3580 if (!missing_ok)
3581 elog(ERROR, "could not find tuple for statistics object %u",
3582 object->objectId);
3583 break;
3584 }
3585
3587
3588 /* Qualify the name if not visible in search path */
3589 if (StatisticsObjIsVisible(object->objectId))
3590 nspname = NULL;
3591 else
3592 nspname = get_namespace_name(stxForm->stxnamespace);
3593
3594 appendStringInfo(&buffer, _("statistics object %s"),
3596 NameStr(stxForm->stxname)));
3597
3599 break;
3600 }
3601
3602 case TSParserRelationId:
3603 {
3604 HeapTuple tup;
3606 char *nspname;
3607
3609 ObjectIdGetDatum(object->objectId));
3610 if (!HeapTupleIsValid(tup))
3611 {
3612 if (!missing_ok)
3613 elog(ERROR, "cache lookup failed for text search parser %u",
3614 object->objectId);
3615 break;
3616 }
3618
3619 /* Qualify the name if not visible in search path */
3620 if (TSParserIsVisible(object->objectId))
3621 nspname = NULL;
3622 else
3623 nspname = get_namespace_name(prsForm->prsnamespace);
3624
3625 appendStringInfo(&buffer, _("text search parser %s"),
3627 NameStr(prsForm->prsname)));
3629 break;
3630 }
3631
3633 {
3634 HeapTuple tup;
3636 char *nspname;
3637
3639 ObjectIdGetDatum(object->objectId));
3640 if (!HeapTupleIsValid(tup))
3641 {
3642 if (!missing_ok)
3643 elog(ERROR, "cache lookup failed for text search dictionary %u",
3644 object->objectId);
3645 break;
3646 }
3647
3649
3650 /* Qualify the name if not visible in search path */
3651 if (TSDictionaryIsVisible(object->objectId))
3652 nspname = NULL;
3653 else
3654 nspname = get_namespace_name(dictForm->dictnamespace);
3655
3656 appendStringInfo(&buffer, _("text search dictionary %s"),
3658 NameStr(dictForm->dictname)));
3660 break;
3661 }
3662
3664 {
3665 HeapTuple tup;
3667 char *nspname;
3668
3670 ObjectIdGetDatum(object->objectId));
3671 if (!HeapTupleIsValid(tup))
3672 {
3673 if (!missing_ok)
3674 elog(ERROR, "cache lookup failed for text search template %u",
3675 object->objectId);
3676 break;
3677 }
3678
3680
3681 /* Qualify the name if not visible in search path */
3682 if (TSTemplateIsVisible(object->objectId))
3683 nspname = NULL;
3684 else
3685 nspname = get_namespace_name(tmplForm->tmplnamespace);
3686
3687 appendStringInfo(&buffer, _("text search template %s"),
3689 NameStr(tmplForm->tmplname)));
3691 break;
3692 }
3693
3694 case TSConfigRelationId:
3695 {
3696 HeapTuple tup;
3698 char *nspname;
3699
3701 ObjectIdGetDatum(object->objectId));
3702 if (!HeapTupleIsValid(tup))
3703 {
3704 if (!missing_ok)
3705 elog(ERROR, "cache lookup failed for text search configuration %u",
3706 object->objectId);
3707 break;
3708 }
3709
3711
3712 /* Qualify the name if not visible in search path */
3713 if (TSConfigIsVisible(object->objectId))
3714 nspname = NULL;
3715 else
3716 nspname = get_namespace_name(cfgForm->cfgnamespace);
3717
3718 appendStringInfo(&buffer, _("text search configuration %s"),
3720 NameStr(cfgForm->cfgname)));
3722 break;
3723 }
3724
3725 case AuthIdRelationId:
3726 {
3727 char *username = GetUserNameFromId(object->objectId,
3728 missing_ok);
3729
3730 if (username)
3731 appendStringInfo(&buffer, _("role %s"), username);
3732 break;
3733 }
3734
3735 case AuthMemRelationId:
3736 {
3738 ScanKeyData skey[1];
3740 HeapTuple tup;
3742
3744
3745 ScanKeyInit(&skey[0],
3748 ObjectIdGetDatum(object->objectId));
3749
3751 NULL, 1, skey);
3752
3754
3755 if (!HeapTupleIsValid(tup))
3756 {
3757 if (!missing_ok)
3758 elog(ERROR, "could not find tuple for role membership %u",
3759 object->objectId);
3760
3763 break;
3764 }
3765
3767
3768 appendStringInfo(&buffer, _("membership of role %s in role %s"),
3769 GetUserNameFromId(amForm->member, false),
3770 GetUserNameFromId(amForm->roleid, false));
3771
3774 break;
3775 }
3776
3777 case DatabaseRelationId:
3778 {
3779 char *datname;
3780
3782 if (!datname)
3783 {
3784 if (!missing_ok)
3785 elog(ERROR, "cache lookup failed for database %u",
3786 object->objectId);
3787 break;
3788 }
3789 appendStringInfo(&buffer, _("database %s"), datname);
3790 break;
3791 }
3792
3794 {
3795 char *tblspace;
3796
3798 if (!tblspace)
3799 {
3800 if (!missing_ok)
3801 elog(ERROR, "cache lookup failed for tablespace %u",
3802 object->objectId);
3803 break;
3804 }
3805 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
3806 break;
3807 }
3808
3810 {
3812
3814 missing_ok);
3815 if (fdw)
3816 appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
3817 break;
3818 }
3819
3821 {
3823
3824 srv = GetForeignServerExtended(object->objectId, missing_ok);
3825 if (srv)
3826 appendStringInfo(&buffer, _("server %s"), srv->servername);
3827 break;
3828 }
3829
3831 {
3832 HeapTuple tup;
3833 Oid useid;
3834 char *usename;
3837
3839 ObjectIdGetDatum(object->objectId));
3840 if (!HeapTupleIsValid(tup))
3841 {
3842 if (!missing_ok)
3843 elog(ERROR, "cache lookup failed for user mapping %u",
3844 object->objectId);
3845 break;
3846 }
3847
3849 useid = umform->umuser;
3850 srv = GetForeignServer(umform->umserver);
3851
3853
3854 if (OidIsValid(useid))
3856 else
3857 usename = "public";
3858
3859 appendStringInfo(&buffer, _("user mapping for %s on server %s"), usename,
3860 srv->servername);
3861 break;
3862 }
3863
3865 {
3867 ScanKeyData skey[1];
3869 HeapTuple tup;
3871 char *rolename;
3872 char *nspname;
3873
3875
3876 ScanKeyInit(&skey[0],
3879 ObjectIdGetDatum(object->objectId));
3880
3882 true, NULL, 1, skey);
3883
3885
3886 if (!HeapTupleIsValid(tup))
3887 {
3888 if (!missing_ok)
3889 elog(ERROR, "could not find tuple for default ACL %u",
3890 object->objectId);
3891
3894 break;
3895 }
3896
3898
3899 rolename = GetUserNameFromId(defacl->defaclrole, false);
3900
3901 if (OidIsValid(defacl->defaclnamespace))
3902 nspname = get_namespace_name(defacl->defaclnamespace);
3903 else
3904 nspname = NULL;
3905
3906 switch (defacl->defaclobjtype)
3907 {
3908 case DEFACLOBJ_RELATION:
3909 if (nspname)
3910 appendStringInfo(&buffer,
3911 _("default privileges on new relations belonging to role %s in schema %s"),
3912 rolename, nspname);
3913 else
3914 appendStringInfo(&buffer,
3915 _("default privileges on new relations belonging to role %s"),
3916 rolename);
3917 break;
3918 case DEFACLOBJ_SEQUENCE:
3919 if (nspname)
3920 appendStringInfo(&buffer,
3921 _("default privileges on new sequences belonging to role %s in schema %s"),
3922 rolename, nspname);
3923 else
3924 appendStringInfo(&buffer,
3925 _("default privileges on new sequences belonging to role %s"),
3926 rolename);
3927 break;
3928 case DEFACLOBJ_FUNCTION:
3929 if (nspname)
3930 appendStringInfo(&buffer,
3931 _("default privileges on new functions belonging to role %s in schema %s"),
3932 rolename, nspname);
3933 else
3934 appendStringInfo(&buffer,
3935 _("default privileges on new functions belonging to role %s"),
3936 rolename);
3937 break;
3938 case DEFACLOBJ_TYPE:
3939 if (nspname)
3940 appendStringInfo(&buffer,
3941 _("default privileges on new types belonging to role %s in schema %s"),
3942 rolename, nspname);
3943 else
3944 appendStringInfo(&buffer,
3945 _("default privileges on new types belonging to role %s"),
3946 rolename);
3947 break;
3949 Assert(!nspname);
3950 appendStringInfo(&buffer,
3951 _("default privileges on new schemas belonging to role %s"),
3952 rolename);
3953 break;
3955 Assert(!nspname);
3956 appendStringInfo(&buffer,
3957 _("default privileges on new large objects belonging to role %s"),
3958 rolename);
3959 break;
3960 default:
3961 /* shouldn't get here */
3962 if (nspname)
3963 appendStringInfo(&buffer,
3964 _("default privileges belonging to role %s in schema %s"),
3965 rolename, nspname);
3966 else
3967 appendStringInfo(&buffer,
3968 _("default privileges belonging to role %s"),
3969 rolename);
3970 break;
3971 }
3972
3975 break;
3976 }
3977
3979 {
3980 char *extname;
3981
3982 extname = get_extension_name(object->objectId);
3983 if (!extname)
3984 {
3985 if (!missing_ok)
3986 elog(ERROR, "cache lookup failed for extension %u",
3987 object->objectId);
3988 break;
3989 }
3990 appendStringInfo(&buffer, _("extension %s"), extname);
3991 break;
3992 }
3993
3995 {
3996 HeapTuple tup;
3997
3999 ObjectIdGetDatum(object->objectId));
4000 if (!HeapTupleIsValid(tup))
4001 {
4002 if (!missing_ok)
4003 elog(ERROR, "cache lookup failed for event trigger %u",
4004 object->objectId);
4005 break;
4006 }
4007 appendStringInfo(&buffer, _("event trigger %s"),
4010 break;
4011 }
4012
4014 {
4015 HeapTuple tup;
4017 char *parname;
4018
4020 ObjectIdGetDatum(object->objectId));
4021 if (!HeapTupleIsValid(tup))
4022 {
4023 if (!missing_ok)
4024 elog(ERROR, "cache lookup failed for parameter ACL %u",
4025 object->objectId);
4026 break;
4027 }
4031 appendStringInfo(&buffer, _("parameter %s"), parname);
4033 break;
4034 }
4035
4036 case PolicyRelationId:
4037 {
4039 ScanKeyData skey[1];
4041 HeapTuple tuple;
4043 StringInfoData rel;
4044
4046
4047 ScanKeyInit(&skey[0],
4050 ObjectIdGetDatum(object->objectId));
4051
4053 true, NULL, 1, skey);
4054
4055 tuple = systable_getnext(sscan);
4056
4057 if (!HeapTupleIsValid(tuple))
4058 {
4059 if (!missing_ok)
4060 elog(ERROR, "could not find tuple for policy %u",
4061 object->objectId);
4062
4065 break;
4066 }
4067
4069
4070 initStringInfo(&rel);
4071 getRelationDescription(&rel, form_policy->polrelid, false);
4072
4073 /* translator: second %s is, e.g., "table %s" */
4074 appendStringInfo(&buffer, _("policy %s on %s"),
4075 NameStr(form_policy->polname), rel.data);
4076 pfree(rel.data);
4079 break;
4080 }
4081
4083 {
4084 HeapTuple tup;
4086
4088 if (!HeapTupleIsValid(tup))
4089 {
4090 if (!missing_ok)
4091 elog(ERROR, "cache lookup failed for property graph element %u",
4092 object->objectId);
4093 break;
4094 }
4095
4097
4098 if (pgeform->pgekind == PGEKIND_VERTEX)
4099 /* translator: followed by, e.g., "property graph %s" */
4100 appendStringInfo(&buffer, _("vertex %s of "), NameStr(pgeform->pgealias));
4101 else if (pgeform->pgekind == PGEKIND_EDGE)
4102 /* translator: followed by, e.g., "property graph %s" */
4103 appendStringInfo(&buffer, _("edge %s of "), NameStr(pgeform->pgealias));
4104 else
4105 appendStringInfo(&buffer, "??? element %s of ", NameStr(pgeform->pgealias));
4106 getRelationDescription(&buffer, pgeform->pgepgid, false);
4107
4109 break;
4110 }
4111
4113 {
4114 Relation rel;
4115 HeapTuple tuple;
4118
4120 tuple = get_catalog_object_by_oid(rel,
4122 object->objectId);
4123 if (!HeapTupleIsValid(tuple))
4124 {
4125 if (!missing_ok)
4126 elog(ERROR, "could not find tuple for element label %u", object->objectId);
4127
4129 break;
4130 }
4131
4133
4134 appendStringInfo(&buffer, _("label %s of "), get_propgraph_label_name(pgelform->pgellabelid));
4137
4139 break;
4140 }
4141
4143 {
4144 HeapTuple tuple;
4146
4148 if (!HeapTupleIsValid(tuple))
4149 {
4150 if (!missing_ok)
4151 elog(ERROR, "could not find tuple for label %u", object->objectId);
4152 break;
4153 }
4154
4156
4157 /* translator: followed by, e.g., "property graph %s" */
4158 appendStringInfo(&buffer, _("label %s of "), NameStr(pglform->pgllabel));
4159 getRelationDescription(&buffer, pglform->pglpgid, false);
4160 ReleaseSysCache(tuple);
4161 break;
4162 }
4163
4165 {
4166 Relation rel;
4167 HeapTuple tuple;
4170
4172 tuple = get_catalog_object_by_oid(rel,
4174 object->objectId);
4175 if (!HeapTupleIsValid(tuple))
4176 {
4177 if (!missing_ok)
4178 elog(ERROR, "could not find tuple for label property %u", object->objectId);
4179
4181 break;
4182 }
4183
4185
4186 appendStringInfo(&buffer, _("property %s of "), get_propgraph_property_name(plpform->plppropid));
4189
4191 break;
4192 }
4193
4195 {
4196 HeapTuple tuple;
4198
4200 if (!HeapTupleIsValid(tuple))
4201 {
4202 if (!missing_ok)
4203 elog(ERROR, "could not find tuple for property %u", object->objectId);
4204 break;
4205 }
4206
4208
4209 /* translator: followed by, e.g., "property graph %s" */
4210 appendStringInfo(&buffer, _("property %s of "), NameStr(pgpform->pgpname));
4211 getRelationDescription(&buffer, pgpform->pgppgid, false);
4212 ReleaseSysCache(tuple);
4213 break;
4214 }
4215
4217 {
4218 char *pubname = get_publication_name(object->objectId,
4219 missing_ok);
4220
4221 if (pubname)
4222 appendStringInfo(&buffer, _("publication %s"), pubname);
4223 break;
4224 }
4225
4227 {
4228 char *pubname;
4229 char *nspname;
4230
4231 if (!getPublicationSchemaInfo(object, missing_ok,
4232 &pubname, &nspname))
4233 break;
4234
4235 appendStringInfo(&buffer, _("publication of schema %s in publication %s"),
4236 nspname, pubname);
4237 pfree(pubname);
4238 pfree(nspname);
4239 break;
4240 }
4241
4243 {
4244 HeapTuple tup;
4245 char *pubname;
4247 StringInfoData rel;
4248
4250 ObjectIdGetDatum(object->objectId));
4251 if (!HeapTupleIsValid(tup))
4252 {
4253 if (!missing_ok)
4254 elog(ERROR, "cache lookup failed for publication table %u",
4255 object->objectId);
4256 break;
4257 }
4258
4260 pubname = get_publication_name(prform->prpubid, false);
4261
4262 initStringInfo(&rel);
4263 getRelationDescription(&rel, prform->prrelid, false);
4264
4265 /* translator: first %s is, e.g., "table %s" */
4266 appendStringInfo(&buffer, _("publication of %s in publication %s"),
4267 rel.data, pubname);
4268 pfree(rel.data);
4270 break;
4271 }
4272
4274 {
4275 char *subname = get_subscription_name(object->objectId,
4276 missing_ok);
4277
4278 if (subname)
4279 appendStringInfo(&buffer, _("subscription %s"), subname);
4280 break;
4281 }
4282
4284 {
4287
4289 ObjectIdGetDatum(object->objectId));
4291 {
4292 if (!missing_ok)
4293 elog(ERROR, "could not find tuple for transform %u",
4294 object->objectId);
4295 break;
4296 }
4297
4299
4300 appendStringInfo(&buffer, _("transform for %s language %s"),
4301 format_type_be(trfForm->trftype),
4302 get_language_name(trfForm->trflang, false));
4303
4305 break;
4306 }
4307
4308 default:
4309 elog(ERROR, "unsupported object class: %u", object->classId);
4310 }
4311
4312 /* an empty buffer is equivalent to no object found */
4313 if (buffer.len == 0)
4314 return NULL;
4315
4316 return buffer.data;
4317}
4318
4319/*
4320 * getObjectDescriptionOids: as above, except the object is specified by Oids
4321 */
4322char *
4324{
4325 ObjectAddress address;
4326
4327 address.classId = classid;
4328 address.objectId = objid;
4329 address.objectSubId = 0;
4330
4331 return getObjectDescription(&address, false);
4332}
4333
4334/*
4335 * subroutine for getObjectDescription: describe a relation
4336 *
4337 * The result is appended to "buffer".
4338 */
4339static void
4340getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok)
4341{
4344 char *nspname;
4345 char *relname;
4346
4348 ObjectIdGetDatum(relid));
4350 {
4351 if (!missing_ok)
4352 elog(ERROR, "cache lookup failed for relation %u", relid);
4353 return;
4354 }
4356
4357 /* Qualify the name if not visible in search path */
4358 if (RelationIsVisible(relid))
4359 nspname = NULL;
4360 else
4361 nspname = get_namespace_name(relForm->relnamespace);
4362
4363 relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
4364
4365 switch (relForm->relkind)
4366 {
4367 case RELKIND_RELATION:
4369 appendStringInfo(buffer, _("table %s"),
4370 relname);
4371 break;
4372 case RELKIND_INDEX:
4374 appendStringInfo(buffer, _("index %s"),
4375 relname);
4376 break;
4377 case RELKIND_SEQUENCE:
4378 appendStringInfo(buffer, _("sequence %s"),
4379 relname);
4380 break;
4381 case RELKIND_TOASTVALUE:
4382 appendStringInfo(buffer, _("toast table %s"),
4383 relname);
4384 break;
4385 case RELKIND_VIEW:
4386 appendStringInfo(buffer, _("view %s"),
4387 relname);
4388 break;
4389 case RELKIND_MATVIEW:
4390 appendStringInfo(buffer, _("materialized view %s"),
4391 relname);
4392 break;
4394 appendStringInfo(buffer, _("composite type %s"),
4395 relname);
4396 break;
4398 appendStringInfo(buffer, _("foreign table %s"),
4399 relname);
4400 break;
4401 case RELKIND_PROPGRAPH:
4402 appendStringInfo(buffer, _("property graph %s"),
4403 relname);
4404 break;
4405 default:
4406 /* shouldn't get here */
4407 appendStringInfo(buffer, _("relation %s"),
4408 relname);
4409 break;
4410 }
4411
4413}
4414
4415/*
4416 * subroutine for getObjectDescription: describe an operator family
4417 */
4418static void
4420{
4425 char *nspname;
4426
4429 {
4430 if (!missing_ok)
4431 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
4432 return;
4433 }
4435
4437 if (!HeapTupleIsValid(amTup))
4438 elog(ERROR, "cache lookup failed for access method %u",
4439 opfForm->opfmethod);
4441
4442 /* Qualify the name if not visible in search path */
4444 nspname = NULL;
4445 else
4446 nspname = get_namespace_name(opfForm->opfnamespace);
4447
4448 appendStringInfo(buffer, _("operator family %s for access method %s"),
4450 NameStr(opfForm->opfname)),
4451 NameStr(amForm->amname));
4452
4455}
4456
4457/*
4458 * SQL-level callable version of getObjectDescription
4459 */
4460Datum
4462{
4463 Oid classid = PG_GETARG_OID(0);
4464 Oid objid = PG_GETARG_OID(1);
4465 int32 objsubid = PG_GETARG_INT32(2);
4466 char *description;
4467 ObjectAddress address;
4468
4469 /* for "pinned" items in pg_depend, return null */
4470 if (!OidIsValid(classid) && !OidIsValid(objid))
4472
4473 address.classId = classid;
4474 address.objectId = objid;
4475 address.objectSubId = objsubid;
4476
4477 description = getObjectDescription(&address, true);
4478
4479 if (description == NULL)
4481
4483}
4484
4485/*
4486 * SQL-level callable function to obtain object type + identity
4487 */
4488Datum
4490{
4491 Oid classid = PG_GETARG_OID(0);
4492 Oid objid = PG_GETARG_OID(1);
4493 int32 objsubid = PG_GETARG_INT32(2);
4495 const char *objname = NULL;
4496 char *objidentity;
4497 ObjectAddress address;
4498 Datum values[4];
4499 bool nulls[4];
4500 TupleDesc tupdesc;
4501 HeapTuple htup;
4502
4503 address.classId = classid;
4504 address.objectId = objid;
4505 address.objectSubId = objsubid;
4506
4507 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4508 elog(ERROR, "return type must be a row type");
4509
4510 if (is_objectclass_supported(address.classId))
4511 {
4514
4517 address.objectId);
4518 if (objtup != NULL)
4519 {
4520 bool isnull;
4523
4526 {
4528 RelationGetDescr(catalog), &isnull));
4529 if (isnull)
4530 elog(ERROR, "invalid null namespace in object %u/%u/%d",
4531 address.classId, address.objectId, address.objectSubId);
4532 }
4533
4534 /*
4535 * We only return the object name if it can be used (together with
4536 * the schema name, if any) as a unique identifier.
4537 */
4539 {
4542 {
4544
4546 RelationGetDescr(catalog), &isnull);
4547 if (isnull)
4548 elog(ERROR, "invalid null name in object %u/%u/%d",
4549 address.classId, address.objectId, address.objectSubId);
4551 }
4552 }
4553 }
4554
4556 }
4557
4558 /* object type, which can never be NULL */
4560 nulls[0] = false;
4561
4562 /*
4563 * Before doing anything, extract the object identity. If the identity
4564 * could not be found, set all the fields except the object type to NULL.
4565 */
4566 objidentity = getObjectIdentity(&address, true);
4567
4568 /* schema name */
4569 if (OidIsValid(schema_oid) && objidentity)
4570 {
4571 const char *schema = quote_identifier(get_namespace_name(schema_oid));
4572
4573 values[1] = CStringGetTextDatum(schema);
4574 nulls[1] = false;
4575 }
4576 else
4577 nulls[1] = true;
4578
4579 /* object name */
4580 if (objname && objidentity)
4581 {
4582 values[2] = CStringGetTextDatum(objname);
4583 nulls[2] = false;
4584 }
4585 else
4586 nulls[2] = true;
4587
4588 /* object identity */
4589 if (objidentity)
4590 {
4591 values[3] = CStringGetTextDatum(objidentity);
4592 nulls[3] = false;
4593 }
4594 else
4595 nulls[3] = true;
4596
4597 htup = heap_form_tuple(tupdesc, values, nulls);
4598
4600}
4601
4602/*
4603 * SQL-level callable function to obtain object type + identity
4604 */
4605Datum
4607{
4608 Oid classid = PG_GETARG_OID(0);
4609 Oid objid = PG_GETARG_OID(1);
4610 int32 objsubid = PG_GETARG_INT32(2);
4611 ObjectAddress address;
4612 char *identity;
4613 List *names;
4614 List *args;
4615 Datum values[3];
4616 bool nulls[3];
4617 TupleDesc tupdesc;
4618 HeapTuple htup;
4619
4620 address.classId = classid;
4621 address.objectId = objid;
4622 address.objectSubId = objsubid;
4623
4624 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4625 elog(ERROR, "return type must be a row type");
4626
4627 /* object type, which can never be NULL */
4629 nulls[0] = false;
4630
4631 /* object identity */
4632 identity = getObjectIdentityParts(&address, &names, &args, true);
4633 if (identity == NULL)
4634 {
4635 nulls[1] = true;
4636 nulls[2] = true;
4637 }
4638 else
4639 {
4640 pfree(identity);
4641
4642 /* object_names */
4643 if (names != NIL)
4645 else
4647 nulls[1] = false;
4648
4649 /* object_args */
4650 if (args)
4652 else
4654 nulls[2] = false;
4655 }
4656
4657 htup = heap_form_tuple(tupdesc, values, nulls);
4658
4660}
4661
4662/*
4663 * SQL-level callable function to obtain the ACL of a specified object, given
4664 * its catalog OID, object OID and sub-object ID.
4665 */
4666Datum
4668{
4669 Oid classId = PG_GETARG_OID(0);
4670 Oid objectId = PG_GETARG_OID(1);
4671 int32 objsubid = PG_GETARG_INT32(2);
4672 Oid catalogId;
4674 Datum datum;
4675 bool isnull;
4676 HeapTuple tup;
4677
4678 /* for "pinned" items in pg_depend, return null */
4679 if (!OidIsValid(classId) && !OidIsValid(objectId))
4681
4682 /* for large objects, the catalog to look at is pg_largeobject_metadata */
4683 catalogId = (classId == LargeObjectRelationId) ?
4685 Anum_acl = get_object_attnum_acl(catalogId);
4686
4687 /* return NULL if no ACL field for this catalog */
4690
4691 /*
4692 * If dealing with a relation's attribute (objsubid is set), the ACL is
4693 * retrieved from pg_attribute.
4694 */
4695 if (classId == RelationRelationId && objsubid != 0)
4696 {
4697 AttrNumber attnum = (AttrNumber) objsubid;
4698
4699 tup = SearchSysCacheCopyAttNum(objectId, attnum);
4700
4701 if (!HeapTupleIsValid(tup))
4703
4705 &isnull);
4706 }
4707 else
4708 {
4709 Relation rel;
4710
4711 rel = table_open(catalogId, AccessShareLock);
4712
4714 objectId);
4715 if (!HeapTupleIsValid(tup))
4716 {
4719 }
4720
4721 datum = heap_getattr(tup, Anum_acl, RelationGetDescr(rel), &isnull);
4723 }
4724
4725 if (isnull)
4727
4728 PG_RETURN_DATUM(datum);
4729}
4730
4731/*
4732 * Return a palloc'ed string that describes the type of object that the
4733 * passed address is for.
4734 *
4735 * Keep ObjectTypeMap in sync with this.
4736 */
4737char *
4738getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
4739{
4740 StringInfoData buffer;
4741
4742 initStringInfo(&buffer);
4743
4744 switch (object->classId)
4745 {
4746 case RelationRelationId:
4747 getRelationTypeDescription(&buffer, object->objectId,
4748 object->objectSubId,
4749 missing_ok);
4750 break;
4751
4753 getProcedureTypeDescription(&buffer, object->objectId,
4754 missing_ok);
4755 break;
4756
4757 case TypeRelationId:
4758 appendStringInfoString(&buffer, "type");
4759 break;
4760
4761 case CastRelationId:
4762 appendStringInfoString(&buffer, "cast");
4763 break;
4764
4766 appendStringInfoString(&buffer, "collation");
4767 break;
4768
4770 getConstraintTypeDescription(&buffer, object->objectId,
4771 missing_ok);
4772 break;
4773
4775 appendStringInfoString(&buffer, "conversion");
4776 break;
4777
4779 appendStringInfoString(&buffer, "default value");
4780 break;
4781
4782 case LanguageRelationId:
4783 appendStringInfoString(&buffer, "language");
4784 break;
4785
4787 appendStringInfoString(&buffer, "large object");
4788 break;
4789
4790 case OperatorRelationId:
4791 appendStringInfoString(&buffer, "operator");
4792 break;
4793
4795 appendStringInfoString(&buffer, "operator class");
4796 break;
4797
4799 appendStringInfoString(&buffer, "operator family");
4800 break;
4801
4803 appendStringInfoString(&buffer, "access method");
4804 break;
4805
4807 appendStringInfoString(&buffer, "operator of access method");
4808 break;
4809
4811 appendStringInfoString(&buffer, "function of access method");
4812 break;
4813
4814 case RewriteRelationId:
4815 appendStringInfoString(&buffer, "rule");
4816 break;
4817
4818 case TriggerRelationId:
4819 appendStringInfoString(&buffer, "trigger");
4820 break;
4821
4823 appendStringInfoString(&buffer, "schema");
4824 break;
4825
4827 appendStringInfoString(&buffer, "statistics object");
4828 break;
4829
4830 case TSParserRelationId:
4831 appendStringInfoString(&buffer, "text search parser");
4832 break;
4833
4835 appendStringInfoString(&buffer, "text search dictionary");
4836 break;
4837
4839 appendStringInfoString(&buffer, "text search template");
4840 break;
4841
4842 case TSConfigRelationId:
4843 appendStringInfoString(&buffer, "text search configuration");
4844 break;
4845
4846 case AuthIdRelationId:
4847 appendStringInfoString(&buffer, "role");
4848 break;
4849
4850 case AuthMemRelationId:
4851 appendStringInfoString(&buffer, "role membership");
4852 break;
4853
4854 case DatabaseRelationId:
4855 appendStringInfoString(&buffer, "database");
4856 break;
4857
4859 appendStringInfoString(&buffer, "tablespace");
4860 break;
4861
4863 appendStringInfoString(&buffer, "foreign-data wrapper");
4864 break;
4865
4867 appendStringInfoString(&buffer, "server");
4868 break;
4869
4871 appendStringInfoString(&buffer, "user mapping");
4872 break;
4873
4875 appendStringInfoString(&buffer, "default acl");
4876 break;
4877
4879 appendStringInfoString(&buffer, "extension");
4880 break;
4881
4883 appendStringInfoString(&buffer, "event trigger");
4884 break;
4885
4887 appendStringInfoString(&buffer, "parameter ACL");
4888 break;
4889
4890 case PolicyRelationId:
4891 appendStringInfoString(&buffer, "policy");
4892 break;
4893
4895 appendStringInfoString(&buffer, "property graph element");
4896 break;
4897
4899 appendStringInfoString(&buffer, "property graph label");
4900 break;
4901
4903 appendStringInfoString(&buffer, "property graph property");
4904 break;
4905
4907 appendStringInfoString(&buffer, "property graph element label");
4908 break;
4909
4911 appendStringInfoString(&buffer, "property graph label property");
4912 break;
4913
4915 appendStringInfoString(&buffer, "publication");
4916 break;
4917
4919 appendStringInfoString(&buffer, "publication namespace");
4920 break;
4921
4923 appendStringInfoString(&buffer, "publication relation");
4924 break;
4925
4927 appendStringInfoString(&buffer, "subscription");
4928 break;
4929
4931 appendStringInfoString(&buffer, "transform");
4932 break;
4933
4934 default:
4935 elog(ERROR, "unsupported object class: %u", object->classId);
4936 }
4937
4938 /* the result can never be empty */
4939 Assert(buffer.len > 0);
4940
4941 return buffer.data;
4942}
4943
4944/*
4945 * subroutine for getObjectTypeDescription: describe a relation type
4946 */
4947static void
4949 bool missing_ok)
4950{
4953
4955 ObjectIdGetDatum(relid));
4957 {
4958 if (!missing_ok)
4959 elog(ERROR, "cache lookup failed for relation %u", relid);
4960
4961 /* fallback to "relation" for an undefined object */
4962 appendStringInfoString(buffer, "relation");
4963 return;
4964 }
4966
4967 switch (relForm->relkind)
4968 {
4969 case RELKIND_RELATION:
4971 appendStringInfoString(buffer, "table");
4972 break;
4973 case RELKIND_INDEX:
4975 appendStringInfoString(buffer, "index");
4976 break;
4977 case RELKIND_SEQUENCE:
4978 appendStringInfoString(buffer, "sequence");
4979 break;
4980 case RELKIND_TOASTVALUE:
4981 appendStringInfoString(buffer, "toast table");
4982 break;
4983 case RELKIND_VIEW:
4984 appendStringInfoString(buffer, "view");
4985 break;
4986 case RELKIND_MATVIEW:
4987 appendStringInfoString(buffer, "materialized view");
4988 break;
4990 appendStringInfoString(buffer, "composite type");
4991 break;
4993 appendStringInfoString(buffer, "foreign table");
4994 break;
4995 case RELKIND_PROPGRAPH:
4996 appendStringInfoString(buffer, "property graph");
4997 break;
4998 default:
4999 /* shouldn't get here */
5000 appendStringInfoString(buffer, "relation");
5001 break;
5002 }
5003
5004 if (objectSubId != 0)
5005 appendStringInfoString(buffer, " column");
5006
5008}
5009
5010/*
5011 * subroutine for getObjectTypeDescription: describe a constraint type
5012 */
5013static void
5015{
5019
5022 constroid);
5024 {
5025 if (!missing_ok)
5026 elog(ERROR, "cache lookup failed for constraint %u", constroid);
5027
5029
5030 /* fallback to "constraint" for an undefined object */
5031 appendStringInfoString(buffer, "constraint");
5032 return;
5033 }
5034
5036
5037 if (OidIsValid(constrForm->conrelid))
5038 appendStringInfoString(buffer, "table constraint");
5039 else if (OidIsValid(constrForm->contypid))
5040 appendStringInfoString(buffer, "domain constraint");
5041 else
5042 elog(ERROR, "invalid constraint %u", constrForm->oid);
5043
5045}
5046
5047/*
5048 * subroutine for getObjectTypeDescription: describe a procedure type
5049 */
5050static void
5052 bool missing_ok)
5053{
5056
5058 ObjectIdGetDatum(procid));
5060 {
5061 if (!missing_ok)
5062 elog(ERROR, "cache lookup failed for procedure %u", procid);
5063
5064 /* fallback to "procedure" for an undefined object */
5065 appendStringInfoString(buffer, "routine");
5066 return;
5067 }
5069
5070 if (procForm->prokind == PROKIND_AGGREGATE)
5071 appendStringInfoString(buffer, "aggregate");
5072 else if (procForm->prokind == PROKIND_PROCEDURE)
5073 appendStringInfoString(buffer, "procedure");
5074 else /* function or window function */
5075 appendStringInfoString(buffer, "function");
5076
5078}
5079
5080/*
5081 * Obtain a given object's identity, as a palloc'ed string.
5082 *
5083 * This is for machine consumption, so it's not translated. All elements are
5084 * schema-qualified when appropriate. Returns NULL if the object could not
5085 * be found.
5086 */
5087char *
5088getObjectIdentity(const ObjectAddress *object, bool missing_ok)
5089{
5090 return getObjectIdentityParts(object, NULL, NULL, missing_ok);
5091}
5092
5093/*
5094 * As above, but more detailed.
5095 *
5096 * There are two sets of return values: the identity itself as a palloc'd
5097 * string is returned. objname and objargs, if not NULL, are output parameters
5098 * that receive lists of C-strings that are useful to give back to
5099 * get_object_address() to reconstruct the ObjectAddress. Returns NULL if
5100 * the object could not be found.
5101 */
5102char *
5104 List **objname, List **objargs,
5105 bool missing_ok)
5106{
5107 StringInfoData buffer;
5108
5109 initStringInfo(&buffer);
5110
5111 /*
5112 * Make sure that both objname and objargs were passed, or none was; and
5113 * initialize them to empty lists. For objname this is useless because it
5114 * will be initialized in all cases inside the switch; but we do it anyway
5115 * so that we can test below that no branch leaves it unset.
5116 */
5117 Assert((objname != NULL) == (objargs != NULL));
5118 if (objname)
5119 {
5120 *objname = NIL;
5121 *objargs = NIL;
5122 }
5123
5124 switch (object->classId)
5125 {
5126 case RelationRelationId:
5127 {
5128 char *attr = NULL;
5129
5130 /*
5131 * Check for the attribute first, so as if it is missing we
5132 * can skip the entire relation description.
5133 */
5134 if (object->objectSubId != 0)
5135 {
5136 attr = get_attname(object->objectId,
5137 object->objectSubId,
5138 missing_ok);
5139
5140 if (missing_ok && attr == NULL)
5141 break;
5142 }
5143
5144 getRelationIdentity(&buffer, object->objectId, objname,
5145 missing_ok);
5146 if (objname && *objname == NIL)
5147 break;
5148
5149 if (attr)
5150 {
5151 appendStringInfo(&buffer, ".%s",
5152 quote_identifier(attr));
5153 if (objname)
5154 *objname = lappend(*objname, attr);
5155 }
5156 }
5157 break;
5158
5160 {
5163 flags);
5164
5165 if (proname == NULL)
5166 break;
5167
5169 if (objname)
5170 format_procedure_parts(object->objectId, objname, objargs,
5171 missing_ok);
5172 break;
5173 }
5174
5175 case TypeRelationId:
5176 {
5178 char *typeout;
5179
5180 typeout = format_type_extended(object->objectId, -1, flags);
5181
5182 if (typeout == NULL)
5183 break;
5184
5186 if (objname)
5187 *objname = list_make1(typeout);
5188 }
5189 break;
5190
5191 case CastRelationId:
5192 {
5194 HeapTuple tup;
5196
5198
5200 object->objectId);
5201
5202 if (!HeapTupleIsValid(tup))
5203 {
5204 if (!missing_ok)
5205 elog(ERROR, "could not find tuple for cast %u",
5206 object->objectId);
5207
5209 break;
5210 }
5211
5213
5214 appendStringInfo(&buffer, "(%s AS %s)",
5216 format_type_be_qualified(castForm->casttarget));
5217
5218 if (objname)
5219 {
5220 *objname = list_make1(format_type_be_qualified(castForm->castsource));
5221 *objargs = list_make1(format_type_be_qualified(castForm->casttarget));
5222 }
5223
5225 break;
5226 }
5227
5229 {
5231 Form_pg_collation coll;
5232 char *schema;
5233
5235 ObjectIdGetDatum(object->objectId));
5237 {
5238 if (!missing_ok)
5239 elog(ERROR, "cache lookup failed for collation %u",
5240 object->objectId);
5241 break;
5242 }
5244 schema = get_namespace_name_or_temp(coll->collnamespace);
5245 appendStringInfoString(&buffer,
5247 NameStr(coll->collname)));
5248 if (objname)
5249 *objname = list_make2(schema,
5250 pstrdup(NameStr(coll->collname)));
5252 break;
5253 }
5254
5256 {
5259
5261 ObjectIdGetDatum(object->objectId));
5263 {
5264 if (!missing_ok)
5265 elog(ERROR, "cache lookup failed for constraint %u",
5266 object->objectId);
5267 break;
5268 }
5270
5271 if (OidIsValid(con->conrelid))
5272 {
5273 appendStringInfo(&buffer, "%s on ",
5274 quote_identifier(NameStr(con->conname)));
5275 getRelationIdentity(&buffer, con->conrelid, objname,
5276 false);
5277 if (objname)
5278 *objname = lappend(*objname, pstrdup(NameStr(con->conname)));
5279 }
5280 else
5281 {
5282 ObjectAddress domain;
5283
5284 Assert(OidIsValid(con->contypid));
5285 domain.classId = TypeRelationId;
5286 domain.objectId = con->contypid;
5287 domain.objectSubId = 0;
5288
5289 appendStringInfo(&buffer, "%s on %s",
5290 quote_identifier(NameStr(con->conname)),
5291 getObjectIdentityParts(&domain, objname,
5292 objargs, false));
5293
5294 if (objname)
5295 *objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
5296 }
5297
5299 break;
5300 }
5301
5303 {
5306 char *schema;
5307
5309 ObjectIdGetDatum(object->objectId));
5311 {
5312 if (!missing_ok)
5313 elog(ERROR, "cache lookup failed for conversion %u",
5314 object->objectId);
5315 break;
5316 }
5318 schema = get_namespace_name_or_temp(conForm->connamespace);
5319 appendStringInfoString(&buffer,
5321 NameStr(conForm->conname)));
5322 if (objname)
5323 *objname = list_make2(schema,
5324 pstrdup(NameStr(conForm->conname)));
5326 break;
5327 }
5328
5330 {
5332
5334
5335 if (!OidIsValid(colobject.objectId))
5336 {
5337 if (!missing_ok)
5338 elog(ERROR, "could not find tuple for attrdef %u",
5339 object->objectId);
5340 break;
5341 }
5342
5343 appendStringInfo(&buffer, "for %s",
5345 objname, objargs,
5346 false));
5347 break;
5348 }
5349
5350 case LanguageRelationId:
5351 {
5354
5356 ObjectIdGetDatum(object->objectId));
5358 {
5359 if (!missing_ok)
5360 elog(ERROR, "cache lookup failed for language %u",
5361 object->objectId);
5362 break;
5363 }
5365 appendStringInfoString(&buffer,
5366 quote_identifier(NameStr(langForm->lanname)));
5367 if (objname)
5368 *objname = list_make1(pstrdup(NameStr(langForm->lanname)));
5370 break;
5371 }
5372
5374 if (!LargeObjectExists(object->objectId))
5375 break;
5376 appendStringInfo(&buffer, "%u",
5377 object->objectId);
5378 if (objname)
5379 *objname = list_make1(psprintf("%u", object->objectId));
5380 break;
5381
5382 case OperatorRelationId:
5383 {
5385 char *oprname = format_operator_extended(object->objectId,
5386 flags);
5387
5388 if (oprname == NULL)
5389 break;
5390
5391 appendStringInfoString(&buffer, oprname);
5392 if (objname)
5393 format_operator_parts(object->objectId, objname, objargs, missing_ok);
5394 break;
5395 }
5396
5398 {
5403 char *schema;
5404
5406 ObjectIdGetDatum(object->objectId));
5408 {
5409 if (!missing_ok)
5410 elog(ERROR, "cache lookup failed for opclass %u",
5411 object->objectId);
5412 break;
5413 }
5415 schema = get_namespace_name_or_temp(opcForm->opcnamespace);
5416
5418 ObjectIdGetDatum(opcForm->opcmethod));
5419 if (!HeapTupleIsValid(amTup))
5420 elog(ERROR, "cache lookup failed for access method %u",
5421 opcForm->opcmethod);
5423
5424 appendStringInfo(&buffer, "%s USING %s",
5426 NameStr(opcForm->opcname)),
5427 quote_identifier(NameStr(amForm->amname)));
5428 if (objname)
5429 *objname = list_make3(pstrdup(NameStr(amForm->amname)),
5430 schema,
5431 pstrdup(NameStr(opcForm->opcname)));
5432
5435 break;
5436 }
5437
5439 getOpFamilyIdentity(&buffer, object->objectId, objname,
5440 missing_ok);
5441 break;
5442
5444 {
5445 char *amname;
5446
5447 amname = get_am_name(object->objectId);
5448 if (!amname)
5449 {
5450 if (!missing_ok)
5451 elog(ERROR, "cache lookup failed for access method %u",
5452 object->objectId);
5453 break;
5454 }
5455 appendStringInfoString(&buffer, quote_identifier(amname));
5456 if (objname)
5457 *objname = list_make1(amname);
5458 }
5459 break;
5460
5462 {
5464 HeapTuple tup;
5465 ScanKeyData skey[1];
5468 StringInfoData opfam;
5469 char *ltype;
5470 char *rtype;
5471
5474
5475 ScanKeyInit(&skey[0],
5478 ObjectIdGetDatum(object->objectId));
5479
5481 NULL, 1, skey);
5482
5484
5485 if (!HeapTupleIsValid(tup))
5486 {
5487 if (!missing_ok)
5488 elog(ERROR, "could not find tuple for amop entry %u",
5489 object->objectId);
5490
5493 break;
5494 }
5495
5497
5498 initStringInfo(&opfam);
5499 getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname,
5500 false);
5501
5502 ltype = format_type_be_qualified(amopForm->amoplefttype);
5503 rtype = format_type_be_qualified(amopForm->amoprighttype);
5504
5505 if (objname)
5506 {
5507 *objname = lappend(*objname,
5508 psprintf("%d", amopForm->amopstrategy));
5509 *objargs = list_make2(ltype, rtype);
5510 }
5511
5512 appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
5513 amopForm->amopstrategy,
5514 ltype, rtype, opfam.data);
5515
5516 pfree(opfam.data);
5517
5520 break;
5521 }
5522
5524 {
5526 ScanKeyData skey[1];
5528 HeapTuple tup;
5530 StringInfoData opfam;
5531 char *ltype;
5532 char *rtype;
5533
5536
5537 ScanKeyInit(&skey[0],
5540 ObjectIdGetDatum(object->objectId));
5541
5543 NULL, 1, skey);
5544
5546
5547 if (!HeapTupleIsValid(tup))
5548 {
5549 if (!missing_ok)
5550 elog(ERROR, "could not find tuple for amproc entry %u",
5551 object->objectId);
5552
5555 break;
5556 }
5557
5559
5560 initStringInfo(&opfam);
5561 getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname,
5562 false);
5563
5564 ltype = format_type_be_qualified(amprocForm->amproclefttype);
5565 rtype = format_type_be_qualified(amprocForm->amprocrighttype);
5566
5567 if (objname)
5568 {
5569 *objname = lappend(*objname,
5570 psprintf("%d", amprocForm->amprocnum));
5571 *objargs = list_make2(ltype, rtype);
5572 }
5573
5574 appendStringInfo(&buffer, "function %d (%s, %s) of %s",
5575 amprocForm->amprocnum,
5576 ltype, rtype, opfam.data);
5577
5578 pfree(opfam.data);
5579
5582 break;
5583 }
5584
5585 case RewriteRelationId:
5586 {
5588 HeapTuple tup;
5590
5592
5594 object->objectId);
5595
5596 if (!HeapTupleIsValid(tup))
5597 {
5598 if (!missing_ok)
5599 elog(ERROR, "could not find tuple for rule %u",
5600 object->objectId);
5601
5603 break;
5604 }
5605
5607
5608 appendStringInfo(&buffer, "%s on ",
5609 quote_identifier(NameStr(rule->rulename)));
5610 getRelationIdentity(&buffer, rule->ev_class, objname, false);
5611 if (objname)
5612 *objname = lappend(*objname, pstrdup(NameStr(rule->rulename)));
5613
5615 break;
5616 }
5617
5618 case TriggerRelationId:
5619 {
5621 HeapTuple tup;
5623
5625
5627 object->objectId);
5628
5629 if (!HeapTupleIsValid(tup))
5630 {
5631 if (!missing_ok)
5632 elog(ERROR, "could not find tuple for trigger %u",
5633 object->objectId);
5634
5636 break;
5637 }
5638
5640
5641 appendStringInfo(&buffer, "%s on ",
5642 quote_identifier(NameStr(trig->tgname)));
5643 getRelationIdentity(&buffer, trig->tgrelid, objname, false);
5644 if (objname)
5645 *objname = lappend(*objname, pstrdup(NameStr(trig->tgname)));
5646
5648 break;
5649 }
5650
5652 {
5653 char *nspname;
5654
5655 nspname = get_namespace_name_or_temp(object->objectId);
5656 if (!nspname)
5657 {
5658 if (!missing_ok)
5659 elog(ERROR, "cache lookup failed for namespace %u",
5660 object->objectId);
5661 break;
5662 }
5663 appendStringInfoString(&buffer,
5664 quote_identifier(nspname));
5665 if (objname)
5666 *objname = list_make1(nspname);
5667 break;
5668 }
5669
5671 {
5672 HeapTuple tup;
5674 char *schema;
5675
5677 ObjectIdGetDatum(object->objectId));
5678 if (!HeapTupleIsValid(tup))
5679 {
5680 if (!missing_ok)
5681 elog(ERROR, "cache lookup failed for statistics object %u",
5682 object->objectId);
5683 break;
5684 }
5686 schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
5687 appendStringInfoString(&buffer,
5689 NameStr(formStatistic->stxname)));
5690 if (objname)
5691 *objname = list_make2(schema,
5692 pstrdup(NameStr(formStatistic->stxname)));
5694 }
5695 break;
5696
5697 case TSParserRelationId:
5698 {
5699 HeapTuple tup;
5701 char *schema;
5702
5704 ObjectIdGetDatum(object->objectId));
5705 if (!HeapTupleIsValid(tup))
5706 {
5707 if (!missing_ok)
5708 elog(ERROR, "cache lookup failed for text search parser %u",
5709 object->objectId);
5710 break;
5711 }
5713 schema = get_namespace_name_or_temp(formParser->prsnamespace);
5714 appendStringInfoString(&buffer,
5716 NameStr(formParser->prsname)));
5717 if (objname)
5718 *objname = list_make2(schema,
5719 pstrdup(NameStr(formParser->prsname)));
5721 break;
5722 }
5723
5725 {
5726 HeapTuple tup;
5728 char *schema;
5729
5731 ObjectIdGetDatum(object->objectId));
5732 if (!HeapTupleIsValid(tup))
5733 {
5734 if (!missing_ok)
5735 elog(ERROR, "cache lookup failed for text search dictionary %u",
5736 object->objectId);
5737 break;
5738 }
5740 schema = get_namespace_name_or_temp(formDict->dictnamespace);
5741 appendStringInfoString(&buffer,
5743 NameStr(formDict->dictname)));
5744 if (objname)
5745 *objname = list_make2(schema,
5746 pstrdup(NameStr(formDict->dictname)));
5748 break;
5749 }
5750
5752 {
5753 HeapTuple tup;
5755 char *schema;
5756
5758 ObjectIdGetDatum(object->objectId));
5759 if (!HeapTupleIsValid(tup))
5760 {
5761 if (!missing_ok)
5762 elog(ERROR, "cache lookup failed for text search template %u",
5763 object->objectId);
5764 break;
5765 }
5767 schema = get_namespace_name_or_temp(formTmpl->tmplnamespace);
5768 appendStringInfoString(&buffer,
5770 NameStr(formTmpl->tmplname)));
5771 if (objname)
5772 *objname = list_make2(schema,
5773 pstrdup(NameStr(formTmpl->tmplname)));
5775 break;
5776 }
5777
5778 case TSConfigRelationId:
5779 {
5780 HeapTuple tup;
5782 char *schema;
5783
5785 ObjectIdGetDatum(object->objectId));
5786 if (!HeapTupleIsValid(tup))
5787 {
5788 if (!missing_ok)
5789 elog(ERROR, "cache lookup failed for text search configuration %u",
5790 object->objectId);
5791 break;
5792 }
5794 schema = get_namespace_name_or_temp(formCfg->cfgnamespace);
5795 appendStringInfoString(&buffer,
5797 NameStr(formCfg->cfgname)));
5798 if (objname)
5799 *objname = list_make2(schema,
5800 pstrdup(NameStr(formCfg->cfgname)));
5802 break;
5803 }
5804
5805 case AuthIdRelationId:
5806 {
5807 char *username;
5808
5809 username = GetUserNameFromId(object->objectId, missing_ok);
5810 if (!username)
5811 break;
5812 if (objname)
5813 *objname = list_make1(username);
5814 appendStringInfoString(&buffer,
5816 break;
5817 }
5818
5819 case AuthMemRelationId:
5820 {
5822 ScanKeyData skey[1];
5824 HeapTuple tup;
5826
5829
5830 ScanKeyInit(&skey[0],
5833 ObjectIdGetDatum(object->objectId));
5834
5836 NULL, 1, skey);
5837
5839
5840 if (!HeapTupleIsValid(tup))
5841 {
5842 if (!missing_ok)
5843 elog(ERROR, "could not find tuple for pg_auth_members entry %u",
5844 object->objectId);
5845
5848 break;
5849 }
5850
5852
5853 appendStringInfo(&buffer, "membership of role %s in role %s",
5854 GetUserNameFromId(amForm->member, false),
5855 GetUserNameFromId(amForm->roleid, false));
5856
5859 break;
5860 }
5861
5862 case DatabaseRelationId:
5863 {
5864 char *datname;
5865
5867 if (!datname)
5868 {
5869 if (!missing_ok)
5870 elog(ERROR, "cache lookup failed for database %u",
5871 object->objectId);
5872 break;
5873 }
5874 if (objname)
5875 *objname = list_make1(datname);
5876 appendStringInfoString(&buffer,
5878 break;
5879 }
5880
5882 {
5883 char *tblspace;
5884
5886 if (!tblspace)
5887 {
5888 if (!missing_ok)
5889 elog(ERROR, "cache lookup failed for tablespace %u",
5890 object->objectId);
5891 break;
5892 }
5893 if (objname)
5894 *objname = list_make1(tblspace);
5895 appendStringInfoString(&buffer,
5897 break;
5898 }
5899
5901 {
5903
5905 missing_ok);
5906 if (fdw)
5907 {
5908 appendStringInfoString(&buffer, quote_identifier(fdw->fdwname));
5909 if (objname)
5910 *objname = list_make1(pstrdup(fdw->fdwname));
5911 }
5912 break;
5913 }
5914
5916 {
5918
5920 missing_ok);
5921 if (srv)
5922 {
5923 appendStringInfoString(&buffer,
5924 quote_identifier(srv->servername));
5925 if (objname)
5926 *objname = list_make1(pstrdup(srv->servername));
5927 }
5928 break;
5929 }
5930
5932 {
5933 HeapTuple tup;
5934 Oid useid;
5937 const char *usename;
5938
5940 ObjectIdGetDatum(object->objectId));
5941 if (!HeapTupleIsValid(tup))
5942 {
5943 if (!missing_ok)
5944 elog(ERROR, "cache lookup failed for user mapping %u",
5945 object->objectId);
5946 break;
5947 }
5949 useid = umform->umuser;
5950 srv = GetForeignServer(umform->umserver);
5951
5953
5954 if (OidIsValid(useid))
5956 else
5957 usename = "public";
5958
5959 if (objname)
5960 {
5961 *objname = list_make1(pstrdup(usename));
5962 *objargs = list_make1(pstrdup(srv->servername));
5963 }
5964
5965 appendStringInfo(&buffer, "%s on server %s",
5967 srv->servername);
5968 break;
5969 }
5970
5972 {
5974 ScanKeyData skey[1];
5976 HeapTuple tup;
5978 char *schema;
5979 char *username;
5980
5982
5983 ScanKeyInit(&skey[0],
5986 ObjectIdGetDatum(object->objectId));
5987
5989 true, NULL, 1, skey);
5990
5992
5993 if (!HeapTupleIsValid(tup))
5994 {
5995 if (!missing_ok)
5996 elog(ERROR, "could not find tuple for default ACL %u",
5997 object->objectId);
5998
6001 break;
6002 }
6003
6005
6006 username = GetUserNameFromId(defacl->defaclrole, false);
6007 appendStringInfo(&buffer,
6008 "for role %s",
6010
6011 if (OidIsValid(defacl->defaclnamespace))
6012 {
6013 schema = get_namespace_name_or_temp(defacl->defaclnamespace);
6014 appendStringInfo(&buffer,
6015 " in schema %s",
6016 quote_identifier(schema));
6017 }
6018 else
6019 schema = NULL;
6020
6021 switch (defacl->defaclobjtype)
6022 {
6023 case DEFACLOBJ_RELATION:
6024 appendStringInfoString(&buffer,
6025 " on tables");
6026 break;
6027 case DEFACLOBJ_SEQUENCE:
6028 appendStringInfoString(&buffer,
6029 " on sequences");
6030 break;
6031 case DEFACLOBJ_FUNCTION:
6032 appendStringInfoString(&buffer,
6033 " on functions");
6034 break;
6035 case DEFACLOBJ_TYPE:
6036 appendStringInfoString(&buffer,
6037 " on types");
6038 break;
6040 appendStringInfoString(&buffer,
6041 " on schemas");
6042 break;
6044 appendStringInfoString(&buffer,
6045 " on large objects");
6046 break;
6047 }
6048
6049 if (objname)
6050 {
6051 *objname = list_make1(username);
6052 if (schema)
6053 *objname = lappend(*objname, schema);
6054 *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
6055 }
6056
6059 break;
6060 }
6061
6063 {
6064 char *extname;
6065
6066 extname = get_extension_name(object->objectId);
6067 if (!extname)
6068 {
6069 if (!missing_ok)
6070 elog(ERROR, "cache lookup failed for extension %u",
6071 object->objectId);
6072 break;
6073 }
6074 appendStringInfoString(&buffer, quote_identifier(extname));
6075 if (objname)
6076 *objname = list_make1(extname);
6077 break;
6078 }
6079
6081 {
6082 HeapTuple tup;
6084 char *evtname;
6085
6087 ObjectIdGetDatum(object->objectId));
6088 if (!HeapTupleIsValid(tup))
6089 {
6090 if (!missing_ok)
6091 elog(ERROR, "cache lookup failed for event trigger %u",
6092 object->objectId);
6093 break;
6094 }
6096 evtname = pstrdup(NameStr(trigForm->evtname));
6097 appendStringInfoString(&buffer, quote_identifier(evtname));
6098 if (objname)
6099 *objname = list_make1(evtname);
6101 break;
6102 }
6103
6105 {
6106 HeapTuple tup;
6108 char *parname;
6109
6111 ObjectIdGetDatum(object->objectId));
6112 if (!HeapTupleIsValid(tup))
6113 {
6114 if (!missing_ok)
6115 elog(ERROR, "cache lookup failed for parameter ACL %u",
6116 object->objectId);
6117 break;
6118 }
6123 if (objname)
6124 *objname = list_make1(parname);
6126 break;
6127 }
6128
6129 case PolicyRelationId:
6130 {
6132 HeapTuple tup;
6134
6136
6138 object->objectId);
6139
6140 if (!HeapTupleIsValid(tup))
6141 {
6142 if (!missing_ok)
6143 elog(ERROR, "could not find tuple for policy %u",
6144 object->objectId);
6145
6147 break;
6148 }
6149
6151
6152 appendStringInfo(&buffer, "%s on ",
6153 quote_identifier(NameStr(policy->polname)));
6154 getRelationIdentity(&buffer, policy->polrelid, objname, false);
6155 if (objname)
6156 *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
6157
6159 break;
6160 }
6161
6163 {
6164 HeapTuple tup;
6166
6168 if (!HeapTupleIsValid(tup))
6169 {
6170 if (!missing_ok)
6171 elog(ERROR, "cache lookup failed for property graph element %u", object->objectId);
6172 break;
6173 }
6175 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pge->pgealias)));
6176
6177 getRelationIdentity(&buffer, pge->pgepgid, objname, false);
6178 if (objname)
6179 *objname = lappend(*objname, pstrdup(NameStr(pge->pgealias)));
6180
6182 break;
6183 }
6184
6186 {
6187 HeapTuple tup;
6189
6191 if (!HeapTupleIsValid(tup))
6192 {
6193 if (!missing_ok)
6194 elog(ERROR, "cache lookup failed for property graph label %u", object->objectId);
6195 break;
6196 }
6197
6199 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pgl->pgllabel)));
6200 getRelationIdentity(&buffer, pgl->pglpgid, objname, false);
6201 if (objname)
6202 *objname = lappend(*objname, pstrdup(NameStr(pgl->pgllabel)));
6204 break;
6205 }
6206
6208 {
6209 HeapTuple tup;
6211
6213 if (!HeapTupleIsValid(tup))
6214 {
6215 if (!missing_ok)
6216 elog(ERROR, "cache lookup failed for property graph property %u", object->objectId);
6217 break;
6218 }
6219
6221 appendStringInfo(&buffer, "%s of ", quote_identifier(NameStr(pgp->pgpname)));
6222 getRelationIdentity(&buffer, pgp->pgppgid, objname, false);
6223 if (objname)
6224 *objname = lappend(*objname, pstrdup(NameStr(pgp->pgpname)));
6226 break;
6227 }
6228
6230 {
6232 HeapTuple tup;
6235 char *labelname;
6236
6240 object->objectId);
6241 if (!HeapTupleIsValid(tup))
6242 {
6243 if (!missing_ok)
6244 elog(ERROR, "could not find tuple for element label %u",
6245 object->objectId);
6246
6248 break;
6249 }
6250
6252
6254 appendStringInfo(&buffer, "%s of ", quote_identifier(labelname));
6257 objargs, false));
6258 /* labelname is already pstrdup'ed. */
6259 if (objname)
6260 *objname = lappend(*objname, labelname);
6261
6263 break;
6264 }
6265
6267 {
6269 HeapTuple tup;
6272 char *propname;
6273
6278 object->objectId);
6279 if (!HeapTupleIsValid(tup))
6280 {
6281 if (!missing_ok)
6282 elog(ERROR, "could not find tuple for label property %u",
6283 object->objectId);
6284
6286 break;
6287 }
6288
6290
6292 appendStringInfo(&buffer, "%s of ", quote_identifier(propname));
6295 objargs, false));
6296 /* propname is already pstrdup'ed. */
6297 if (objname)
6298 *objname = lappend(*objname, propname);
6299
6301 break;
6302 }
6303
6305 {
6306 char *pubname;
6307
6308 pubname = get_publication_name(object->objectId, missing_ok);
6309 if (pubname)
6310 {
6311 appendStringInfoString(&buffer,
6312 quote_identifier(pubname));
6313 if (objname)
6314 *objname = list_make1(pubname);
6315 }
6316 break;
6317 }
6318
6320 {
6321 char *pubname;
6322 char *nspname;
6323
6324 if (!getPublicationSchemaInfo(object, missing_ok, &pubname,
6325 &nspname))
6326 break;
6327 appendStringInfo(&buffer, "%s in publication %s",
6328 nspname, pubname);
6329
6330 if (objargs)
6331 *objargs = list_make1(pubname);
6332 else
6333 pfree(pubname);
6334
6335 if (objname)
6336 *objname = list_make1(nspname);
6337 else
6338 pfree(nspname);
6339
6340 break;
6341 }
6342
6344 {
6345 HeapTuple tup;
6346 char *pubname;
6348
6350 ObjectIdGetDatum(object->objectId));
6351 if (!HeapTupleIsValid(tup))
6352 {
6353 if (!missing_ok)
6354 elog(ERROR, "cache lookup failed for publication table %u",
6355 object->objectId);
6356 break;
6357 }
6358
6360 pubname = get_publication_name(prform->prpubid, false);
6361
6362 getRelationIdentity(&buffer, prform->prrelid, objname, false);
6363 appendStringInfo(&buffer, " in publication %s", pubname);
6364
6365 if (objargs)
6366 *objargs = list_make1(pubname);
6367
6369 break;
6370 }
6371
6373 {
6374 char *subname;
6375
6376 subname = get_subscription_name(object->objectId, missing_ok);
6377 if (subname)
6378 {
6379 appendStringInfoString(&buffer,
6381 if (objname)
6382 *objname = list_make1(subname);
6383 }
6384 break;
6385 }
6386
6388 {
6390 HeapTuple tup;
6391 Form_pg_transform transform;
6392 char *transformLang;
6393 char *transformType;
6394
6396
6399 object->objectId);
6400
6401 if (!HeapTupleIsValid(tup))
6402 {
6403 if (!missing_ok)
6404 elog(ERROR, "could not find tuple for transform %u",
6405 object->objectId);
6406
6408 break;
6409 }
6410
6411 transform = (Form_pg_transform) GETSTRUCT(tup);
6412
6413 transformType = format_type_be_qualified(transform->trftype);
6414 transformLang = get_language_name(transform->trflang, false);
6415
6416 appendStringInfo(&buffer, "for %s language %s",
6419 if (objname)
6420 {
6421 *objname = list_make1(transformType);
6422 *objargs = list_make1(pstrdup(transformLang));
6423 }
6424
6426 }
6427 break;
6428
6429 default:
6430 elog(ERROR, "unsupported object class: %u", object->classId);
6431 }
6432
6433 if (!missing_ok)
6434 {
6435 /*
6436 * If a get_object_address() representation was requested, make sure
6437 * we are providing one. We don't check objargs, because many of the
6438 * cases above leave it as NIL.
6439 */
6440 if (objname && *objname == NIL)
6441 elog(ERROR, "requested object address for unsupported object class %u: text result \"%s\"",
6442 object->classId, buffer.data);
6443 }
6444 else
6445 {
6446 /* an empty buffer is equivalent to no object found */
6447 if (buffer.len == 0)
6448 {
6449 Assert((objname == NULL || *objname == NIL) &&
6450 (objargs == NULL || *objargs == NIL));
6451 return NULL;
6452 }
6453 }
6454
6455 return buffer.data;
6456}
6457
6458static void
6460 bool missing_ok)
6461{
6466 char *schema;
6467
6470 {
6471 if (!missing_ok)
6472 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
6473 return;
6474 }
6476
6478 if (!HeapTupleIsValid(amTup))
6479 elog(ERROR, "cache lookup failed for access method %u",
6480 opfForm->opfmethod);
6482
6483 schema = get_namespace_name_or_temp(opfForm->opfnamespace);
6484 appendStringInfo(buffer, "%s USING %s",
6486 NameStr(opfForm->opfname)),
6487 NameStr(amForm->amname));
6488
6489 if (object)
6490 *object = list_make3(pstrdup(NameStr(amForm->amname)),
6491 pstrdup(schema),
6492 pstrdup(NameStr(opfForm->opfname)));
6493
6496}
6497
6498/*
6499 * Append the relation identity (quoted qualified name) to the given
6500 * StringInfo.
6501 */
6502static void
6503getRelationIdentity(StringInfo buffer, Oid relid, List **object,
6504 bool missing_ok)
6505{
6508 char *schema;
6509
6511 ObjectIdGetDatum(relid));
6513 {
6514 if (!missing_ok)
6515 elog(ERROR, "cache lookup failed for relation %u", relid);
6516
6517 if (object)
6518 *object = NIL;
6519 return;
6520 }
6522
6523 schema = get_namespace_name_or_temp(relForm->relnamespace);
6526 NameStr(relForm->relname)));
6527 if (object)
6528 *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
6529
6531}
6532
6533/*
6534 * Auxiliary function to build a TEXT array out of a list of C-strings.
6535 */
6536ArrayType *
6538{
6539 ArrayType *arr;
6540 Datum *datums;
6541 bool *nulls;
6542 int j = 0;
6543 ListCell *cell;
6544 MemoryContext memcxt;
6546 int lb[1];
6547
6548 /* Work in a temp context; easier than individually pfree'ing the Datums */
6550 "strlist to array",
6552 oldcxt = MemoryContextSwitchTo(memcxt);
6553
6554 datums = palloc_array(Datum, list_length(list));
6555 nulls = palloc_array(bool, list_length(list));
6556
6557 foreach(cell, list)
6558 {
6559 char *name = lfirst(cell);
6560
6561 if (name)
6562 {
6563 nulls[j] = false;
6564 datums[j++] = CStringGetTextDatum(name);
6565 }
6566 else
6567 nulls[j] = true;
6568 }
6569
6571
6572 lb[0] = 1;
6573 arr = construct_md_array(datums, nulls, 1, &j,
6574 lb, TEXTOID, -1, false, TYPALIGN_INT);
6575
6576 MemoryContextDelete(memcxt);
6577
6578 return arr;
6579}
6580
6581/*
6582 * get_relkind_objtype
6583 *
6584 * Return the object type for the relkind given by the caller.
6585 *
6586 * If an unexpected relkind is passed, we say OBJECT_TABLE rather than
6587 * failing. That's because this is mostly used for generating error messages
6588 * for failed ACL checks on relations, and we'd rather produce a generic
6589 * message saying "table" than fail entirely.
6590 */
6593{
6594 switch (relkind)
6595 {
6596 case RELKIND_RELATION:
6598 return OBJECT_TABLE;
6599 case RELKIND_INDEX:
6601 return OBJECT_INDEX;
6602 case RELKIND_SEQUENCE:
6603 return OBJECT_SEQUENCE;
6604 case RELKIND_VIEW:
6605 return OBJECT_VIEW;
6606 case RELKIND_MATVIEW:
6607 return OBJECT_MATVIEW;
6609 return OBJECT_FOREIGN_TABLE;
6610 case RELKIND_PROPGRAPH:
6611 return OBJECT_PROPGRAPH;
6612 case RELKIND_TOASTVALUE:
6613 return OBJECT_TABLE;
6614 default:
6615 /* Per above, don't raise an error */
6616 return OBJECT_TABLE;
6617 }
6618}
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:4134
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition aclchk.c:2997
bool has_createrole_privilege(Oid roleid)
Definition aclchk.c:4213
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:190
#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:835
#define Assert(condition)
Definition c.h:943
int32_t int32
Definition c.h:620
uint64_t uint64
Definition c.h:625
uint16_t uint16
Definition c.h:623
#define lengthof(array)
Definition c.h:873
#define pg_fallthrough
Definition c.h:161
#define OidIsValid(objectId)
Definition c.h:858
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:875
#define _(x)
Definition elog.c:96
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:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
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:91
#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:185
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, uint16 flags)
Definition foreign.c:51
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition foreign.c:736
ForeignServer * GetForeignServer(Oid serverid)
Definition foreign.c:114
ForeignServer * GetForeignServerExtended(Oid serverid, uint16 flags)
Definition foreign.c:126
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition foreign.c:713
char * format_type_be_qualified(Oid type_oid)
char * format_type_be(Oid type_oid)
char * format_type_extended(Oid type_oid, int32 typemod, uint16 flags)
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:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
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:686
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
#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:4090
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1225
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:1076
char * get_database_name(Oid dbid)
Definition lsyscache.c:1384
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2309
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3978
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1405
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3698
char * get_propgraph_label_name(Oid labeloid)
Definition lsyscache.c:4072
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:4028
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:4048
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:3998
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3674
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:475
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:990
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:138
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition parse_oper.c:136
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:244
#define linitial(l)
Definition pg_list.h:178
#define list_make3(x1, x2, x3)
Definition pg_list.h:248
#define lsecond(l)
Definition pg_list.h:183
#define list_make2(x1, x2)
Definition pg_list.h:246
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 Name DatumGetName(Datum X)
Definition postgres.h:393
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:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define PointerGetDatum(X)
Definition postgres.h:354
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(Oid procedure_oid)
Definition regproc.c:305
char * format_procedure_extended(Oid procedure_oid, uint16 flags)
Definition regproc.c:332
void format_operator_parts(Oid operator_oid, List **objnames, List **objargs, bool missing_ok)
Definition regproc.c:814
char * format_operator_extended(Oid operator_oid, uint16 flags)
Definition regproc.c:730
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:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
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:173
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:138
#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:97
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:562
HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:400
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
HeapTuple SearchSysCache3(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3)
Definition syscache.c:241
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache4(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition syscache.c:251
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
#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