PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2025, 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"
53#include "catalog/pg_rewrite.h"
58#include "catalog/pg_trigger.h"
60#include "catalog/pg_ts_dict.h"
63#include "catalog/pg_type.h"
65#include "commands/dbcommands.h"
66#include "commands/defrem.h"
68#include "commands/extension.h"
69#include "commands/policy.h"
70#include "commands/proclang.h"
71#include "commands/tablespace.h"
72#include "commands/trigger.h"
73#include "foreign/foreign.h"
74#include "funcapi.h"
75#include "miscadmin.h"
76#include "parser/parse_func.h"
77#include "parser/parse_oper.h"
78#include "parser/parse_type.h"
81#include "storage/lmgr.h"
82#include "storage/sinval.h"
83#include "utils/acl.h"
84#include "utils/builtins.h"
85#include "utils/fmgroids.h"
86#include "utils/lsyscache.h"
87#include "utils/memutils.h"
88#include "utils/regproc.h"
89#include "utils/syscache.h"
90
91/*
92 * ObjectProperty
93 *
94 * This array provides a common part of system object structure; to help
95 * consolidate routines to handle various kind of object classes.
96 */
97typedef struct
98{
99 const char *class_descr; /* string describing the catalog, for internal
100 * error messages */
101 Oid class_oid; /* oid of catalog */
102 Oid oid_index_oid; /* oid of index on system oid column */
103 int oid_catcache_id; /* id of catcache on system oid column */
104 int name_catcache_id; /* id of catcache on (name,namespace), or
105 * (name) if the object does not live in a
106 * namespace */
107 AttrNumber attnum_oid; /* attribute number of oid column */
108 AttrNumber attnum_name; /* attnum of name field */
109 AttrNumber attnum_namespace; /* attnum of namespace field */
110 AttrNumber attnum_owner; /* attnum of owner field */
111 AttrNumber attnum_acl; /* attnum of acl field */
112 ObjectType objtype; /* OBJECT_* of this object type */
113 bool is_nsp_name_unique; /* can the nsp/name combination (or name
114 * alone, if there's no namespace) be
115 * considered a unique identifier for an
116 * object of this class? */
118
120{
121 {
122 "access method",
123 AccessMethodRelationId,
124 AmOidIndexId,
125 AMOID,
126 AMNAME,
127 Anum_pg_am_oid,
128 Anum_pg_am_amname,
133 true
134 },
135 {
136 "access method operator",
137 AccessMethodOperatorRelationId,
138 AccessMethodOperatorOidIndexId,
139 -1,
140 -1,
141 Anum_pg_amop_oid,
147 false
148 },
149 {
150 "access method procedure",
151 AccessMethodProcedureRelationId,
152 AccessMethodProcedureOidIndexId,
153 -1,
154 -1,
155 Anum_pg_amproc_oid,
161 false
162 },
163 {
164 "cast",
165 CastRelationId,
166 CastOidIndexId,
167 -1,
168 -1,
169 Anum_pg_cast_oid,
175 false
176 },
177 {
178 "collation",
179 CollationRelationId,
180 CollationOidIndexId,
181 COLLOID,
182 -1, /* COLLNAMEENCNSP also takes encoding */
183 Anum_pg_collation_oid,
184 Anum_pg_collation_collname,
185 Anum_pg_collation_collnamespace,
186 Anum_pg_collation_collowner,
189 true
190 },
191 {
192 "constraint",
193 ConstraintRelationId,
194 ConstraintOidIndexId,
195 CONSTROID,
196 -1,
197 Anum_pg_constraint_oid,
198 Anum_pg_constraint_conname,
199 Anum_pg_constraint_connamespace,
202 -1,
203 false
204 },
205 {
206 "conversion",
207 ConversionRelationId,
208 ConversionOidIndexId,
209 CONVOID,
210 CONNAMENSP,
211 Anum_pg_conversion_oid,
212 Anum_pg_conversion_conname,
213 Anum_pg_conversion_connamespace,
214 Anum_pg_conversion_conowner,
217 true
218 },
219 {
220 "database",
221 DatabaseRelationId,
222 DatabaseOidIndexId,
223 DATABASEOID,
224 -1,
225 Anum_pg_database_oid,
226 Anum_pg_database_datname,
228 Anum_pg_database_datdba,
229 Anum_pg_database_datacl,
231 true
232 },
233 {
234 "default ACL",
235 DefaultAclRelationId,
236 DefaultAclOidIndexId,
237 -1,
238 -1,
239 Anum_pg_default_acl_oid,
245 false
246 },
247 {
248 "extension",
249 ExtensionRelationId,
250 ExtensionOidIndexId,
251 -1,
252 -1,
253 Anum_pg_extension_oid,
254 Anum_pg_extension_extname,
255 InvalidAttrNumber, /* extension doesn't belong to extnamespace */
256 Anum_pg_extension_extowner,
259 true
260 },
261 {
262 "foreign-data wrapper",
263 ForeignDataWrapperRelationId,
264 ForeignDataWrapperOidIndexId,
265 FOREIGNDATAWRAPPEROID,
266 FOREIGNDATAWRAPPERNAME,
267 Anum_pg_foreign_data_wrapper_oid,
268 Anum_pg_foreign_data_wrapper_fdwname,
270 Anum_pg_foreign_data_wrapper_fdwowner,
271 Anum_pg_foreign_data_wrapper_fdwacl,
273 true
274 },
275 {
276 "foreign server",
277 ForeignServerRelationId,
278 ForeignServerOidIndexId,
279 FOREIGNSERVEROID,
280 FOREIGNSERVERNAME,
281 Anum_pg_foreign_server_oid,
282 Anum_pg_foreign_server_srvname,
284 Anum_pg_foreign_server_srvowner,
285 Anum_pg_foreign_server_srvacl,
287 true
288 },
289 {
290 "function",
291 ProcedureRelationId,
292 ProcedureOidIndexId,
293 PROCOID,
294 -1, /* PROCNAMEARGSNSP also takes argument types */
295 Anum_pg_proc_oid,
296 Anum_pg_proc_proname,
297 Anum_pg_proc_pronamespace,
298 Anum_pg_proc_proowner,
299 Anum_pg_proc_proacl,
301 false
302 },
303 {
304 "language",
305 LanguageRelationId,
306 LanguageOidIndexId,
307 LANGOID,
308 LANGNAME,
309 Anum_pg_language_oid,
310 Anum_pg_language_lanname,
312 Anum_pg_language_lanowner,
313 Anum_pg_language_lanacl,
315 true
316 },
317 {
318 "large object metadata",
319 LargeObjectMetadataRelationId,
320 LargeObjectMetadataOidIndexId,
321 -1,
322 -1,
323 Anum_pg_largeobject_metadata_oid,
326 Anum_pg_largeobject_metadata_lomowner,
327 Anum_pg_largeobject_metadata_lomacl,
329 false
330 },
331 {
332 "operator class",
333 OperatorClassRelationId,
334 OpclassOidIndexId,
335 CLAOID,
336 -1, /* CLAAMNAMENSP also takes opcmethod */
337 Anum_pg_opclass_oid,
338 Anum_pg_opclass_opcname,
339 Anum_pg_opclass_opcnamespace,
340 Anum_pg_opclass_opcowner,
343 true
344 },
345 {
346 "operator",
347 OperatorRelationId,
348 OperatorOidIndexId,
349 OPEROID,
350 -1, /* OPERNAMENSP also takes left and right type */
351 Anum_pg_operator_oid,
352 Anum_pg_operator_oprname,
353 Anum_pg_operator_oprnamespace,
354 Anum_pg_operator_oprowner,
357 false
358 },
359 {
360 "operator family",
361 OperatorFamilyRelationId,
362 OpfamilyOidIndexId,
363 OPFAMILYOID,
364 -1, /* OPFAMILYAMNAMENSP also takes opfmethod */
365 Anum_pg_opfamily_oid,
366 Anum_pg_opfamily_opfname,
367 Anum_pg_opfamily_opfnamespace,
368 Anum_pg_opfamily_opfowner,
371 true
372 },
373 {
374 "role",
375 AuthIdRelationId,
376 AuthIdOidIndexId,
377 AUTHOID,
378 AUTHNAME,
379 Anum_pg_authid_oid,
380 Anum_pg_authid_rolname,
385 true
386 },
387 {
388 "role membership",
389 AuthMemRelationId,
390 AuthMemOidIndexId,
391 -1,
392 -1,
393 Anum_pg_auth_members_oid,
396 Anum_pg_auth_members_grantor,
398 -1,
399 true
400 },
401 {
402 "rule",
403 RewriteRelationId,
404 RewriteOidIndexId,
405 -1,
406 -1,
407 Anum_pg_rewrite_oid,
408 Anum_pg_rewrite_rulename,
413 false
414 },
415 {
416 "schema",
417 NamespaceRelationId,
418 NamespaceOidIndexId,
419 NAMESPACEOID,
420 NAMESPACENAME,
421 Anum_pg_namespace_oid,
422 Anum_pg_namespace_nspname,
424 Anum_pg_namespace_nspowner,
425 Anum_pg_namespace_nspacl,
427 true
428 },
429 {
430 "relation",
431 RelationRelationId,
432 ClassOidIndexId,
433 RELOID,
434 RELNAMENSP,
435 Anum_pg_class_oid,
436 Anum_pg_class_relname,
437 Anum_pg_class_relnamespace,
438 Anum_pg_class_relowner,
439 Anum_pg_class_relacl,
441 true
442 },
443 {
444 "tablespace",
445 TableSpaceRelationId,
446 TablespaceOidIndexId,
447 TABLESPACEOID,
448 -1,
449 Anum_pg_tablespace_oid,
450 Anum_pg_tablespace_spcname,
452 Anum_pg_tablespace_spcowner,
453 Anum_pg_tablespace_spcacl,
455 true
456 },
457 {
458 "transform",
459 TransformRelationId,
460 TransformOidIndexId,
461 TRFOID,
462 -1,
463 Anum_pg_transform_oid,
469 false
470 },
471 {
472 "trigger",
473 TriggerRelationId,
474 TriggerOidIndexId,
475 -1,
476 -1,
477 Anum_pg_trigger_oid,
478 Anum_pg_trigger_tgname,
483 false
484 },
485 {
486 "policy",
487 PolicyRelationId,
488 PolicyOidIndexId,
489 -1,
490 -1,
491 Anum_pg_policy_oid,
492 Anum_pg_policy_polname,
497 false
498 },
499 {
500 "event trigger",
501 EventTriggerRelationId,
502 EventTriggerOidIndexId,
503 EVENTTRIGGEROID,
504 EVENTTRIGGERNAME,
505 Anum_pg_event_trigger_oid,
506 Anum_pg_event_trigger_evtname,
508 Anum_pg_event_trigger_evtowner,
511 true
512 },
513 {
514 "text search configuration",
515 TSConfigRelationId,
516 TSConfigOidIndexId,
517 TSCONFIGOID,
518 TSCONFIGNAMENSP,
519 Anum_pg_ts_config_oid,
520 Anum_pg_ts_config_cfgname,
521 Anum_pg_ts_config_cfgnamespace,
522 Anum_pg_ts_config_cfgowner,
525 true
526 },
527 {
528 "text search dictionary",
529 TSDictionaryRelationId,
530 TSDictionaryOidIndexId,
531 TSDICTOID,
532 TSDICTNAMENSP,
533 Anum_pg_ts_dict_oid,
534 Anum_pg_ts_dict_dictname,
535 Anum_pg_ts_dict_dictnamespace,
536 Anum_pg_ts_dict_dictowner,
539 true
540 },
541 {
542 "text search parser",
543 TSParserRelationId,
544 TSParserOidIndexId,
545 TSPARSEROID,
546 TSPARSERNAMENSP,
547 Anum_pg_ts_parser_oid,
548 Anum_pg_ts_parser_prsname,
549 Anum_pg_ts_parser_prsnamespace,
553 true
554 },
555 {
556 "text search template",
557 TSTemplateRelationId,
558 TSTemplateOidIndexId,
559 TSTEMPLATEOID,
560 TSTEMPLATENAMENSP,
561 Anum_pg_ts_template_oid,
562 Anum_pg_ts_template_tmplname,
563 Anum_pg_ts_template_tmplnamespace,
567 true,
568 },
569 {
570 "type",
571 TypeRelationId,
572 TypeOidIndexId,
573 TYPEOID,
574 TYPENAMENSP,
575 Anum_pg_type_oid,
576 Anum_pg_type_typname,
577 Anum_pg_type_typnamespace,
578 Anum_pg_type_typowner,
579 Anum_pg_type_typacl,
581 true
582 },
583 {
584 "publication",
585 PublicationRelationId,
586 PublicationObjectIndexId,
587 PUBLICATIONOID,
588 PUBLICATIONNAME,
589 Anum_pg_publication_oid,
590 Anum_pg_publication_pubname,
592 Anum_pg_publication_pubowner,
595 true
596 },
597 {
598 "subscription",
599 SubscriptionRelationId,
600 SubscriptionObjectIndexId,
601 SUBSCRIPTIONOID,
602 SUBSCRIPTIONNAME,
603 Anum_pg_subscription_oid,
604 Anum_pg_subscription_subname,
606 Anum_pg_subscription_subowner,
609 true
610 },
611 {
612 "extended statistics",
613 StatisticExtRelationId,
614 StatisticExtOidIndexId,
615 STATEXTOID,
616 STATEXTNAMENSP,
617 Anum_pg_statistic_ext_oid,
618 Anum_pg_statistic_ext_stxname,
619 Anum_pg_statistic_ext_stxnamespace,
620 Anum_pg_statistic_ext_stxowner,
621 InvalidAttrNumber, /* no ACL (same as relation) */
623 true
624 },
625 {
626 "user mapping",
627 UserMappingRelationId,
628 UserMappingOidIndexId,
629 USERMAPPINGOID,
630 -1,
631 Anum_pg_user_mapping_oid,
637 false
638 },
639};
640
641/*
642 * This struct maps the string object types as returned by
643 * getObjectTypeDescription into ObjectType enum values. Note that some enum
644 * values can be obtained by different names, and that some string object types
645 * do not have corresponding values in the output enum. The user of this map
646 * must be careful to test for invalid values being returned.
647 *
648 * To ease maintenance, this follows the order of getObjectTypeDescription.
649 */
650static const struct object_type_map
651{
652 const char *tm_name;
654}
655
656 ObjectTypeMap[] =
657{
658 {
659 "table", OBJECT_TABLE
660 },
661 {
662 "index", OBJECT_INDEX
663 },
664 {
665 "sequence", OBJECT_SEQUENCE
666 },
667 {
668 "toast table", -1
669 }, /* unmapped */
670 {
671 "view", OBJECT_VIEW
672 },
673 {
674 "materialized view", OBJECT_MATVIEW
675 },
676 {
677 "composite type", -1
678 }, /* unmapped */
679 {
680 "foreign table", OBJECT_FOREIGN_TABLE
681 },
682 {
683 "table column", OBJECT_COLUMN
684 },
685 {
686 "index column", -1
687 }, /* unmapped */
688 {
689 "sequence column", -1
690 }, /* unmapped */
691 {
692 "toast table column", -1
693 }, /* unmapped */
694 {
695 "view column", -1
696 }, /* unmapped */
697 {
698 "materialized view column", -1
699 }, /* unmapped */
700 {
701 "composite type column", -1
702 }, /* unmapped */
703 {
704 "foreign table column", OBJECT_COLUMN
705 },
706 {
707 "aggregate", OBJECT_AGGREGATE
708 },
709 {
710 "function", OBJECT_FUNCTION
711 },
712 {
713 "procedure", OBJECT_PROCEDURE
714 },
715 {
716 "type", OBJECT_TYPE
717 },
718 {
719 "cast", OBJECT_CAST
720 },
721 {
722 "collation", OBJECT_COLLATION
723 },
724 {
725 "table constraint", OBJECT_TABCONSTRAINT
726 },
727 {
728 "domain constraint", OBJECT_DOMCONSTRAINT
729 },
730 {
731 "conversion", OBJECT_CONVERSION
732 },
733 {
734 "default value", OBJECT_DEFAULT
735 },
736 {
737 "language", OBJECT_LANGUAGE
738 },
739 {
740 "large object", OBJECT_LARGEOBJECT
741 },
742 {
743 "operator", OBJECT_OPERATOR
744 },
745 {
746 "operator class", OBJECT_OPCLASS
747 },
748 {
749 "operator family", OBJECT_OPFAMILY
750 },
751 {
752 "access method", OBJECT_ACCESS_METHOD
753 },
754 {
755 "operator of access method", OBJECT_AMOP
756 },
757 {
758 "function of access method", OBJECT_AMPROC
759 },
760 {
761 "rule", OBJECT_RULE
762 },
763 {
764 "trigger", OBJECT_TRIGGER
765 },
766 {
767 "schema", OBJECT_SCHEMA
768 },
769 {
770 "text search parser", OBJECT_TSPARSER
771 },
772 {
773 "text search dictionary", OBJECT_TSDICTIONARY
774 },
775 {
776 "text search template", OBJECT_TSTEMPLATE
777 },
778 {
779 "text search configuration", OBJECT_TSCONFIGURATION
780 },
781 {
782 "role", OBJECT_ROLE
783 },
784 {
785 "role membership", -1 /* unmapped */
786 },
787 {
788 "database", OBJECT_DATABASE
789 },
790 {
791 "tablespace", OBJECT_TABLESPACE
792 },
793 {
794 "foreign-data wrapper", OBJECT_FDW
795 },
796 {
797 "server", OBJECT_FOREIGN_SERVER
798 },
799 {
800 "user mapping", OBJECT_USER_MAPPING
801 },
802 {
803 "default acl", OBJECT_DEFACL
804 },
805 {
806 "extension", OBJECT_EXTENSION
807 },
808 {
809 "event trigger", OBJECT_EVENT_TRIGGER
810 },
811 {
812 "parameter ACL", OBJECT_PARAMETER_ACL
813 },
814 {
815 "policy", OBJECT_POLICY
816 },
817 {
818 "publication", OBJECT_PUBLICATION
819 },
820 {
821 "publication namespace", OBJECT_PUBLICATION_NAMESPACE
822 },
823 {
824 "publication relation", OBJECT_PUBLICATION_REL
825 },
826 {
827 "subscription", OBJECT_SUBSCRIPTION
828 },
829 {
830 "transform", OBJECT_TRANSFORM
831 },
832 {
833 "statistics object", OBJECT_STATISTIC_EXT
834 }
836
838{
841 0
842};
843
845 String *strval, bool missing_ok);
847 List *object, Relation *relp,
848 LOCKMODE lockmode, bool missing_ok);
850 List *object, Relation *relp, bool missing_ok);
852 List *object, Relation *relp,
853 LOCKMODE lockmode, bool missing_ok);
855 List *object, Relation *relp, LOCKMODE lockmode,
856 bool missing_ok);
858 TypeName *typename, bool missing_ok);
860 bool missing_ok);
862 List *object, bool missing_ok);
863
865 bool missing_ok);
867 Relation *relp,
868 bool missing_ok);
870 bool missing_ok);
872 bool missing_ok);
873static const ObjectPropertyType *get_object_property_data(Oid class_id);
874
875static void getRelationDescription(StringInfo buffer, Oid relid,
876 bool missing_ok);
877static void getOpFamilyDescription(StringInfo buffer, Oid opfid,
878 bool missing_ok);
879static void getRelationTypeDescription(StringInfo buffer, Oid relid,
880 int32 objectSubId, bool missing_ok);
881static void getProcedureTypeDescription(StringInfo buffer, Oid procid,
882 bool missing_ok);
883static void getConstraintTypeDescription(StringInfo buffer, Oid constroid,
884 bool missing_ok);
885static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object,
886 bool missing_ok);
887static void getRelationIdentity(StringInfo buffer, Oid relid, List **object,
888 bool missing_ok);
889
890/*
891 * Translate an object name and arguments (as passed by the parser) to an
892 * ObjectAddress.
893 *
894 * The returned object will be locked using the specified lockmode. If a
895 * sub-object is looked up, the parent object will be locked instead.
896 *
897 * If the object is a relation or a child object of a relation (e.g. an
898 * attribute or constraint), the relation is also opened and *relp receives
899 * the open relcache entry pointer; otherwise, *relp is set to NULL.
900 * (relp can be NULL if the caller never passes a relation-related object.) This
901 * is a bit grotty but it makes life simpler, since the caller will
902 * typically need the relcache entry too. Caller must close the relcache
903 * entry when done with it. The relation is locked with the specified lockmode
904 * if the target object is the relation itself or an attribute, but for other
905 * child objects, only AccessShareLock is acquired on the relation.
906 *
907 * If the object is not found, an error is thrown, unless missing_ok is
908 * true. In this case, no lock is acquired, relp is set to NULL, and the
909 * returned address has objectId set to InvalidOid.
910 *
911 * We don't currently provide a function to release the locks acquired here;
912 * typically, the lock must be held until commit to guard against a concurrent
913 * drop operation.
914 *
915 * Note: If the object is not found, we don't give any indication of the
916 * reason. (It might have been a missing schema if the name was qualified, or
917 * a nonexistent type name in case of a cast, function or operator; etc).
918 * Currently there is only one caller that might be interested in such info, so
919 * we don't spend much effort here. If more callers start to care, it might be
920 * better to add some support for that in this function.
921 */
924 Relation *relp, LOCKMODE lockmode, bool missing_ok)
925{
926 ObjectAddress address = {InvalidOid, InvalidOid, 0};
927 ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
928 Relation relation = NULL;
929 uint64 inval_count;
930
931 /* Some kind of lock must be taken. */
932 Assert(lockmode != NoLock);
933
934 for (;;)
935 {
936 /*
937 * Remember this value, so that, after looking up the object name and
938 * locking it, we can check whether any invalidation messages have
939 * been processed that might require a do-over.
940 */
941 inval_count = SharedInvalidMessageCounter;
942
943 /* Look up object address. */
944 switch (objtype)
945 {
946 case OBJECT_INDEX:
947 case OBJECT_SEQUENCE:
948 case OBJECT_TABLE:
949 case OBJECT_VIEW:
950 case OBJECT_MATVIEW:
952 address =
954 &relation, lockmode,
955 missing_ok);
956 break;
957 case OBJECT_ATTRIBUTE:
958 case OBJECT_COLUMN:
959 address =
961 &relation, lockmode,
962 missing_ok);
963 break;
964 case OBJECT_DEFAULT:
965 address =
966 get_object_address_attrdef(objtype, castNode(List, object),
967 &relation, lockmode,
968 missing_ok);
969 break;
970 case OBJECT_RULE:
971 case OBJECT_TRIGGER:
973 case OBJECT_POLICY:
974 address = get_object_address_relobject(objtype, castNode(List, object),
975 &relation, missing_ok);
976 break;
978 {
979 List *objlist;
980 ObjectAddress domaddr;
981 char *constrname;
982
983 objlist = castNode(List, object);
985 linitial_node(TypeName, objlist),
986 missing_ok);
987 constrname = strVal(lsecond(objlist));
988
989 address.classId = ConstraintRelationId;
991 constrname, missing_ok);
992 address.objectSubId = 0;
993 }
994 break;
995 case OBJECT_DATABASE:
996 case OBJECT_EXTENSION:
998 case OBJECT_ROLE:
999 case OBJECT_SCHEMA:
1000 case OBJECT_LANGUAGE:
1001 case OBJECT_FDW:
1006 case OBJECT_PUBLICATION:
1008 address = get_object_address_unqualified(objtype,
1009 castNode(String, object), missing_ok);
1010 break;
1011 case OBJECT_TYPE:
1012 case OBJECT_DOMAIN:
1013 address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
1014 break;
1015 case OBJECT_AGGREGATE:
1016 case OBJECT_FUNCTION:
1017 case OBJECT_PROCEDURE:
1018 case OBJECT_ROUTINE:
1019 address.classId = ProcedureRelationId;
1020 address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
1021 address.objectSubId = 0;
1022 break;
1023 case OBJECT_OPERATOR:
1024 address.classId = OperatorRelationId;
1025 address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
1026 address.objectSubId = 0;
1027 break;
1028 case OBJECT_COLLATION:
1029 address.classId = CollationRelationId;
1030 address.objectId = get_collation_oid(castNode(List, object), missing_ok);
1031 address.objectSubId = 0;
1032 break;
1033 case OBJECT_CONVERSION:
1034 address.classId = ConversionRelationId;
1035 address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
1036 address.objectSubId = 0;
1037 break;
1038 case OBJECT_OPCLASS:
1039 case OBJECT_OPFAMILY:
1040 address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
1041 break;
1042 case OBJECT_AMOP:
1043 case OBJECT_AMPROC:
1044 address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
1045 break;
1046 case OBJECT_LARGEOBJECT:
1047 address.classId = LargeObjectRelationId;
1048 address.objectId = oidparse(object);
1049 address.objectSubId = 0;
1050 if (!LargeObjectExists(address.objectId))
1051 {
1052 if (!missing_ok)
1053 ereport(ERROR,
1054 (errcode(ERRCODE_UNDEFINED_OBJECT),
1055 errmsg("large object %u does not exist",
1056 address.objectId)));
1057 }
1058 break;
1059 case OBJECT_CAST:
1060 {
1061 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
1062 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
1063 Oid sourcetypeid;
1064 Oid targettypeid;
1065
1066 sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
1067 targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
1068 address.classId = CastRelationId;
1069 address.objectId =
1070 get_cast_oid(sourcetypeid, targettypeid, missing_ok);
1071 address.objectSubId = 0;
1072 }
1073 break;
1074 case OBJECT_TRANSFORM:
1075 {
1076 TypeName *typename = linitial_node(TypeName, castNode(List, object));
1077 char *langname = strVal(lsecond(castNode(List, object)));
1078 Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
1079 Oid lang_id = get_language_oid(langname, missing_ok);
1080
1081 address.classId = TransformRelationId;
1082 address.objectId =
1083 get_transform_oid(type_id, lang_id, missing_ok);
1084 address.objectSubId = 0;
1085 }
1086 break;
1087 case OBJECT_TSPARSER:
1088 address.classId = TSParserRelationId;
1089 address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
1090 address.objectSubId = 0;
1091 break;
1093 address.classId = TSDictionaryRelationId;
1094 address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
1095 address.objectSubId = 0;
1096 break;
1097 case OBJECT_TSTEMPLATE:
1098 address.classId = TSTemplateRelationId;
1099 address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
1100 address.objectSubId = 0;
1101 break;
1103 address.classId = TSConfigRelationId;
1104 address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
1105 address.objectSubId = 0;
1106 break;
1108 address = get_object_address_usermapping(castNode(List, object),
1109 missing_ok);
1110 break;
1113 missing_ok);
1114 break;
1117 &relation,
1118 missing_ok);
1119 break;
1120 case OBJECT_DEFACL:
1121 address = get_object_address_defacl(castNode(List, object),
1122 missing_ok);
1123 break;
1125 address.classId = StatisticExtRelationId;
1127 missing_ok);
1128 address.objectSubId = 0;
1129 break;
1130 /* no default, to let compiler warn about missing case */
1131 }
1132
1133 if (!address.classId)
1134 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1135
1136 /*
1137 * If we could not find the supplied object, return without locking.
1138 */
1139 if (!OidIsValid(address.objectId))
1140 {
1141 Assert(missing_ok);
1142 return address;
1143 }
1144
1145 /*
1146 * If we're retrying, see if we got the same answer as last time. If
1147 * so, we're done; if not, we locked the wrong thing, so give up our
1148 * lock.
1149 */
1150 if (OidIsValid(old_address.classId))
1151 {
1152 if (old_address.classId == address.classId
1153 && old_address.objectId == address.objectId
1154 && old_address.objectSubId == address.objectSubId)
1155 break;
1156 if (old_address.classId != RelationRelationId)
1157 {
1158 if (IsSharedRelation(old_address.classId))
1159 UnlockSharedObject(old_address.classId,
1160 old_address.objectId,
1161 0, lockmode);
1162 else
1163 UnlockDatabaseObject(old_address.classId,
1164 old_address.objectId,
1165 0, lockmode);
1166 }
1167 }
1168
1169 /*
1170 * If we're dealing with a relation or attribute, then the relation is
1171 * already locked. Otherwise, we lock it now.
1172 */
1173 if (address.classId != RelationRelationId)
1174 {
1175 if (IsSharedRelation(address.classId))
1176 LockSharedObject(address.classId, address.objectId, 0,
1177 lockmode);
1178 else
1179 LockDatabaseObject(address.classId, address.objectId, 0,
1180 lockmode);
1181 }
1182
1183 /*
1184 * At this point, we've resolved the name to an OID and locked the
1185 * corresponding database object. However, it's possible that by the
1186 * time we acquire the lock on the object, concurrent DDL has modified
1187 * the database in such a way that the name we originally looked up no
1188 * longer resolves to that OID.
1189 *
1190 * We can be certain that this isn't an issue if (a) no shared
1191 * invalidation messages have been processed or (b) we've locked a
1192 * relation somewhere along the line. All the relation name lookups
1193 * in this module ultimately use RangeVarGetRelid() to acquire a
1194 * relation lock, and that function protects against the same kinds of
1195 * races we're worried about here. Even when operating on a
1196 * constraint, rule, or trigger, we still acquire AccessShareLock on
1197 * the relation, which is enough to freeze out any concurrent DDL.
1198 *
1199 * In all other cases, however, it's possible that the name we looked
1200 * up no longer refers to the object we locked, so we retry the lookup
1201 * and see whether we get the same answer.
1202 */
1203 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
1204 break;
1205 old_address = address;
1206 }
1207
1208 /* relp must be given if it's a relation */
1209 Assert(!relation || relp);
1210
1211 /* Return the object address and the relation. */
1212 if (relp)
1213 *relp = relation;
1214 return address;
1215}
1216
1217/*
1218 * Return an ObjectAddress based on a RangeVar and an object name. The
1219 * name of the relation identified by the RangeVar is prepended to the
1220 * (possibly empty) list passed in as object. This is useful to find
1221 * the ObjectAddress of objects that depend on a relation. All other
1222 * considerations are exactly as for get_object_address above.
1223 */
1226 Relation *relp, LOCKMODE lockmode,
1227 bool missing_ok)
1228{
1229 if (rel)
1230 {
1231 object = lcons(makeString(rel->relname), object);
1232 if (rel->schemaname)
1233 object = lcons(makeString(rel->schemaname), object);
1234 if (rel->catalogname)
1235 object = lcons(makeString(rel->catalogname), object);
1236 }
1237
1238 return get_object_address(objtype, (Node *) object,
1239 relp, lockmode, missing_ok);
1240}
1241
1242/*
1243 * Find an ObjectAddress for a type of object that is identified by an
1244 * unqualified name.
1245 */
1246static ObjectAddress
1248 String *strval, bool missing_ok)
1249{
1250 const char *name;
1251 ObjectAddress address;
1252
1253 name = strVal(strval);
1254
1255 /* Translate name to OID. */
1256 switch (objtype)
1257 {
1259 address.classId = AccessMethodRelationId;
1260 address.objectId = get_am_oid(name, missing_ok);
1261 address.objectSubId = 0;
1262 break;
1263 case OBJECT_DATABASE:
1264 address.classId = DatabaseRelationId;
1265 address.objectId = get_database_oid(name, missing_ok);
1266 address.objectSubId = 0;
1267 break;
1268 case OBJECT_EXTENSION:
1269 address.classId = ExtensionRelationId;
1270 address.objectId = get_extension_oid(name, missing_ok);
1271 address.objectSubId = 0;
1272 break;
1273 case OBJECT_TABLESPACE:
1274 address.classId = TableSpaceRelationId;
1275 address.objectId = get_tablespace_oid(name, missing_ok);
1276 address.objectSubId = 0;
1277 break;
1278 case OBJECT_ROLE:
1279 address.classId = AuthIdRelationId;
1280 address.objectId = get_role_oid(name, missing_ok);
1281 address.objectSubId = 0;
1282 break;
1283 case OBJECT_SCHEMA:
1284 address.classId = NamespaceRelationId;
1285 address.objectId = get_namespace_oid(name, missing_ok);
1286 address.objectSubId = 0;
1287 break;
1288 case OBJECT_LANGUAGE:
1289 address.classId = LanguageRelationId;
1290 address.objectId = get_language_oid(name, missing_ok);
1291 address.objectSubId = 0;
1292 break;
1293 case OBJECT_FDW:
1294 address.classId = ForeignDataWrapperRelationId;
1295 address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
1296 address.objectSubId = 0;
1297 break;
1299 address.classId = ForeignServerRelationId;
1300 address.objectId = get_foreign_server_oid(name, missing_ok);
1301 address.objectSubId = 0;
1302 break;
1304 address.classId = EventTriggerRelationId;
1305 address.objectId = get_event_trigger_oid(name, missing_ok);
1306 address.objectSubId = 0;
1307 break;
1309 address.classId = ParameterAclRelationId;
1310 address.objectId = ParameterAclLookup(name, missing_ok);
1311 address.objectSubId = 0;
1312 break;
1313 case OBJECT_PUBLICATION:
1314 address.classId = PublicationRelationId;
1315 address.objectId = get_publication_oid(name, missing_ok);
1316 address.objectSubId = 0;
1317 break;
1319 address.classId = SubscriptionRelationId;
1320 address.objectId = get_subscription_oid(name, missing_ok);
1321 address.objectSubId = 0;
1322 break;
1323 default:
1324 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1325 /* placate compiler, which doesn't know elog won't return */
1326 address.classId = InvalidOid;
1327 address.objectId = InvalidOid;
1328 address.objectSubId = 0;
1329 }
1330
1331 return address;
1332}
1333
1334/*
1335 * Locate a relation by qualified name.
1336 */
1337static ObjectAddress
1339 Relation *relp, LOCKMODE lockmode,
1340 bool missing_ok)
1341{
1342 Relation relation;
1343 ObjectAddress address;
1344
1345 address.classId = RelationRelationId;
1346 address.objectId = InvalidOid;
1347 address.objectSubId = 0;
1348
1350 lockmode, missing_ok);
1351 if (!relation)
1352 return address;
1353
1354 switch (objtype)
1355 {
1356 case OBJECT_INDEX:
1357 if (relation->rd_rel->relkind != RELKIND_INDEX &&
1358 relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
1359 ereport(ERROR,
1360 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1361 errmsg("\"%s\" is not an index",
1362 RelationGetRelationName(relation))));
1363 break;
1364 case OBJECT_SEQUENCE:
1365 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
1366 ereport(ERROR,
1367 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1368 errmsg("\"%s\" is not a sequence",
1369 RelationGetRelationName(relation))));
1370 break;
1371 case OBJECT_TABLE:
1372 if (relation->rd_rel->relkind != RELKIND_RELATION &&
1373 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1374 ereport(ERROR,
1375 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1376 errmsg("\"%s\" is not a table",
1377 RelationGetRelationName(relation))));
1378 break;
1379 case OBJECT_VIEW:
1380 if (relation->rd_rel->relkind != RELKIND_VIEW)
1381 ereport(ERROR,
1382 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1383 errmsg("\"%s\" is not a view",
1384 RelationGetRelationName(relation))));
1385 break;
1386 case OBJECT_MATVIEW:
1387 if (relation->rd_rel->relkind != RELKIND_MATVIEW)
1388 ereport(ERROR,
1389 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1390 errmsg("\"%s\" is not a materialized view",
1391 RelationGetRelationName(relation))));
1392 break;
1394 if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1395 ereport(ERROR,
1396 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1397 errmsg("\"%s\" is not a foreign table",
1398 RelationGetRelationName(relation))));
1399 break;
1400 default:
1401 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1402 break;
1403 }
1404
1405 /* Done. */
1406 address.objectId = RelationGetRelid(relation);
1407 *relp = relation;
1408
1409 return address;
1410}
1411
1412/*
1413 * Find object address for an object that is attached to a relation.
1414 *
1415 * Note that we take only an AccessShareLock on the relation. We need not
1416 * pass down the LOCKMODE from get_object_address(), because that is the lock
1417 * mode for the object itself, not the relation to which it is attached.
1418 */
1419static ObjectAddress
1421 Relation *relp, bool missing_ok)
1422{
1423 ObjectAddress address;
1424 Relation relation = NULL;
1425 int nnames;
1426 const char *depname;
1427 List *relname;
1428 Oid reloid;
1429
1430 /* Extract name of dependent object. */
1431 depname = strVal(llast(object));
1432
1433 /* Separate relation name from dependent object name. */
1434 nnames = list_length(object);
1435 if (nnames < 2)
1436 ereport(ERROR,
1437 (errcode(ERRCODE_SYNTAX_ERROR),
1438 errmsg("must specify relation and object name")));
1439
1440 /* Extract relation name and open relation. */
1441 relname = list_copy_head(object, nnames - 1);
1444 missing_ok);
1445
1446 reloid = relation ? RelationGetRelid(relation) : InvalidOid;
1447
1448 switch (objtype)
1449 {
1450 case OBJECT_RULE:
1451 address.classId = RewriteRelationId;
1452 address.objectId = relation ?
1453 get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
1454 address.objectSubId = 0;
1455 break;
1456 case OBJECT_TRIGGER:
1457 address.classId = TriggerRelationId;
1458 address.objectId = relation ?
1459 get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
1460 address.objectSubId = 0;
1461 break;
1463 address.classId = ConstraintRelationId;
1464 address.objectId = relation ?
1465 get_relation_constraint_oid(reloid, depname, missing_ok) :
1466 InvalidOid;
1467 address.objectSubId = 0;
1468 break;
1469 case OBJECT_POLICY:
1470 address.classId = PolicyRelationId;
1471 address.objectId = relation ?
1472 get_relation_policy_oid(reloid, depname, missing_ok) :
1473 InvalidOid;
1474 address.objectSubId = 0;
1475 break;
1476 default:
1477 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1478 }
1479
1480 /* Avoid relcache leak when object not found. */
1481 if (!OidIsValid(address.objectId))
1482 {
1483 if (relation != NULL)
1484 table_close(relation, AccessShareLock);
1485
1486 relation = NULL; /* department of accident prevention */
1487 return address;
1488 }
1489
1490 /* Done. */
1491 *relp = relation;
1492 return address;
1493}
1494
1495/*
1496 * Find the ObjectAddress for an attribute.
1497 */
1498static ObjectAddress
1500 Relation *relp, LOCKMODE lockmode,
1501 bool missing_ok)
1502{
1503 ObjectAddress address;
1504 List *relname;
1505 Oid reloid;
1506 Relation relation;
1507 const char *attname;
1509
1510 /* Extract relation name and open relation. */
1511 if (list_length(object) < 2)
1512 ereport(ERROR,
1513 (errcode(ERRCODE_SYNTAX_ERROR),
1514 errmsg("column name must be qualified")));
1515 attname = strVal(llast(object));
1516 relname = list_copy_head(object, list_length(object) - 1);
1517 /* XXX no missing_ok support here */
1518 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1519 reloid = RelationGetRelid(relation);
1520
1521 /* Look up attribute and construct return value. */
1522 attnum = get_attnum(reloid, attname);
1524 {
1525 if (!missing_ok)
1526 ereport(ERROR,
1527 (errcode(ERRCODE_UNDEFINED_COLUMN),
1528 errmsg("column \"%s\" of relation \"%s\" does not exist",
1530
1531 address.classId = RelationRelationId;
1532 address.objectId = InvalidOid;
1534 relation_close(relation, lockmode);
1535 return address;
1536 }
1537
1538 address.classId = RelationRelationId;
1539 address.objectId = reloid;
1540 address.objectSubId = attnum;
1541
1542 *relp = relation;
1543 return address;
1544}
1545
1546/*
1547 * Find the ObjectAddress for an attribute's default value.
1548 */
1549static ObjectAddress
1551 Relation *relp, LOCKMODE lockmode,
1552 bool missing_ok)
1553{
1554 ObjectAddress address;
1555 List *relname;
1556 Oid reloid;
1557 Relation relation;
1558 const char *attname;
1560 TupleDesc tupdesc;
1561 Oid defoid;
1562
1563 /* Extract relation name and open relation. */
1564 if (list_length(object) < 2)
1565 ereport(ERROR,
1566 (errcode(ERRCODE_SYNTAX_ERROR),
1567 errmsg("column name must be qualified")));
1568 attname = strVal(llast(object));
1569 relname = list_copy_head(object, list_length(object) - 1);
1570 /* XXX no missing_ok support here */
1571 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
1572 reloid = RelationGetRelid(relation);
1573
1574 tupdesc = RelationGetDescr(relation);
1575
1576 /* Look up attribute number and fetch the pg_attrdef OID */
1577 attnum = get_attnum(reloid, attname);
1578 defoid = InvalidOid;
1579 if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
1580 defoid = GetAttrDefaultOid(reloid, attnum);
1581 if (!OidIsValid(defoid))
1582 {
1583 if (!missing_ok)
1584 ereport(ERROR,
1585 (errcode(ERRCODE_UNDEFINED_COLUMN),
1586 errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
1588
1589 address.classId = AttrDefaultRelationId;
1590 address.objectId = InvalidOid;
1592 relation_close(relation, lockmode);
1593 return address;
1594 }
1595
1596 address.classId = AttrDefaultRelationId;
1597 address.objectId = defoid;
1598 address.objectSubId = 0;
1599
1600 *relp = relation;
1601 return address;
1602}
1603
1604/*
1605 * Find the ObjectAddress for a type or domain
1606 */
1607static ObjectAddress
1608get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
1609{
1610 ObjectAddress address;
1611 Type tup;
1612
1613 address.classId = TypeRelationId;
1614 address.objectId = InvalidOid;
1615 address.objectSubId = 0;
1616
1617 tup = LookupTypeName(NULL, typename, NULL, missing_ok);
1618 if (!HeapTupleIsValid(tup))
1619 {
1620 if (!missing_ok)
1621 ereport(ERROR,
1622 (errcode(ERRCODE_UNDEFINED_OBJECT),
1623 errmsg("type \"%s\" does not exist",
1624 TypeNameToString(typename))));
1625 return address;
1626 }
1627 address.objectId = typeTypeId(tup);
1628
1629 if (objtype == OBJECT_DOMAIN)
1630 {
1631 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
1632 ereport(ERROR,
1633 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1634 errmsg("\"%s\" is not a domain",
1635 TypeNameToString(typename))));
1636 }
1637
1638 ReleaseSysCache(tup);
1639
1640 return address;
1641}
1642
1643/*
1644 * Find the ObjectAddress for an opclass or opfamily.
1645 */
1646static ObjectAddress
1647get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
1648{
1649 Oid amoid;
1650 ObjectAddress address;
1651
1652 /* XXX no missing_ok support here */
1653 amoid = get_index_am_oid(strVal(linitial(object)), false);
1654 object = list_copy_tail(object, 1);
1655
1656 switch (objtype)
1657 {
1658 case OBJECT_OPCLASS:
1659 address.classId = OperatorClassRelationId;
1660 address.objectId = get_opclass_oid(amoid, object, missing_ok);
1661 address.objectSubId = 0;
1662 break;
1663 case OBJECT_OPFAMILY:
1664 address.classId = OperatorFamilyRelationId;
1665 address.objectId = get_opfamily_oid(amoid, object, missing_ok);
1666 address.objectSubId = 0;
1667 break;
1668 default:
1669 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1670 /* placate compiler, which doesn't know elog won't return */
1671 address.classId = InvalidOid;
1672 address.objectId = InvalidOid;
1673 address.objectSubId = 0;
1674 }
1675
1676 return address;
1677}
1678
1679/*
1680 * Find the ObjectAddress for an opclass/opfamily member.
1681 *
1682 * (The returned address corresponds to a pg_amop/pg_amproc object).
1683 */
1684static ObjectAddress
1686 List *object, bool missing_ok)
1687{
1688 ObjectAddress famaddr;
1689 ObjectAddress address;
1690 ListCell *cell;
1691 List *copy;
1692 TypeName *typenames[2];
1693 Oid typeoids[2];
1694 int membernum;
1695 int i;
1696
1697 /*
1698 * The last element of the object list contains the strategy or procedure
1699 * number. We need to strip that out before getting the opclass/family
1700 * address. The rest can be used directly by get_object_address_opcf().
1701 */
1702 membernum = atoi(strVal(llast(linitial(object))));
1703 copy = list_copy_head(linitial(object), list_length(linitial(object)) - 1);
1704
1705 /* no missing_ok support here */
1706 famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
1707
1708 /* find out left/right type names and OIDs */
1709 typenames[0] = typenames[1] = NULL;
1710 typeoids[0] = typeoids[1] = InvalidOid;
1711 i = 0;
1712 foreach(cell, lsecond(object))
1713 {
1714 ObjectAddress typaddr;
1715
1716 typenames[i] = lfirst_node(TypeName, cell);
1717 typaddr = get_object_address_type(OBJECT_TYPE, typenames[i], missing_ok);
1718 typeoids[i] = typaddr.objectId;
1719 if (++i >= 2)
1720 break;
1721 }
1722
1723 switch (objtype)
1724 {
1725 case OBJECT_AMOP:
1726 {
1727 HeapTuple tp;
1728
1729 ObjectAddressSet(address, AccessMethodOperatorRelationId,
1730 InvalidOid);
1731
1732 tp = SearchSysCache4(AMOPSTRATEGY,
1733 ObjectIdGetDatum(famaddr.objectId),
1734 ObjectIdGetDatum(typeoids[0]),
1735 ObjectIdGetDatum(typeoids[1]),
1736 Int16GetDatum(membernum));
1737 if (!HeapTupleIsValid(tp))
1738 {
1739 if (!missing_ok)
1740 ereport(ERROR,
1741 (errcode(ERRCODE_UNDEFINED_OBJECT),
1742 errmsg("operator %d (%s, %s) of %s does not exist",
1743 membernum,
1746 getObjectDescription(&famaddr, false))));
1747 }
1748 else
1749 {
1750 address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
1751 ReleaseSysCache(tp);
1752 }
1753 }
1754 break;
1755
1756 case OBJECT_AMPROC:
1757 {
1758 HeapTuple tp;
1759
1760 ObjectAddressSet(address, AccessMethodProcedureRelationId,
1761 InvalidOid);
1762
1763 tp = SearchSysCache4(AMPROCNUM,
1764 ObjectIdGetDatum(famaddr.objectId),
1765 ObjectIdGetDatum(typeoids[0]),
1766 ObjectIdGetDatum(typeoids[1]),
1767 Int16GetDatum(membernum));
1768 if (!HeapTupleIsValid(tp))
1769 {
1770 if (!missing_ok)
1771 ereport(ERROR,
1772 (errcode(ERRCODE_UNDEFINED_OBJECT),
1773 errmsg("function %d (%s, %s) of %s does not exist",
1774 membernum,
1777 getObjectDescription(&famaddr, false))));
1778 }
1779 else
1780 {
1781 address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
1782 ReleaseSysCache(tp);
1783 }
1784 }
1785 break;
1786 default:
1787 elog(ERROR, "unrecognized object type: %d", (int) objtype);
1788 }
1789
1790 return address;
1791}
1792
1793/*
1794 * Find the ObjectAddress for a user mapping.
1795 */
1796static ObjectAddress
1797get_object_address_usermapping(List *object, bool missing_ok)
1798{
1799 ObjectAddress address;
1800 Oid userid;
1801 char *username;
1802 char *servername;
1803 ForeignServer *server;
1804 HeapTuple tp;
1805
1806 ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
1807
1808 /* fetch string names from input lists, for error messages */
1809 username = strVal(linitial(object));
1810 servername = strVal(lsecond(object));
1811
1812 /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
1813 if (strcmp(username, "public") == 0)
1814 userid = InvalidOid;
1815 else
1816 {
1817 tp = SearchSysCache1(AUTHNAME,
1819 if (!HeapTupleIsValid(tp))
1820 {
1821 if (!missing_ok)
1822 ereport(ERROR,
1823 (errcode(ERRCODE_UNDEFINED_OBJECT),
1824 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1825 username, servername)));
1826 return address;
1827 }
1828 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
1829 ReleaseSysCache(tp);
1830 }
1831
1832 /* Now look up the pg_user_mapping tuple */
1833 server = GetForeignServerByName(servername, true);
1834 if (!server)
1835 {
1836 if (!missing_ok)
1837 ereport(ERROR,
1838 (errcode(ERRCODE_UNDEFINED_OBJECT),
1839 errmsg("server \"%s\" does not exist", servername)));
1840 return address;
1841 }
1842 tp = SearchSysCache2(USERMAPPINGUSERSERVER,
1843 ObjectIdGetDatum(userid),
1844 ObjectIdGetDatum(server->serverid));
1845 if (!HeapTupleIsValid(tp))
1846 {
1847 if (!missing_ok)
1848 ereport(ERROR,
1849 (errcode(ERRCODE_UNDEFINED_OBJECT),
1850 errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
1851 username, servername)));
1852 return address;
1853 }
1854
1855 address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
1856
1857 ReleaseSysCache(tp);
1858
1859 return address;
1860}
1861
1862/*
1863 * Find the ObjectAddress for a publication relation. The first element of
1864 * the object parameter is the relation name, the second is the
1865 * publication name.
1866 */
1867static ObjectAddress
1869 Relation *relp, bool missing_ok)
1870{
1871 ObjectAddress address;
1872 Relation relation;
1873 List *relname;
1874 char *pubname;
1875 Publication *pub;
1876
1877 ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
1878
1879 relname = linitial(object);
1881 AccessShareLock, missing_ok);
1882 if (!relation)
1883 return address;
1884
1885 /* fetch publication name from input list */
1886 pubname = strVal(lsecond(object));
1887
1888 /* Now look up the pg_publication tuple */
1889 pub = GetPublicationByName(pubname, missing_ok);
1890 if (!pub)
1891 {
1893 return address;
1894 }
1895
1896 /* Find the publication relation mapping in syscache. */
1897 address.objectId =
1898 GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
1900 ObjectIdGetDatum(pub->oid));
1901 if (!OidIsValid(address.objectId))
1902 {
1903 if (!missing_ok)
1904 ereport(ERROR,
1905 (errcode(ERRCODE_UNDEFINED_OBJECT),
1906 errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
1907 RelationGetRelationName(relation), pubname)));
1909 return address;
1910 }
1911
1912 *relp = relation;
1913 return address;
1914}
1915
1916/*
1917 * Find the ObjectAddress for a publication schema. The first element of the
1918 * object parameter is the schema name, the second is the publication name.
1919 */
1920static ObjectAddress
1922{
1923 ObjectAddress address;
1924 Publication *pub;
1925 char *pubname;
1926 char *schemaname;
1927 Oid schemaid;
1928
1929 ObjectAddressSet(address, PublicationNamespaceRelationId, InvalidOid);
1930
1931 /* Fetch schema name and publication name from input list */
1932 schemaname = strVal(linitial(object));
1933 pubname = strVal(lsecond(object));
1934
1935 schemaid = get_namespace_oid(schemaname, missing_ok);
1936 if (!OidIsValid(schemaid))
1937 return address;
1938
1939 /* Now look up the pg_publication tuple */
1940 pub = GetPublicationByName(pubname, missing_ok);
1941 if (!pub)
1942 return address;
1943
1944 /* Find the publication schema mapping in syscache */
1945 address.objectId =
1946 GetSysCacheOid2(PUBLICATIONNAMESPACEMAP,
1947 Anum_pg_publication_namespace_oid,
1948 ObjectIdGetDatum(schemaid),
1949 ObjectIdGetDatum(pub->oid));
1950 if (!OidIsValid(address.objectId) && !missing_ok)
1951 ereport(ERROR,
1952 (errcode(ERRCODE_UNDEFINED_OBJECT),
1953 errmsg("publication schema \"%s\" in publication \"%s\" does not exist",
1954 schemaname, pubname)));
1955
1956 return address;
1957}
1958
1959/*
1960 * Find the ObjectAddress for a default ACL.
1961 */
1962static ObjectAddress
1963get_object_address_defacl(List *object, bool missing_ok)
1964{
1965 HeapTuple tp;
1966 Oid userid;
1967 Oid schemaid;
1968 char *username;
1969 char *schema;
1970 char objtype;
1971 char *objtype_str;
1972 ObjectAddress address;
1973
1974 ObjectAddressSet(address, DefaultAclRelationId, InvalidOid);
1975
1976 /*
1977 * First figure out the textual attributes so that they can be used for
1978 * error reporting.
1979 */
1980 username = strVal(lsecond(object));
1981 if (list_length(object) >= 3)
1982 schema = (char *) strVal(lthird(object));
1983 else
1984 schema = NULL;
1985
1986 /*
1987 * Decode defaclobjtype. Only first char is considered; the rest of the
1988 * string, if any, is blissfully ignored.
1989 */
1990 objtype = ((char *) strVal(linitial(object)))[0];
1991 switch (objtype)
1992 {
1993 case DEFACLOBJ_RELATION:
1994 objtype_str = "tables";
1995 break;
1996 case DEFACLOBJ_SEQUENCE:
1997 objtype_str = "sequences";
1998 break;
1999 case DEFACLOBJ_FUNCTION:
2000 objtype_str = "functions";
2001 break;
2002 case DEFACLOBJ_TYPE:
2003 objtype_str = "types";
2004 break;
2005 case DEFACLOBJ_NAMESPACE:
2006 objtype_str = "schemas";
2007 break;
2008 case DEFACLOBJ_LARGEOBJECT:
2009 objtype_str = "large objects";
2010 break;
2011 default:
2012 ereport(ERROR,
2013 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2014 errmsg("unrecognized default ACL object type \"%c\"", objtype),
2015 errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
2016 DEFACLOBJ_RELATION,
2017 DEFACLOBJ_SEQUENCE,
2018 DEFACLOBJ_FUNCTION,
2019 DEFACLOBJ_TYPE,
2020 DEFACLOBJ_NAMESPACE,
2021 DEFACLOBJ_LARGEOBJECT)));
2022 }
2023
2024 /*
2025 * Look up user ID. Behave as "default ACL not found" if the user doesn't
2026 * exist.
2027 */
2028 tp = SearchSysCache1(AUTHNAME,
2030 if (!HeapTupleIsValid(tp))
2031 goto not_found;
2032 userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
2033 ReleaseSysCache(tp);
2034
2035 /*
2036 * If a schema name was given, look up its OID. If it doesn't exist,
2037 * behave as "default ACL not found".
2038 */
2039 if (schema)
2040 {
2041 schemaid = get_namespace_oid(schema, true);
2042 if (schemaid == InvalidOid)
2043 goto not_found;
2044 }
2045 else
2046 schemaid = InvalidOid;
2047
2048 /* Finally, look up the pg_default_acl object */
2049 tp = SearchSysCache3(DEFACLROLENSPOBJ,
2050 ObjectIdGetDatum(userid),
2051 ObjectIdGetDatum(schemaid),
2052 CharGetDatum(objtype));
2053 if (!HeapTupleIsValid(tp))
2054 goto not_found;
2055
2056 address.objectId = ((Form_pg_default_acl) GETSTRUCT(tp))->oid;
2057 ReleaseSysCache(tp);
2058
2059 return address;
2060
2061not_found:
2062 if (!missing_ok)
2063 {
2064 if (schema)
2065 ereport(ERROR,
2066 (errcode(ERRCODE_UNDEFINED_OBJECT),
2067 errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
2068 username, schema, objtype_str)));
2069 else
2070 ereport(ERROR,
2071 (errcode(ERRCODE_UNDEFINED_OBJECT),
2072 errmsg("default ACL for user \"%s\" on %s does not exist",
2073 username, objtype_str)));
2074 }
2075 return address;
2076}
2077
2078/*
2079 * Convert an array of TEXT into a List of string Values, as emitted by the
2080 * parser, which is what get_object_address uses as input.
2081 */
2082static List *
2084{
2085 Datum *elems;
2086 bool *nulls;
2087 int nelems;
2088 List *list = NIL;
2089 int i;
2090
2091 deconstruct_array_builtin(arr, TEXTOID, &elems, &nulls, &nelems);
2092
2093 for (i = 0; i < nelems; i++)
2094 {
2095 if (nulls[i])
2096 ereport(ERROR,
2097 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2098 errmsg("name or argument lists may not contain nulls")));
2100 }
2101
2102 return list;
2103}
2104
2105/*
2106 * SQL-callable version of get_object_address
2107 */
2108Datum
2110{
2111 char *ttype = TextDatumGetCString(PG_GETARG_DATUM(0));
2112 ArrayType *namearr = PG_GETARG_ARRAYTYPE_P(1);
2113 ArrayType *argsarr = PG_GETARG_ARRAYTYPE_P(2);
2114 int itype;
2116 List *name = NIL;
2117 TypeName *typename = NULL;
2118 List *args = NIL;
2119 Node *objnode = NULL;
2120 ObjectAddress addr;
2121 TupleDesc tupdesc;
2122 Datum values[3];
2123 bool nulls[3];
2124 HeapTuple htup;
2125 Relation relation;
2126
2127 /* Decode object type, raise error if unknown */
2128 itype = read_objtype_from_string(ttype);
2129 if (itype < 0)
2130 ereport(ERROR,
2131 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2132 errmsg("unsupported object type \"%s\"", ttype)));
2133 type = (ObjectType) itype;
2134
2135 /*
2136 * Convert the text array to the representation appropriate for the given
2137 * object type. Most use a simple string Values list, but there are some
2138 * exceptions.
2139 */
2140 if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
2142 {
2143 Datum *elems;
2144 bool *nulls;
2145 int nelems;
2146
2147 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2148 if (nelems != 1)
2149 ereport(ERROR,
2150 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2151 errmsg("name list length must be exactly %d", 1)));
2152 if (nulls[0])
2153 ereport(ERROR,
2154 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2155 errmsg("name or argument lists may not contain nulls")));
2156 typename = typeStringToTypeName(TextDatumGetCString(elems[0]), NULL);
2157 }
2158 else if (type == OBJECT_LARGEOBJECT)
2159 {
2160 Datum *elems;
2161 bool *nulls;
2162 int nelems;
2163
2164 deconstruct_array_builtin(namearr, TEXTOID, &elems, &nulls, &nelems);
2165 if (nelems != 1)
2166 ereport(ERROR,
2167 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2168 errmsg("name list length must be exactly %d", 1)));
2169 if (nulls[0])
2170 ereport(ERROR,
2171 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2172 errmsg("large object OID may not be null")));
2173 objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
2174 }
2175 else
2176 {
2178 if (name == NIL)
2179 ereport(ERROR,
2180 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2181 errmsg("name list length must be at least %d", 1)));
2182 }
2183
2184 /*
2185 * If args are given, decode them according to the object type.
2186 */
2187 if (type == OBJECT_AGGREGATE ||
2188 type == OBJECT_FUNCTION ||
2190 type == OBJECT_ROUTINE ||
2191 type == OBJECT_OPERATOR ||
2192 type == OBJECT_CAST ||
2193 type == OBJECT_AMOP ||
2195 {
2196 /* in these cases, the args list must be of TypeName */
2197 Datum *elems;
2198 bool *nulls;
2199 int nelems;
2200 int i;
2201
2202 deconstruct_array_builtin(argsarr, TEXTOID, &elems, &nulls, &nelems);
2203
2204 args = NIL;
2205 for (i = 0; i < nelems; i++)
2206 {
2207 if (nulls[i])
2208 ereport(ERROR,
2209 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2210 errmsg("name or argument lists may not contain nulls")));
2211 args = lappend(args,
2213 NULL));
2214 }
2215 }
2216 else
2217 {
2218 /* For all other object types, use string Values */
2220 }
2221
2222 /*
2223 * get_object_address is pretty sensitive to the length of its input
2224 * lists; check that they're what it wants.
2225 */
2226 switch (type)
2227 {
2230 if (list_length(name) != 1)
2231 ereport(ERROR,
2232 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2233 errmsg("name list length must be exactly %d", 1)));
2234 /* fall through to check args length */
2235 /* FALLTHROUGH */
2237 case OBJECT_CAST:
2239 case OBJECT_DEFACL:
2240 case OBJECT_TRANSFORM:
2241 if (list_length(args) != 1)
2242 ereport(ERROR,
2243 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2244 errmsg("argument list length must be exactly %d", 1)));
2245 break;
2246 case OBJECT_OPFAMILY:
2247 case OBJECT_OPCLASS:
2248 if (list_length(name) < 2)
2249 ereport(ERROR,
2250 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2251 errmsg("name list length must be at least %d", 2)));
2252 break;
2253 case OBJECT_AMOP:
2254 case OBJECT_AMPROC:
2255 if (list_length(name) < 3)
2256 ereport(ERROR,
2257 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2258 errmsg("name list length must be at least %d", 3)));
2259 /* fall through to check args length */
2260 /* FALLTHROUGH */
2261 case OBJECT_OPERATOR:
2262 if (list_length(args) != 2)
2263 ereport(ERROR,
2264 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2265 errmsg("argument list length must be exactly %d", 2)));
2266 break;
2267 default:
2268 break;
2269 }
2270
2271 /*
2272 * Now build the Node type that get_object_address() expects for the given
2273 * type.
2274 */
2275 switch (type)
2276 {
2277 case OBJECT_TABLE:
2278 case OBJECT_SEQUENCE:
2279 case OBJECT_VIEW:
2280 case OBJECT_MATVIEW:
2281 case OBJECT_INDEX:
2283 case OBJECT_COLUMN:
2284 case OBJECT_ATTRIBUTE:
2285 case OBJECT_COLLATION:
2286 case OBJECT_CONVERSION:
2288 case OBJECT_TSPARSER:
2290 case OBJECT_TSTEMPLATE:
2292 case OBJECT_DEFAULT:
2293 case OBJECT_POLICY:
2294 case OBJECT_RULE:
2295 case OBJECT_TRIGGER:
2297 case OBJECT_OPCLASS:
2298 case OBJECT_OPFAMILY:
2299 objnode = (Node *) name;
2300 break;
2302 case OBJECT_DATABASE:
2304 case OBJECT_EXTENSION:
2305 case OBJECT_FDW:
2307 case OBJECT_LANGUAGE:
2309 case OBJECT_PUBLICATION:
2310 case OBJECT_ROLE:
2311 case OBJECT_SCHEMA:
2313 case OBJECT_TABLESPACE:
2314 if (list_length(name) != 1)
2315 ereport(ERROR,
2316 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2317 errmsg("name list length must be exactly %d", 1)));
2318 objnode = linitial(name);
2319 break;
2320 case OBJECT_TYPE:
2321 case OBJECT_DOMAIN:
2322 objnode = (Node *) typename;
2323 break;
2324 case OBJECT_CAST:
2326 case OBJECT_TRANSFORM:
2327 objnode = (Node *) list_make2(typename, linitial(args));
2328 break;
2330 objnode = (Node *) list_make2(name, linitial(args));
2331 break;
2334 objnode = (Node *) list_make2(linitial(name), linitial(args));
2335 break;
2336 case OBJECT_DEFACL:
2337 objnode = (Node *) lcons(linitial(args), name);
2338 break;
2339 case OBJECT_AMOP:
2340 case OBJECT_AMPROC:
2341 objnode = (Node *) list_make2(name, args);
2342 break;
2343 case OBJECT_FUNCTION:
2344 case OBJECT_PROCEDURE:
2345 case OBJECT_ROUTINE:
2346 case OBJECT_AGGREGATE:
2347 case OBJECT_OPERATOR:
2348 {
2350
2351 owa->objname = name;
2352 owa->objargs = args;
2353 objnode = (Node *) owa;
2354 break;
2355 }
2356 case OBJECT_LARGEOBJECT:
2357 /* already handled above */
2358 break;
2359 /* no default, to let compiler warn about missing case */
2360 }
2361
2362 if (objnode == NULL)
2363 elog(ERROR, "unrecognized object type: %d", type);
2364
2365 addr = get_object_address(type, objnode,
2366 &relation, AccessShareLock, false);
2367
2368 /* We don't need the relcache entry, thank you very much */
2369 if (relation)
2371
2372 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2373 elog(ERROR, "return type must be a row type");
2374
2375 values[0] = ObjectIdGetDatum(addr.classId);
2376 values[1] = ObjectIdGetDatum(addr.objectId);
2377 values[2] = Int32GetDatum(addr.objectSubId);
2378 nulls[0] = false;
2379 nulls[1] = false;
2380 nulls[2] = false;
2381
2382 htup = heap_form_tuple(tupdesc, values, nulls);
2383
2385}
2386
2387/*
2388 * Check ownership of an object previously identified by get_object_address.
2389 */
2390void
2392 Node *object, Relation relation)
2393{
2394 switch (objtype)
2395 {
2396 case OBJECT_INDEX:
2397 case OBJECT_SEQUENCE:
2398 case OBJECT_TABLE:
2399 case OBJECT_VIEW:
2400 case OBJECT_MATVIEW:
2402 case OBJECT_COLUMN:
2403 case OBJECT_RULE:
2404 case OBJECT_TRIGGER:
2405 case OBJECT_POLICY:
2407 if (!object_ownercheck(RelationRelationId, RelationGetRelid(relation), roleid))
2409 RelationGetRelationName(relation));
2410 break;
2411 case OBJECT_TYPE:
2412 case OBJECT_DOMAIN:
2413 case OBJECT_ATTRIBUTE:
2414 if (!object_ownercheck(address.classId, address.objectId, roleid))
2416 break;
2418 {
2419 HeapTuple tuple;
2420 Oid contypid;
2421
2422 tuple = SearchSysCache1(CONSTROID,
2423 ObjectIdGetDatum(address.objectId));
2424 if (!HeapTupleIsValid(tuple))
2425 elog(ERROR, "constraint with OID %u does not exist",
2426 address.objectId);
2427
2428 contypid = ((Form_pg_constraint) GETSTRUCT(tuple))->contypid;
2429
2430 ReleaseSysCache(tuple);
2431
2432 /*
2433 * Fallback to type ownership check in this case as this is
2434 * what domain constraints rely on.
2435 */
2436 if (!object_ownercheck(TypeRelationId, contypid, roleid))
2438 }
2439 break;
2440 case OBJECT_AGGREGATE:
2441 case OBJECT_FUNCTION:
2442 case OBJECT_PROCEDURE:
2443 case OBJECT_ROUTINE:
2444 case OBJECT_OPERATOR:
2445 if (!object_ownercheck(address.classId, address.objectId, roleid))
2447 NameListToString((castNode(ObjectWithArgs, object))->objname));
2448 break;
2449 case OBJECT_DATABASE:
2451 case OBJECT_EXTENSION:
2452 case OBJECT_FDW:
2454 case OBJECT_LANGUAGE:
2455 case OBJECT_PUBLICATION:
2456 case OBJECT_SCHEMA:
2458 case OBJECT_TABLESPACE:
2459 if (!object_ownercheck(address.classId, address.objectId, roleid))
2461 strVal(object));
2462 break;
2463 case OBJECT_COLLATION:
2464 case OBJECT_CONVERSION:
2465 case OBJECT_OPCLASS:
2466 case OBJECT_OPFAMILY:
2470 if (!object_ownercheck(address.classId, address.objectId, roleid))
2472 NameListToString(castNode(List, object)));
2473 break;
2474 case OBJECT_LARGEOBJECT:
2475 if (!lo_compat_privileges &&
2476 !object_ownercheck(address.classId, address.objectId, roleid))
2477 ereport(ERROR,
2478 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2479 errmsg("must be owner of large object %u",
2480 address.objectId)));
2481 break;
2482 case OBJECT_CAST:
2483 {
2484 /* We can only check permissions on the source/target types */
2485 TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
2486 TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
2487 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
2488 Oid targettypeid = typenameTypeId(NULL, targettype);
2489
2490 if (!object_ownercheck(TypeRelationId, sourcetypeid, roleid)
2491 && !object_ownercheck(TypeRelationId, targettypeid, roleid))
2492 ereport(ERROR,
2493 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2494 errmsg("must be owner of type %s or type %s",
2495 format_type_be(sourcetypeid),
2496 format_type_be(targettypeid))));
2497 }
2498 break;
2499 case OBJECT_TRANSFORM:
2500 {
2501 TypeName *typename = linitial_node(TypeName, castNode(List, object));
2502 Oid typeid = typenameTypeId(NULL, typename);
2503
2504 if (!object_ownercheck(TypeRelationId, typeid, roleid))
2506 }
2507 break;
2508 case OBJECT_ROLE:
2509
2510 /*
2511 * We treat roles as being "owned" by those with CREATEROLE priv,
2512 * provided that they also have admin option on the role.
2513 *
2514 * However, superusers are only owned by superusers.
2515 */
2516 if (superuser_arg(address.objectId))
2517 {
2518 if (!superuser_arg(roleid))
2519 ereport(ERROR,
2520 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2521 errmsg("permission denied"),
2522 errdetail("The current user must have the %s attribute.",
2523 "SUPERUSER")));
2524 }
2525 else
2526 {
2527 if (!has_createrole_privilege(roleid))
2528 ereport(ERROR,
2529 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2530 errmsg("permission denied"),
2531 errdetail("The current user must have the %s attribute.",
2532 "CREATEROLE")));
2533 if (!is_admin_of_role(roleid, address.objectId))
2534 ereport(ERROR,
2535 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2536 errmsg("permission denied"),
2537 errdetail("The current user must have the %s option on role \"%s\".",
2538 "ADMIN",
2540 true))));
2541 }
2542 break;
2543 case OBJECT_TSPARSER:
2544 case OBJECT_TSTEMPLATE:
2547 /* We treat these object types as being owned by superusers */
2548 if (!superuser_arg(roleid))
2549 ereport(ERROR,
2550 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2551 errmsg("must be superuser")));
2552 break;
2553 case OBJECT_AMOP:
2554 case OBJECT_AMPROC:
2555 case OBJECT_DEFAULT:
2556 case OBJECT_DEFACL:
2560 /* These are currently not supported or don't make sense here. */
2561 elog(ERROR, "unsupported object type: %d", (int) objtype);
2562 break;
2563 }
2564}
2565
2566/*
2567 * get_object_namespace
2568 *
2569 * Find the schema containing the specified object. For non-schema objects,
2570 * this function returns InvalidOid.
2571 */
2572Oid
2574{
2575 int cache;
2576 HeapTuple tuple;
2577 Oid oid;
2578 const ObjectPropertyType *property;
2579
2580 /* If not owned by a namespace, just return InvalidOid. */
2581 property = get_object_property_data(address->classId);
2582 if (property->attnum_namespace == InvalidAttrNumber)
2583 return InvalidOid;
2584
2585 /* Currently, we can only handle object types with system caches. */
2586 cache = property->oid_catcache_id;
2587 Assert(cache != -1);
2588
2589 /* Fetch tuple from syscache and extract namespace attribute. */
2590 tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
2591 if (!HeapTupleIsValid(tuple))
2592 elog(ERROR, "cache lookup failed for cache %d oid %u",
2593 cache, address->objectId);
2595 tuple,
2596 property->attnum_namespace));
2597 ReleaseSysCache(tuple);
2598
2599 return oid;
2600}
2601
2602/*
2603 * Return ObjectType for the given object type as given by
2604 * getObjectTypeDescription; if no valid ObjectType code exists, but it's a
2605 * possible output type from getObjectTypeDescription, return -1.
2606 * Otherwise, an error is thrown.
2607 */
2608int
2609read_objtype_from_string(const char *objtype)
2610{
2611 int i;
2612
2613 for (i = 0; i < lengthof(ObjectTypeMap); i++)
2614 {
2615 if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
2616 return ObjectTypeMap[i].tm_type;
2617 }
2618 ereport(ERROR,
2619 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2620 errmsg("unrecognized object type \"%s\"", objtype)));
2621
2622 return -1; /* keep compiler quiet */
2623}
2624
2625/*
2626 * Interfaces to reference fields of ObjectPropertyType
2627 */
2628const char *
2630{
2631 const ObjectPropertyType *prop = get_object_property_data(class_id);
2632
2633 return prop->class_descr;
2634}
2635
2636Oid
2638{
2639 const ObjectPropertyType *prop = get_object_property_data(class_id);
2640
2641 return prop->oid_index_oid;
2642}
2643
2644int
2646{
2647 const ObjectPropertyType *prop = get_object_property_data(class_id);
2648
2649 return prop->oid_catcache_id;
2650}
2651
2652int
2654{
2655 const ObjectPropertyType *prop = get_object_property_data(class_id);
2656
2657 return prop->name_catcache_id;
2658}
2659
2662{
2663 const ObjectPropertyType *prop = get_object_property_data(class_id);
2664
2665 return prop->attnum_oid;
2666}
2667
2670{
2671 const ObjectPropertyType *prop = get_object_property_data(class_id);
2672
2673 return prop->attnum_name;
2674}
2675
2678{
2679 const ObjectPropertyType *prop = get_object_property_data(class_id);
2680
2681 return prop->attnum_namespace;
2682}
2683
2686{
2687 const ObjectPropertyType *prop = get_object_property_data(class_id);
2688
2689 return prop->attnum_owner;
2690}
2691
2694{
2695 const ObjectPropertyType *prop = get_object_property_data(class_id);
2696
2697 return prop->attnum_acl;
2698}
2699
2700/*
2701 * get_object_type
2702 *
2703 * Return the object type associated with a given object. This routine
2704 * is primarily used to determine the object type to mention in ACL check
2705 * error messages, so it's desirable for it to avoid failing.
2706 */
2708get_object_type(Oid class_id, Oid object_id)
2709{
2710 const ObjectPropertyType *prop = get_object_property_data(class_id);
2711
2712 if (prop->objtype == OBJECT_TABLE)
2713 {
2714 /*
2715 * If the property data says it's a table, dig a little deeper to get
2716 * the real relation kind, so that callers can produce more precise
2717 * error messages.
2718 */
2719 return get_relkind_objtype(get_rel_relkind(object_id));
2720 }
2721 else
2722 return prop->objtype;
2723}
2724
2725bool
2727{
2728 const ObjectPropertyType *prop = get_object_property_data(class_id);
2729
2730 return prop->is_nsp_name_unique;
2731}
2732
2733/*
2734 * Return whether we have useful data for the given object class in the
2735 * ObjectProperty table.
2736 */
2737bool
2739{
2740 int index;
2741
2742 for (index = 0; index < lengthof(ObjectProperty); index++)
2743 {
2744 if (ObjectProperty[index].class_oid == class_id)
2745 return true;
2746 }
2747
2748 return false;
2749}
2750
2751/*
2752 * Find ObjectProperty structure by class_id.
2753 */
2754static const ObjectPropertyType *
2756{
2757 static const ObjectPropertyType *prop_last = NULL;
2758 int index;
2759
2760 /*
2761 * A shortcut to speed up multiple consecutive lookups of a particular
2762 * object class.
2763 */
2764 if (prop_last && prop_last->class_oid == class_id)
2765 return prop_last;
2766
2767 for (index = 0; index < lengthof(ObjectProperty); index++)
2768 {
2769 if (ObjectProperty[index].class_oid == class_id)
2770 {
2771 prop_last = &ObjectProperty[index];
2772 return &ObjectProperty[index];
2773 }
2774 }
2775
2776 ereport(ERROR,
2777 (errmsg_internal("unrecognized class ID: %u", class_id)));
2778
2779 return NULL; /* keep MSC compiler happy */
2780}
2781
2782/*
2783 * Return a copy of the tuple for the object with the given object OID, from
2784 * the given catalog (which must have been opened by the caller and suitably
2785 * locked). NULL is returned if the OID is not found.
2786 *
2787 * We try a syscache first, if available.
2788 */
2791{
2792 return
2793 get_catalog_object_by_oid_extended(catalog, oidcol, objectId, false);
2794}
2795
2796/*
2797 * Same as get_catalog_object_by_oid(), but with an additional "locktup"
2798 * argument controlling whether to acquire a LOCKTAG_TUPLE at mode
2799 * InplaceUpdateTupleLock. See README.tuplock section "Locking to write
2800 * inplace-updated tables".
2801 */
2804 AttrNumber oidcol,
2805 Oid objectId,
2806 bool locktup)
2807{
2808 HeapTuple tuple;
2809 Oid classId = RelationGetRelid(catalog);
2810 int oidCacheId = get_object_catcache_oid(classId);
2811
2812 if (oidCacheId > 0)
2813 {
2814 if (locktup)
2815 tuple = SearchSysCacheLockedCopy1(oidCacheId,
2816 ObjectIdGetDatum(objectId));
2817 else
2818 tuple = SearchSysCacheCopy1(oidCacheId,
2819 ObjectIdGetDatum(objectId));
2820 if (!HeapTupleIsValid(tuple)) /* should not happen */
2821 return NULL;
2822 }
2823 else
2824 {
2825 Oid oidIndexId = get_object_oid_index(classId);
2826 SysScanDesc scan;
2827 ScanKeyData skey;
2828
2829 Assert(OidIsValid(oidIndexId));
2830
2831 ScanKeyInit(&skey,
2832 oidcol,
2833 BTEqualStrategyNumber, F_OIDEQ,
2834 ObjectIdGetDatum(objectId));
2835
2836 scan = systable_beginscan(catalog, oidIndexId, true,
2837 NULL, 1, &skey);
2838 tuple = systable_getnext(scan);
2839 if (!HeapTupleIsValid(tuple))
2840 {
2841 systable_endscan(scan);
2842 return NULL;
2843 }
2844
2845 if (locktup)
2846 LockTuple(catalog, &tuple->t_self, InplaceUpdateTupleLock);
2847
2848 tuple = heap_copytuple(tuple);
2849
2850 systable_endscan(scan);
2851 }
2852
2853 return tuple;
2854}
2855
2856/*
2857 * getPublicationSchemaInfo
2858 *
2859 * Get publication name and schema name from the object address into pubname and
2860 * nspname. Both pubname and nspname are palloc'd strings which will be freed by
2861 * the caller.
2862 */
2863static bool
2864getPublicationSchemaInfo(const ObjectAddress *object, bool missing_ok,
2865 char **pubname, char **nspname)
2866{
2867 HeapTuple tup;
2869
2870 tup = SearchSysCache1(PUBLICATIONNAMESPACE,
2871 ObjectIdGetDatum(object->objectId));
2872 if (!HeapTupleIsValid(tup))
2873 {
2874 if (!missing_ok)
2875 elog(ERROR, "cache lookup failed for publication schema %u",
2876 object->objectId);
2877 return false;
2878 }
2879
2881 *pubname = get_publication_name(pnform->pnpubid, missing_ok);
2882 if (!(*pubname))
2883 {
2884 ReleaseSysCache(tup);
2885 return false;
2886 }
2887
2888 *nspname = get_namespace_name(pnform->pnnspid);
2889 if (!(*nspname))
2890 {
2891 Oid schemaid = pnform->pnnspid;
2892
2893 pfree(*pubname);
2894 ReleaseSysCache(tup);
2895 if (!missing_ok)
2896 elog(ERROR, "cache lookup failed for schema %u",
2897 schemaid);
2898 return false;
2899 }
2900
2901 ReleaseSysCache(tup);
2902 return true;
2903}
2904
2905/*
2906 * getObjectDescription: build an object description for messages
2907 *
2908 * The result is a palloc'd string. NULL is returned for an undefined
2909 * object if missing_ok is true, else an error is generated.
2910 */
2911char *
2912getObjectDescription(const ObjectAddress *object, bool missing_ok)
2913{
2914 StringInfoData buffer;
2915
2916 initStringInfo(&buffer);
2917
2918 switch (object->classId)
2919 {
2920 case RelationRelationId:
2921 if (object->objectSubId == 0)
2922 getRelationDescription(&buffer, object->objectId, missing_ok);
2923 else
2924 {
2925 /* column, not whole relation */
2926 StringInfoData rel;
2927 char *attname = get_attname(object->objectId,
2928 object->objectSubId,
2929 missing_ok);
2930
2931 if (!attname)
2932 break;
2933
2934 initStringInfo(&rel);
2935 getRelationDescription(&rel, object->objectId, missing_ok);
2936 /* translator: second %s is, e.g., "table %s" */
2937 appendStringInfo(&buffer, _("column %s of %s"),
2938 attname, rel.data);
2939 pfree(rel.data);
2940 }
2941 break;
2942
2943 case ProcedureRelationId:
2944 {
2947 flags);
2948
2949 if (proname == NULL)
2950 break;
2951
2952 appendStringInfo(&buffer, _("function %s"), proname);
2953 break;
2954 }
2955
2956 case TypeRelationId:
2957 {
2959 char *typname = format_type_extended(object->objectId, -1,
2960 flags);
2961
2962 if (typname == NULL)
2963 break;
2964
2965 appendStringInfo(&buffer, _("type %s"), typname);
2966 break;
2967 }
2968
2969 case CastRelationId:
2970 {
2971 Relation castDesc;
2972 ScanKeyData skey[1];
2973 SysScanDesc rcscan;
2974 HeapTuple tup;
2975 Form_pg_cast castForm;
2976
2977 castDesc = table_open(CastRelationId, AccessShareLock);
2978
2979 ScanKeyInit(&skey[0],
2980 Anum_pg_cast_oid,
2981 BTEqualStrategyNumber, F_OIDEQ,
2982 ObjectIdGetDatum(object->objectId));
2983
2984 rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
2985 NULL, 1, skey);
2986
2987 tup = systable_getnext(rcscan);
2988
2989 if (!HeapTupleIsValid(tup))
2990 {
2991 if (!missing_ok)
2992 elog(ERROR, "could not find tuple for cast %u",
2993 object->objectId);
2994
2995 systable_endscan(rcscan);
2996 table_close(castDesc, AccessShareLock);
2997 break;
2998 }
2999
3000 castForm = (Form_pg_cast) GETSTRUCT(tup);
3001
3002 appendStringInfo(&buffer, _("cast from %s to %s"),
3003 format_type_be(castForm->castsource),
3004 format_type_be(castForm->casttarget));
3005
3006 systable_endscan(rcscan);
3007 table_close(castDesc, AccessShareLock);
3008 break;
3009 }
3010
3011 case CollationRelationId:
3012 {
3013 HeapTuple collTup;
3014 Form_pg_collation coll;
3015 char *nspname;
3016
3017 collTup = SearchSysCache1(COLLOID,
3018 ObjectIdGetDatum(object->objectId));
3019 if (!HeapTupleIsValid(collTup))
3020 {
3021 if (!missing_ok)
3022 elog(ERROR, "cache lookup failed for collation %u",
3023 object->objectId);
3024 break;
3025 }
3026
3027 coll = (Form_pg_collation) GETSTRUCT(collTup);
3028
3029 /* Qualify the name if not visible in search path */
3030 if (CollationIsVisible(object->objectId))
3031 nspname = NULL;
3032 else
3033 nspname = get_namespace_name(coll->collnamespace);
3034
3035 appendStringInfo(&buffer, _("collation %s"),
3037 NameStr(coll->collname)));
3038 ReleaseSysCache(collTup);
3039 break;
3040 }
3041
3042 case ConstraintRelationId:
3043 {
3044 HeapTuple conTup;
3046
3047 conTup = SearchSysCache1(CONSTROID,
3048 ObjectIdGetDatum(object->objectId));
3049 if (!HeapTupleIsValid(conTup))
3050 {
3051 if (!missing_ok)
3052 elog(ERROR, "cache lookup failed for constraint %u",
3053 object->objectId);
3054 break;
3055 }
3056
3057 con = (Form_pg_constraint) GETSTRUCT(conTup);
3058
3059 if (OidIsValid(con->conrelid))
3060 {
3061 StringInfoData rel;
3062
3063 initStringInfo(&rel);
3064 getRelationDescription(&rel, con->conrelid, false);
3065 /* translator: second %s is, e.g., "table %s" */
3066 appendStringInfo(&buffer, _("constraint %s on %s"),
3067 NameStr(con->conname), rel.data);
3068 pfree(rel.data);
3069 }
3070 else
3071 {
3072 appendStringInfo(&buffer, _("constraint %s"),
3073 NameStr(con->conname));
3074 }
3075
3076 ReleaseSysCache(conTup);
3077 break;
3078 }
3079
3080 case ConversionRelationId:
3081 {
3082 HeapTuple conTup;
3083 Form_pg_conversion conv;
3084 char *nspname;
3085
3086 conTup = SearchSysCache1(CONVOID,
3087 ObjectIdGetDatum(object->objectId));
3088 if (!HeapTupleIsValid(conTup))
3089 {
3090 if (!missing_ok)
3091 elog(ERROR, "cache lookup failed for conversion %u",
3092 object->objectId);
3093 break;
3094 }
3095
3096 conv = (Form_pg_conversion) GETSTRUCT(conTup);
3097
3098 /* Qualify the name if not visible in search path */
3099 if (ConversionIsVisible(object->objectId))
3100 nspname = NULL;
3101 else
3102 nspname = get_namespace_name(conv->connamespace);
3103
3104 appendStringInfo(&buffer, _("conversion %s"),
3106 NameStr(conv->conname)));
3107 ReleaseSysCache(conTup);
3108 break;
3109 }
3110
3111 case AttrDefaultRelationId:
3112 {
3113 ObjectAddress colobject;
3114
3115 colobject = GetAttrDefaultColumnAddress(object->objectId);
3116
3117 if (!OidIsValid(colobject.objectId))
3118 {
3119 if (!missing_ok)
3120 elog(ERROR, "could not find tuple for attrdef %u",
3121 object->objectId);
3122 break;
3123 }
3124
3125 /* translator: %s is typically "column %s of table %s" */
3126 appendStringInfo(&buffer, _("default value for %s"),
3127 getObjectDescription(&colobject, false));
3128 break;
3129 }
3130
3131 case LanguageRelationId:
3132 {
3133 char *langname = get_language_name(object->objectId,
3134 missing_ok);
3135
3136 if (langname)
3137 appendStringInfo(&buffer, _("language %s"),
3138 get_language_name(object->objectId, false));
3139 break;
3140 }
3141
3142 case LargeObjectRelationId:
3143 if (!LargeObjectExists(object->objectId))
3144 break;
3145 appendStringInfo(&buffer, _("large object %u"),
3146 object->objectId);
3147 break;
3148
3149 case OperatorRelationId:
3150 {
3152 char *oprname = format_operator_extended(object->objectId,
3153 flags);
3154
3155 if (oprname == NULL)
3156 break;
3157
3158 appendStringInfo(&buffer, _("operator %s"), oprname);
3159 break;
3160 }
3161
3162 case OperatorClassRelationId:
3163 {
3164 HeapTuple opcTup;
3165 Form_pg_opclass opcForm;
3166 HeapTuple amTup;
3167 Form_pg_am amForm;
3168 char *nspname;
3169
3170 opcTup = SearchSysCache1(CLAOID,
3171 ObjectIdGetDatum(object->objectId));
3172 if (!HeapTupleIsValid(opcTup))
3173 {
3174 if (!missing_ok)
3175 elog(ERROR, "cache lookup failed for opclass %u",
3176 object->objectId);
3177 break;
3178 }
3179
3180 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
3181
3182 amTup = SearchSysCache1(AMOID,
3183 ObjectIdGetDatum(opcForm->opcmethod));
3184 if (!HeapTupleIsValid(amTup))
3185 elog(ERROR, "cache lookup failed for access method %u",
3186 opcForm->opcmethod);
3187 amForm = (Form_pg_am) GETSTRUCT(amTup);
3188
3189 /* Qualify the name if not visible in search path */
3190 if (OpclassIsVisible(object->objectId))
3191 nspname = NULL;
3192 else
3193 nspname = get_namespace_name(opcForm->opcnamespace);
3194
3195 appendStringInfo(&buffer, _("operator class %s for access method %s"),
3197 NameStr(opcForm->opcname)),
3198 NameStr(amForm->amname));
3199
3200 ReleaseSysCache(amTup);
3201 ReleaseSysCache(opcTup);
3202 break;
3203 }
3204
3205 case OperatorFamilyRelationId:
3206 getOpFamilyDescription(&buffer, object->objectId, missing_ok);
3207 break;
3208
3209 case AccessMethodRelationId:
3210 {
3211 HeapTuple tup;
3212
3213 tup = SearchSysCache1(AMOID,
3214 ObjectIdGetDatum(object->objectId));
3215 if (!HeapTupleIsValid(tup))
3216 {
3217 if (!missing_ok)
3218 elog(ERROR, "cache lookup failed for access method %u",
3219 object->objectId);
3220 break;
3221 }
3222
3223 appendStringInfo(&buffer, _("access method %s"),
3224 NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
3225 ReleaseSysCache(tup);
3226 break;
3227 }
3228
3229 case AccessMethodOperatorRelationId:
3230 {
3231 Relation amopDesc;
3232 HeapTuple tup;
3233 ScanKeyData skey[1];
3234 SysScanDesc amscan;
3235 Form_pg_amop amopForm;
3236 StringInfoData opfam;
3237
3238 amopDesc = table_open(AccessMethodOperatorRelationId,
3240
3241 ScanKeyInit(&skey[0],
3242 Anum_pg_amop_oid,
3243 BTEqualStrategyNumber, F_OIDEQ,
3244 ObjectIdGetDatum(object->objectId));
3245
3246 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
3247 NULL, 1, skey);
3248
3249 tup = systable_getnext(amscan);
3250
3251 if (!HeapTupleIsValid(tup))
3252 {
3253 if (!missing_ok)
3254 elog(ERROR, "could not find tuple for amop entry %u",
3255 object->objectId);
3256
3257 systable_endscan(amscan);
3258 table_close(amopDesc, AccessShareLock);
3259 break;
3260 }
3261
3262 amopForm = (Form_pg_amop) GETSTRUCT(tup);
3263
3264 initStringInfo(&opfam);
3265 getOpFamilyDescription(&opfam, amopForm->amopfamily, false);
3266
3267 /*
3268 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3269 * completely if the type links are dangling, which is a form
3270 * of catalog corruption that could occur due to old bugs.
3271 */
3272
3273 /*------
3274 translator: %d is the operator strategy (a number), the
3275 first two %s's are data type names, the third %s is the
3276 description of the operator family, and the last %s is the
3277 textual form of the operator with arguments. */
3278 appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
3279 amopForm->amopstrategy,
3280 format_type_extended(amopForm->amoplefttype,
3282 format_type_extended(amopForm->amoprighttype,
3284 opfam.data,
3285 format_operator(amopForm->amopopr));
3286
3287 pfree(opfam.data);
3288
3289 systable_endscan(amscan);
3290 table_close(amopDesc, AccessShareLock);
3291 break;
3292 }
3293
3294 case AccessMethodProcedureRelationId:
3295 {
3296 Relation amprocDesc;
3297 ScanKeyData skey[1];
3298 SysScanDesc amscan;
3299 HeapTuple tup;
3300 Form_pg_amproc amprocForm;
3301 StringInfoData opfam;
3302
3303 amprocDesc = table_open(AccessMethodProcedureRelationId,
3305
3306 ScanKeyInit(&skey[0],
3307 Anum_pg_amproc_oid,
3308 BTEqualStrategyNumber, F_OIDEQ,
3309 ObjectIdGetDatum(object->objectId));
3310
3311 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
3312 NULL, 1, skey);
3313
3314 tup = systable_getnext(amscan);
3315
3316 if (!HeapTupleIsValid(tup))
3317 {
3318 if (!missing_ok)
3319 elog(ERROR, "could not find tuple for amproc entry %u",
3320 object->objectId);
3321
3322 systable_endscan(amscan);
3323 table_close(amprocDesc, AccessShareLock);
3324 break;
3325 }
3326
3327 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
3328
3329 initStringInfo(&opfam);
3330 getOpFamilyDescription(&opfam, amprocForm->amprocfamily, false);
3331
3332 /*
3333 * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail
3334 * completely if the type links are dangling, which is a form
3335 * of catalog corruption that could occur due to old bugs.
3336 */
3337
3338 /*------
3339 translator: %d is the function number, the first two %s's
3340 are data type names, the third %s is the description of the
3341 operator family, and the last %s is the textual form of the
3342 function with arguments. */
3343 appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
3344 amprocForm->amprocnum,
3345 format_type_extended(amprocForm->amproclefttype,
3347 format_type_extended(amprocForm->amprocrighttype,
3349 opfam.data,
3350 format_procedure(amprocForm->amproc));
3351
3352 pfree(opfam.data);
3353
3354 systable_endscan(amscan);
3355 table_close(amprocDesc, AccessShareLock);
3356 break;
3357 }
3358
3359 case RewriteRelationId:
3360 {
3361 Relation ruleDesc;
3362 ScanKeyData skey[1];
3363 SysScanDesc rcscan;
3364 HeapTuple tup;
3366 StringInfoData rel;
3367
3368 ruleDesc = table_open(RewriteRelationId, AccessShareLock);
3369
3370 ScanKeyInit(&skey[0],
3371 Anum_pg_rewrite_oid,
3372 BTEqualStrategyNumber, F_OIDEQ,
3373 ObjectIdGetDatum(object->objectId));
3374
3375 rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
3376 NULL, 1, skey);
3377
3378 tup = systable_getnext(rcscan);
3379
3380 if (!HeapTupleIsValid(tup))
3381 {
3382 if (!missing_ok)
3383 elog(ERROR, "could not find tuple for rule %u",
3384 object->objectId);
3385
3386 systable_endscan(rcscan);
3387 table_close(ruleDesc, AccessShareLock);
3388 break;
3389 }
3390
3392
3393 initStringInfo(&rel);
3394 getRelationDescription(&rel, rule->ev_class, false);
3395
3396 /* translator: second %s is, e.g., "table %s" */
3397 appendStringInfo(&buffer, _("rule %s on %s"),
3398 NameStr(rule->rulename), rel.data);
3399 pfree(rel.data);
3400 systable_endscan(rcscan);
3401 table_close(ruleDesc, AccessShareLock);
3402 break;
3403 }
3404
3405 case TriggerRelationId:
3406 {
3407 Relation trigDesc;
3408 ScanKeyData skey[1];
3409 SysScanDesc tgscan;
3410 HeapTuple tup;
3411 Form_pg_trigger trig;
3412 StringInfoData rel;
3413
3414 trigDesc = table_open(TriggerRelationId, AccessShareLock);
3415
3416 ScanKeyInit(&skey[0],
3417 Anum_pg_trigger_oid,
3418 BTEqualStrategyNumber, F_OIDEQ,
3419 ObjectIdGetDatum(object->objectId));
3420
3421 tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
3422 NULL, 1, skey);
3423
3424 tup = systable_getnext(tgscan);
3425
3426 if (!HeapTupleIsValid(tup))
3427 {
3428 if (!missing_ok)
3429 elog(ERROR, "could not find tuple for trigger %u",
3430 object->objectId);
3431
3432 systable_endscan(tgscan);
3433 table_close(trigDesc, AccessShareLock);
3434 break;
3435 }
3436
3437 trig = (Form_pg_trigger) GETSTRUCT(tup);
3438
3439 initStringInfo(&rel);
3440 getRelationDescription(&rel, trig->tgrelid, false);
3441
3442 /* translator: second %s is, e.g., "table %s" */
3443 appendStringInfo(&buffer, _("trigger %s on %s"),
3444 NameStr(trig->tgname), rel.data);
3445 pfree(rel.data);
3446 systable_endscan(tgscan);
3447 table_close(trigDesc, AccessShareLock);
3448 break;
3449 }
3450
3451 case NamespaceRelationId:
3452 {
3453 char *nspname;
3454
3455 nspname = get_namespace_name(object->objectId);
3456 if (!nspname)
3457 {
3458 if (!missing_ok)
3459 elog(ERROR, "cache lookup failed for namespace %u",
3460 object->objectId);
3461 break;
3462 }
3463 appendStringInfo(&buffer, _("schema %s"), nspname);
3464 break;
3465 }
3466
3467 case StatisticExtRelationId:
3468 {
3469 HeapTuple stxTup;
3470 Form_pg_statistic_ext stxForm;
3471 char *nspname;
3472
3473 stxTup = SearchSysCache1(STATEXTOID,
3474 ObjectIdGetDatum(object->objectId));
3475 if (!HeapTupleIsValid(stxTup))
3476 {
3477 if (!missing_ok)
3478 elog(ERROR, "could not find tuple for statistics object %u",
3479 object->objectId);
3480 break;
3481 }
3482
3483 stxForm = (Form_pg_statistic_ext) GETSTRUCT(stxTup);
3484
3485 /* Qualify the name if not visible in search path */
3486 if (StatisticsObjIsVisible(object->objectId))
3487 nspname = NULL;
3488 else
3489 nspname = get_namespace_name(stxForm->stxnamespace);
3490
3491 appendStringInfo(&buffer, _("statistics object %s"),
3493 NameStr(stxForm->stxname)));
3494
3495 ReleaseSysCache(stxTup);
3496 break;
3497 }
3498
3499 case TSParserRelationId:
3500 {
3501 HeapTuple tup;
3502 Form_pg_ts_parser prsForm;
3503 char *nspname;
3504
3505 tup = SearchSysCache1(TSPARSEROID,
3506 ObjectIdGetDatum(object->objectId));
3507 if (!HeapTupleIsValid(tup))
3508 {
3509 if (!missing_ok)
3510 elog(ERROR, "cache lookup failed for text search parser %u",
3511 object->objectId);
3512 break;
3513 }
3514 prsForm = (Form_pg_ts_parser) GETSTRUCT(tup);
3515
3516 /* Qualify the name if not visible in search path */
3517 if (TSParserIsVisible(object->objectId))
3518 nspname = NULL;
3519 else
3520 nspname = get_namespace_name(prsForm->prsnamespace);
3521
3522 appendStringInfo(&buffer, _("text search parser %s"),
3524 NameStr(prsForm->prsname)));
3525 ReleaseSysCache(tup);
3526 break;
3527 }
3528
3529 case TSDictionaryRelationId:
3530 {
3531 HeapTuple tup;
3532 Form_pg_ts_dict dictForm;
3533 char *nspname;
3534
3535 tup = SearchSysCache1(TSDICTOID,
3536 ObjectIdGetDatum(object->objectId));
3537 if (!HeapTupleIsValid(tup))
3538 {
3539 if (!missing_ok)
3540 elog(ERROR, "cache lookup failed for text search dictionary %u",
3541 object->objectId);
3542 break;
3543 }
3544
3545 dictForm = (Form_pg_ts_dict) GETSTRUCT(tup);
3546
3547 /* Qualify the name if not visible in search path */
3548 if (TSDictionaryIsVisible(object->objectId))
3549 nspname = NULL;
3550 else
3551 nspname = get_namespace_name(dictForm->dictnamespace);
3552
3553 appendStringInfo(&buffer, _("text search dictionary %s"),
3555 NameStr(dictForm->dictname)));
3556 ReleaseSysCache(tup);
3557 break;
3558 }
3559
3560 case TSTemplateRelationId:
3561 {
3562 HeapTuple tup;
3563 Form_pg_ts_template tmplForm;
3564 char *nspname;
3565
3566 tup = SearchSysCache1(TSTEMPLATEOID,
3567 ObjectIdGetDatum(object->objectId));
3568 if (!HeapTupleIsValid(tup))
3569 {
3570 if (!missing_ok)
3571 elog(ERROR, "cache lookup failed for text search template %u",
3572 object->objectId);
3573 break;
3574 }
3575
3576 tmplForm = (Form_pg_ts_template) GETSTRUCT(tup);
3577
3578 /* Qualify the name if not visible in search path */
3579 if (TSTemplateIsVisible(object->objectId))
3580 nspname = NULL;
3581 else
3582 nspname = get_namespace_name(tmplForm->tmplnamespace);
3583
3584 appendStringInfo(&buffer, _("text search template %s"),
3586 NameStr(tmplForm->tmplname)));
3587 ReleaseSysCache(tup);
3588 break;
3589 }
3590
3591 case TSConfigRelationId:
3592 {
3593 HeapTuple tup;
3594 Form_pg_ts_config cfgForm;
3595 char *nspname;
3596
3597 tup = SearchSysCache1(TSCONFIGOID,
3598 ObjectIdGetDatum(object->objectId));
3599 if (!HeapTupleIsValid(tup))
3600 {
3601 if (!missing_ok)
3602 elog(ERROR, "cache lookup failed for text search configuration %u",
3603 object->objectId);
3604 break;
3605 }
3606
3607 cfgForm = (Form_pg_ts_config) GETSTRUCT(tup);
3608
3609 /* Qualify the name if not visible in search path */
3610 if (TSConfigIsVisible(object->objectId))
3611 nspname = NULL;
3612 else
3613 nspname = get_namespace_name(cfgForm->cfgnamespace);
3614
3615 appendStringInfo(&buffer, _("text search configuration %s"),
3617 NameStr(cfgForm->cfgname)));
3618 ReleaseSysCache(tup);
3619 break;
3620 }
3621
3622 case AuthIdRelationId:
3623 {
3624 char *username = GetUserNameFromId(object->objectId,
3625 missing_ok);
3626
3627 if (username)
3628 appendStringInfo(&buffer, _("role %s"), username);
3629 break;
3630 }
3631
3632 case AuthMemRelationId:
3633 {
3634 Relation amDesc;
3635 ScanKeyData skey[1];
3636 SysScanDesc rcscan;
3637 HeapTuple tup;
3638 Form_pg_auth_members amForm;
3639
3640 amDesc = table_open(AuthMemRelationId, AccessShareLock);
3641
3642 ScanKeyInit(&skey[0],
3643 Anum_pg_auth_members_oid,
3644 BTEqualStrategyNumber, F_OIDEQ,
3645 ObjectIdGetDatum(object->objectId));
3646
3647 rcscan = systable_beginscan(amDesc, AuthMemOidIndexId, true,
3648 NULL, 1, skey);
3649
3650 tup = systable_getnext(rcscan);
3651
3652 if (!HeapTupleIsValid(tup))
3653 {
3654 if (!missing_ok)
3655 elog(ERROR, "could not find tuple for role membership %u",
3656 object->objectId);
3657
3658 systable_endscan(rcscan);
3660 break;
3661 }
3662
3663 amForm = (Form_pg_auth_members) GETSTRUCT(tup);
3664
3665 appendStringInfo(&buffer, _("membership of role %s in role %s"),
3666 GetUserNameFromId(amForm->member, false),
3667 GetUserNameFromId(amForm->roleid, false));
3668
3669 systable_endscan(rcscan);
3671 break;
3672 }
3673
3674 case DatabaseRelationId:
3675 {
3676 char *datname;
3677
3679 if (!datname)
3680 {
3681 if (!missing_ok)
3682 elog(ERROR, "cache lookup failed for database %u",
3683 object->objectId);
3684 break;
3685 }
3686 appendStringInfo(&buffer, _("database %s"), datname);
3687 break;
3688 }
3689
3690 case TableSpaceRelationId:
3691 {
3692 char *tblspace;
3693
3694 tblspace = get_tablespace_name(object->objectId);
3695 if (!tblspace)
3696 {
3697 if (!missing_ok)
3698 elog(ERROR, "cache lookup failed for tablespace %u",
3699 object->objectId);
3700 break;
3701 }
3702 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
3703 break;
3704 }
3705
3706 case ForeignDataWrapperRelationId:
3707 {
3708 ForeignDataWrapper *fdw;
3709
3711 missing_ok);
3712 if (fdw)
3713 appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
3714 break;
3715 }
3716
3717 case ForeignServerRelationId:
3718 {
3719 ForeignServer *srv;
3720
3721 srv = GetForeignServerExtended(object->objectId, missing_ok);
3722 if (srv)
3723 appendStringInfo(&buffer, _("server %s"), srv->servername);
3724 break;
3725 }
3726
3727 case UserMappingRelationId:
3728 {
3729 HeapTuple tup;
3730 Oid useid;
3731 char *usename;
3732 Form_pg_user_mapping umform;
3733 ForeignServer *srv;
3734
3735 tup = SearchSysCache1(USERMAPPINGOID,
3736 ObjectIdGetDatum(object->objectId));
3737 if (!HeapTupleIsValid(tup))
3738 {
3739 if (!missing_ok)
3740 elog(ERROR, "cache lookup failed for user mapping %u",
3741 object->objectId);
3742 break;
3743 }
3744
3745 umform = (Form_pg_user_mapping) GETSTRUCT(tup);
3746 useid = umform->umuser;
3747 srv = GetForeignServer(umform->umserver);
3748
3749 ReleaseSysCache(tup);
3750
3751 if (OidIsValid(useid))
3752 usename = GetUserNameFromId(useid, false);
3753 else
3754 usename = "public";
3755
3756 appendStringInfo(&buffer, _("user mapping for %s on server %s"), usename,
3757 srv->servername);
3758 break;
3759 }
3760
3761 case DefaultAclRelationId:
3762 {
3763 Relation defaclrel;
3764 ScanKeyData skey[1];
3765 SysScanDesc rcscan;
3766 HeapTuple tup;
3767 Form_pg_default_acl defacl;
3768 char *rolename;
3769 char *nspname;
3770
3771 defaclrel = table_open(DefaultAclRelationId, AccessShareLock);
3772
3773 ScanKeyInit(&skey[0],
3774 Anum_pg_default_acl_oid,
3775 BTEqualStrategyNumber, F_OIDEQ,
3776 ObjectIdGetDatum(object->objectId));
3777
3778 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
3779 true, NULL, 1, skey);
3780
3781 tup = systable_getnext(rcscan);
3782
3783 if (!HeapTupleIsValid(tup))
3784 {
3785 if (!missing_ok)
3786 elog(ERROR, "could not find tuple for default ACL %u",
3787 object->objectId);
3788
3789 systable_endscan(rcscan);
3790 table_close(defaclrel, AccessShareLock);
3791 break;
3792 }
3793
3794 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
3795
3796 rolename = GetUserNameFromId(defacl->defaclrole, false);
3797
3798 if (OidIsValid(defacl->defaclnamespace))
3799 nspname = get_namespace_name(defacl->defaclnamespace);
3800 else
3801 nspname = NULL;
3802
3803 switch (defacl->defaclobjtype)
3804 {
3805 case DEFACLOBJ_RELATION:
3806 if (nspname)
3807 appendStringInfo(&buffer,
3808 _("default privileges on new relations belonging to role %s in schema %s"),
3809 rolename, nspname);
3810 else
3811 appendStringInfo(&buffer,
3812 _("default privileges on new relations belonging to role %s"),
3813 rolename);
3814 break;
3815 case DEFACLOBJ_SEQUENCE:
3816 if (nspname)
3817 appendStringInfo(&buffer,
3818 _("default privileges on new sequences belonging to role %s in schema %s"),
3819 rolename, nspname);
3820 else
3821 appendStringInfo(&buffer,
3822 _("default privileges on new sequences belonging to role %s"),
3823 rolename);
3824 break;
3825 case DEFACLOBJ_FUNCTION:
3826 if (nspname)
3827 appendStringInfo(&buffer,
3828 _("default privileges on new functions belonging to role %s in schema %s"),
3829 rolename, nspname);
3830 else
3831 appendStringInfo(&buffer,
3832 _("default privileges on new functions belonging to role %s"),
3833 rolename);
3834 break;
3835 case DEFACLOBJ_TYPE:
3836 if (nspname)
3837 appendStringInfo(&buffer,
3838 _("default privileges on new types belonging to role %s in schema %s"),
3839 rolename, nspname);
3840 else
3841 appendStringInfo(&buffer,
3842 _("default privileges on new types belonging to role %s"),
3843 rolename);
3844 break;
3845 case DEFACLOBJ_NAMESPACE:
3846 Assert(!nspname);
3847 appendStringInfo(&buffer,
3848 _("default privileges on new schemas belonging to role %s"),
3849 rolename);
3850 break;
3851 case DEFACLOBJ_LARGEOBJECT:
3852 Assert(!nspname);
3853 appendStringInfo(&buffer,
3854 _("default privileges on new large objects belonging to role %s"),
3855 rolename);
3856 break;
3857 default:
3858 /* shouldn't get here */
3859 if (nspname)
3860 appendStringInfo(&buffer,
3861 _("default privileges belonging to role %s in schema %s"),
3862 rolename, nspname);
3863 else
3864 appendStringInfo(&buffer,
3865 _("default privileges belonging to role %s"),
3866 rolename);
3867 break;
3868 }
3869
3870 systable_endscan(rcscan);
3871 table_close(defaclrel, AccessShareLock);
3872 break;
3873 }
3874
3875 case ExtensionRelationId:
3876 {
3877 char *extname;
3878
3879 extname = get_extension_name(object->objectId);
3880 if (!extname)
3881 {
3882 if (!missing_ok)
3883 elog(ERROR, "cache lookup failed for extension %u",
3884 object->objectId);
3885 break;
3886 }
3887 appendStringInfo(&buffer, _("extension %s"), extname);
3888 break;
3889 }
3890
3891 case EventTriggerRelationId:
3892 {
3893 HeapTuple tup;
3894
3895 tup = SearchSysCache1(EVENTTRIGGEROID,
3896 ObjectIdGetDatum(object->objectId));
3897 if (!HeapTupleIsValid(tup))
3898 {
3899 if (!missing_ok)
3900 elog(ERROR, "cache lookup failed for event trigger %u",
3901 object->objectId);
3902 break;
3903 }
3904 appendStringInfo(&buffer, _("event trigger %s"),
3905 NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname));
3906 ReleaseSysCache(tup);
3907 break;
3908 }
3909
3910 case ParameterAclRelationId:
3911 {
3912 HeapTuple tup;
3913 Datum nameDatum;
3914 char *parname;
3915
3916 tup = SearchSysCache1(PARAMETERACLOID,
3917 ObjectIdGetDatum(object->objectId));
3918 if (!HeapTupleIsValid(tup))
3919 {
3920 if (!missing_ok)
3921 elog(ERROR, "cache lookup failed for parameter ACL %u",
3922 object->objectId);
3923 break;
3924 }
3925 nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tup,
3926 Anum_pg_parameter_acl_parname);
3927 parname = TextDatumGetCString(nameDatum);
3928 appendStringInfo(&buffer, _("parameter %s"), parname);
3929 ReleaseSysCache(tup);
3930 break;
3931 }
3932
3933 case PolicyRelationId:
3934 {
3935 Relation policy_rel;
3936 ScanKeyData skey[1];
3937 SysScanDesc sscan;
3938 HeapTuple tuple;
3939 Form_pg_policy form_policy;
3940 StringInfoData rel;
3941
3942 policy_rel = table_open(PolicyRelationId, AccessShareLock);
3943
3944 ScanKeyInit(&skey[0],
3945 Anum_pg_policy_oid,
3946 BTEqualStrategyNumber, F_OIDEQ,
3947 ObjectIdGetDatum(object->objectId));
3948
3949 sscan = systable_beginscan(policy_rel, PolicyOidIndexId,
3950 true, NULL, 1, skey);
3951
3952 tuple = systable_getnext(sscan);
3953
3954 if (!HeapTupleIsValid(tuple))
3955 {
3956 if (!missing_ok)
3957 elog(ERROR, "could not find tuple for policy %u",
3958 object->objectId);
3959
3960 systable_endscan(sscan);
3961 table_close(policy_rel, AccessShareLock);
3962 break;
3963 }
3964
3965 form_policy = (Form_pg_policy) GETSTRUCT(tuple);
3966
3967 initStringInfo(&rel);
3968 getRelationDescription(&rel, form_policy->polrelid, false);
3969
3970 /* translator: second %s is, e.g., "table %s" */
3971 appendStringInfo(&buffer, _("policy %s on %s"),
3972 NameStr(form_policy->polname), rel.data);
3973 pfree(rel.data);
3974 systable_endscan(sscan);
3975 table_close(policy_rel, AccessShareLock);
3976 break;
3977 }
3978
3979 case PublicationRelationId:
3980 {
3981 char *pubname = get_publication_name(object->objectId,
3982 missing_ok);
3983
3984 if (pubname)
3985 appendStringInfo(&buffer, _("publication %s"), pubname);
3986 break;
3987 }
3988
3989 case PublicationNamespaceRelationId:
3990 {
3991 char *pubname;
3992 char *nspname;
3993
3994 if (!getPublicationSchemaInfo(object, missing_ok,
3995 &pubname, &nspname))
3996 break;
3997
3998 appendStringInfo(&buffer, _("publication of schema %s in publication %s"),
3999 nspname, pubname);
4000 pfree(pubname);
4001 pfree(nspname);
4002 break;
4003 }
4004
4005 case PublicationRelRelationId:
4006 {
4007 HeapTuple tup;
4008 char *pubname;
4010 StringInfoData rel;
4011
4012 tup = SearchSysCache1(PUBLICATIONREL,
4013 ObjectIdGetDatum(object->objectId));
4014 if (!HeapTupleIsValid(tup))
4015 {
4016 if (!missing_ok)
4017 elog(ERROR, "cache lookup failed for publication table %u",
4018 object->objectId);
4019 break;
4020 }
4021
4022 prform = (Form_pg_publication_rel) GETSTRUCT(tup);
4023 pubname = get_publication_name(prform->prpubid, false);
4024
4025 initStringInfo(&rel);
4026 getRelationDescription(&rel, prform->prrelid, false);
4027
4028 /* translator: first %s is, e.g., "table %s" */
4029 appendStringInfo(&buffer, _("publication of %s in publication %s"),
4030 rel.data, pubname);
4031 pfree(rel.data);
4032 ReleaseSysCache(tup);
4033 break;
4034 }
4035
4036 case SubscriptionRelationId:
4037 {
4038 char *subname = get_subscription_name(object->objectId,
4039 missing_ok);
4040
4041 if (subname)
4042 appendStringInfo(&buffer, _("subscription %s"), subname);
4043 break;
4044 }
4045
4046 case TransformRelationId:
4047 {
4048 HeapTuple trfTup;
4049 Form_pg_transform trfForm;
4050
4051 trfTup = SearchSysCache1(TRFOID,
4052 ObjectIdGetDatum(object->objectId));
4053 if (!HeapTupleIsValid(trfTup))
4054 {
4055 if (!missing_ok)
4056 elog(ERROR, "could not find tuple for transform %u",
4057 object->objectId);
4058 break;
4059 }
4060
4061 trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
4062
4063 appendStringInfo(&buffer, _("transform for %s language %s"),
4064 format_type_be(trfForm->trftype),
4065 get_language_name(trfForm->trflang, false));
4066
4067 ReleaseSysCache(trfTup);
4068 break;
4069 }
4070
4071 default:
4072 elog(ERROR, "unsupported object class: %u", object->classId);
4073 }
4074
4075 /* an empty buffer is equivalent to no object found */
4076 if (buffer.len == 0)
4077 return NULL;
4078
4079 return buffer.data;
4080}
4081
4082/*
4083 * getObjectDescriptionOids: as above, except the object is specified by Oids
4084 */
4085char *
4087{
4088 ObjectAddress address;
4089
4090 address.classId = classid;
4091 address.objectId = objid;
4092 address.objectSubId = 0;
4093
4094 return getObjectDescription(&address, false);
4095}
4096
4097/*
4098 * subroutine for getObjectDescription: describe a relation
4099 *
4100 * The result is appended to "buffer".
4101 */
4102static void
4103getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok)
4104{
4105 HeapTuple relTup;
4106 Form_pg_class relForm;
4107 char *nspname;
4108 char *relname;
4109
4110 relTup = SearchSysCache1(RELOID,
4111 ObjectIdGetDatum(relid));
4112 if (!HeapTupleIsValid(relTup))
4113 {
4114 if (!missing_ok)
4115 elog(ERROR, "cache lookup failed for relation %u", relid);
4116 return;
4117 }
4118 relForm = (Form_pg_class) GETSTRUCT(relTup);
4119
4120 /* Qualify the name if not visible in search path */
4121 if (RelationIsVisible(relid))
4122 nspname = NULL;
4123 else
4124 nspname = get_namespace_name(relForm->relnamespace);
4125
4126 relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
4127
4128 switch (relForm->relkind)
4129 {
4130 case RELKIND_RELATION:
4131 case RELKIND_PARTITIONED_TABLE:
4132 appendStringInfo(buffer, _("table %s"),
4133 relname);
4134 break;
4135 case RELKIND_INDEX:
4136 case RELKIND_PARTITIONED_INDEX:
4137 appendStringInfo(buffer, _("index %s"),
4138 relname);
4139 break;
4140 case RELKIND_SEQUENCE:
4141 appendStringInfo(buffer, _("sequence %s"),
4142 relname);
4143 break;
4144 case RELKIND_TOASTVALUE:
4145 appendStringInfo(buffer, _("toast table %s"),
4146 relname);
4147 break;
4148 case RELKIND_VIEW:
4149 appendStringInfo(buffer, _("view %s"),
4150 relname);
4151 break;
4152 case RELKIND_MATVIEW:
4153 appendStringInfo(buffer, _("materialized view %s"),
4154 relname);
4155 break;
4156 case RELKIND_COMPOSITE_TYPE:
4157 appendStringInfo(buffer, _("composite type %s"),
4158 relname);
4159 break;
4160 case RELKIND_FOREIGN_TABLE:
4161 appendStringInfo(buffer, _("foreign table %s"),
4162 relname);
4163 break;
4164 default:
4165 /* shouldn't get here */
4166 appendStringInfo(buffer, _("relation %s"),
4167 relname);
4168 break;
4169 }
4170
4171 ReleaseSysCache(relTup);
4172}
4173
4174/*
4175 * subroutine for getObjectDescription: describe an operator family
4176 */
4177static void
4178getOpFamilyDescription(StringInfo buffer, Oid opfid, bool missing_ok)
4179{
4180 HeapTuple opfTup;
4181 Form_pg_opfamily opfForm;
4182 HeapTuple amTup;
4183 Form_pg_am amForm;
4184 char *nspname;
4185
4186 opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
4187 if (!HeapTupleIsValid(opfTup))
4188 {
4189 if (!missing_ok)
4190 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
4191 return;
4192 }
4193 opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
4194
4195 amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
4196 if (!HeapTupleIsValid(amTup))
4197 elog(ERROR, "cache lookup failed for access method %u",
4198 opfForm->opfmethod);
4199 amForm = (Form_pg_am) GETSTRUCT(amTup);
4200
4201 /* Qualify the name if not visible in search path */
4202 if (OpfamilyIsVisible(opfid))
4203 nspname = NULL;
4204 else
4205 nspname = get_namespace_name(opfForm->opfnamespace);
4206
4207 appendStringInfo(buffer, _("operator family %s for access method %s"),
4209 NameStr(opfForm->opfname)),
4210 NameStr(amForm->amname));
4211
4212 ReleaseSysCache(amTup);
4213 ReleaseSysCache(opfTup);
4214}
4215
4216/*
4217 * SQL-level callable version of getObjectDescription
4218 */
4219Datum
4221{
4222 Oid classid = PG_GETARG_OID(0);
4223 Oid objid = PG_GETARG_OID(1);
4224 int32 objsubid = PG_GETARG_INT32(2);
4225 char *description;
4226 ObjectAddress address;
4227
4228 /* for "pinned" items in pg_depend, return null */
4229 if (!OidIsValid(classid) && !OidIsValid(objid))
4231
4232 address.classId = classid;
4233 address.objectId = objid;
4234 address.objectSubId = objsubid;
4235
4236 description = getObjectDescription(&address, true);
4237
4238 if (description == NULL)
4240
4242}
4243
4244/*
4245 * SQL-level callable function to obtain object type + identity
4246 */
4247Datum
4249{
4250 Oid classid = PG_GETARG_OID(0);
4251 Oid objid = PG_GETARG_OID(1);
4252 int32 objsubid = PG_GETARG_INT32(2);
4253 Oid schema_oid = InvalidOid;
4254 const char *objname = NULL;
4255 char *objidentity;
4256 ObjectAddress address;
4257 Datum values[4];
4258 bool nulls[4];
4259 TupleDesc tupdesc;
4260 HeapTuple htup;
4261
4262 address.classId = classid;
4263 address.objectId = objid;
4264 address.objectSubId = objsubid;
4265
4266 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4267 elog(ERROR, "return type must be a row type");
4268
4269 if (is_objectclass_supported(address.classId))
4270 {
4271 HeapTuple objtup;
4272 Relation catalog = table_open(address.classId, AccessShareLock);
4273
4274 objtup = get_catalog_object_by_oid(catalog,
4276 address.objectId);
4277 if (objtup != NULL)
4278 {
4279 bool isnull;
4280 AttrNumber nspAttnum;
4281 AttrNumber nameAttnum;
4282
4283 nspAttnum = get_object_attnum_namespace(address.classId);
4284 if (nspAttnum != InvalidAttrNumber)
4285 {
4286 schema_oid = heap_getattr(objtup, nspAttnum,
4287 RelationGetDescr(catalog), &isnull);
4288 if (isnull)
4289 elog(ERROR, "invalid null namespace in object %u/%u/%d",
4290 address.classId, address.objectId, address.objectSubId);
4291 }
4292
4293 /*
4294 * We only return the object name if it can be used (together with
4295 * the schema name, if any) as a unique identifier.
4296 */
4298 {
4299 nameAttnum = get_object_attnum_name(address.classId);
4300 if (nameAttnum != InvalidAttrNumber)
4301 {
4302 Datum nameDatum;
4303
4304 nameDatum = heap_getattr(objtup, nameAttnum,
4305 RelationGetDescr(catalog), &isnull);
4306 if (isnull)
4307 elog(ERROR, "invalid null name in object %u/%u/%d",
4308 address.classId, address.objectId, address.objectSubId);
4309 objname = quote_identifier(NameStr(*(DatumGetName(nameDatum))));
4310 }
4311 }
4312 }
4313
4314 table_close(catalog, AccessShareLock);
4315 }
4316
4317 /* object type, which can never be NULL */
4319 nulls[0] = false;
4320
4321 /*
4322 * Before doing anything, extract the object identity. If the identity
4323 * could not be found, set all the fields except the object type to NULL.
4324 */
4325 objidentity = getObjectIdentity(&address, true);
4326
4327 /* schema name */
4328 if (OidIsValid(schema_oid) && objidentity)
4329 {
4330 const char *schema = quote_identifier(get_namespace_name(schema_oid));
4331
4332 values[1] = CStringGetTextDatum(schema);
4333 nulls[1] = false;
4334 }
4335 else
4336 nulls[1] = true;
4337
4338 /* object name */
4339 if (objname && objidentity)
4340 {
4341 values[2] = CStringGetTextDatum(objname);
4342 nulls[2] = false;
4343 }
4344 else
4345 nulls[2] = true;
4346
4347 /* object identity */
4348 if (objidentity)
4349 {
4350 values[3] = CStringGetTextDatum(objidentity);
4351 nulls[3] = false;
4352 }
4353 else
4354 nulls[3] = true;
4355
4356 htup = heap_form_tuple(tupdesc, values, nulls);
4357
4359}
4360
4361/*
4362 * SQL-level callable function to obtain object type + identity
4363 */
4364Datum
4366{
4367 Oid classid = PG_GETARG_OID(0);
4368 Oid objid = PG_GETARG_OID(1);
4369 int32 objsubid = PG_GETARG_INT32(2);
4370 ObjectAddress address;
4371 char *identity;
4372 List *names;
4373 List *args;
4374 Datum values[3];
4375 bool nulls[3];
4376 TupleDesc tupdesc;
4377 HeapTuple htup;
4378
4379 address.classId = classid;
4380 address.objectId = objid;
4381 address.objectSubId = objsubid;
4382
4383 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4384 elog(ERROR, "return type must be a row type");
4385
4386 /* object type, which can never be NULL */
4388 nulls[0] = false;
4389
4390 /* object identity */
4391 identity = getObjectIdentityParts(&address, &names, &args, true);
4392 if (identity == NULL)
4393 {
4394 nulls[1] = true;
4395 nulls[2] = true;
4396 }
4397 else
4398 {
4399 pfree(identity);
4400
4401 /* object_names */
4402 if (names != NIL)
4404 else
4406 nulls[1] = false;
4407
4408 /* object_args */
4409 if (args)
4411 else
4413 nulls[2] = false;
4414 }
4415
4416 htup = heap_form_tuple(tupdesc, values, nulls);
4417
4419}
4420
4421/*
4422 * SQL-level callable function to obtain the ACL of a specified object, given
4423 * its catalog OID, object OID and sub-object ID.
4424 */
4425Datum
4427{
4428 Oid classId = PG_GETARG_OID(0);
4429 Oid objectId = PG_GETARG_OID(1);
4430 int32 objsubid = PG_GETARG_INT32(2);
4431 Oid catalogId;
4432 AttrNumber Anum_acl;
4433 Datum datum;
4434 bool isnull;
4435 HeapTuple tup;
4436
4437 /* for "pinned" items in pg_depend, return null */
4438 if (!OidIsValid(classId) && !OidIsValid(objectId))
4440
4441 /* for large objects, the catalog to look at is pg_largeobject_metadata */
4442 catalogId = (classId == LargeObjectRelationId) ?
4443 LargeObjectMetadataRelationId : classId;
4444 Anum_acl = get_object_attnum_acl(catalogId);
4445
4446 /* return NULL if no ACL field for this catalog */
4447 if (Anum_acl == InvalidAttrNumber)
4449
4450 /*
4451 * If dealing with a relation's attribute (objsubid is set), the ACL is
4452 * retrieved from pg_attribute.
4453 */
4454 if (classId == RelationRelationId && objsubid != 0)
4455 {
4456 AttrNumber attnum = (AttrNumber) objsubid;
4457
4458 tup = SearchSysCacheCopyAttNum(objectId, attnum);
4459
4460 if (!HeapTupleIsValid(tup))
4462
4463 datum = SysCacheGetAttr(ATTNUM, tup, Anum_pg_attribute_attacl,
4464 &isnull);
4465 }
4466 else
4467 {
4468 Relation rel;
4469
4470 rel = table_open(catalogId, AccessShareLock);
4471
4473 objectId);
4474 if (!HeapTupleIsValid(tup))
4475 {
4478 }
4479
4480 datum = heap_getattr(tup, Anum_acl, RelationGetDescr(rel), &isnull);
4482 }
4483
4484 if (isnull)
4486
4487 PG_RETURN_DATUM(datum);
4488}
4489
4490/*
4491 * Return a palloc'ed string that describes the type of object that the
4492 * passed address is for.
4493 *
4494 * Keep ObjectTypeMap in sync with this.
4495 */
4496char *
4497getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
4498{
4499 StringInfoData buffer;
4500
4501 initStringInfo(&buffer);
4502
4503 switch (object->classId)
4504 {
4505 case RelationRelationId:
4506 getRelationTypeDescription(&buffer, object->objectId,
4507 object->objectSubId,
4508 missing_ok);
4509 break;
4510
4511 case ProcedureRelationId:
4512 getProcedureTypeDescription(&buffer, object->objectId,
4513 missing_ok);
4514 break;
4515
4516 case TypeRelationId:
4517 appendStringInfoString(&buffer, "type");
4518 break;
4519
4520 case CastRelationId:
4521 appendStringInfoString(&buffer, "cast");
4522 break;
4523
4524 case CollationRelationId:
4525 appendStringInfoString(&buffer, "collation");
4526 break;
4527
4528 case ConstraintRelationId:
4529 getConstraintTypeDescription(&buffer, object->objectId,
4530 missing_ok);
4531 break;
4532
4533 case ConversionRelationId:
4534 appendStringInfoString(&buffer, "conversion");
4535 break;
4536
4537 case AttrDefaultRelationId:
4538 appendStringInfoString(&buffer, "default value");
4539 break;
4540
4541 case LanguageRelationId:
4542 appendStringInfoString(&buffer, "language");
4543 break;
4544
4545 case LargeObjectRelationId:
4546 appendStringInfoString(&buffer, "large object");
4547 break;
4548
4549 case OperatorRelationId:
4550 appendStringInfoString(&buffer, "operator");
4551 break;
4552
4553 case OperatorClassRelationId:
4554 appendStringInfoString(&buffer, "operator class");
4555 break;
4556
4557 case OperatorFamilyRelationId:
4558 appendStringInfoString(&buffer, "operator family");
4559 break;
4560
4561 case AccessMethodRelationId:
4562 appendStringInfoString(&buffer, "access method");
4563 break;
4564
4565 case AccessMethodOperatorRelationId:
4566 appendStringInfoString(&buffer, "operator of access method");
4567 break;
4568
4569 case AccessMethodProcedureRelationId:
4570 appendStringInfoString(&buffer, "function of access method");
4571 break;
4572
4573 case RewriteRelationId:
4574 appendStringInfoString(&buffer, "rule");
4575 break;
4576
4577 case TriggerRelationId:
4578 appendStringInfoString(&buffer, "trigger");
4579 break;
4580
4581 case NamespaceRelationId:
4582 appendStringInfoString(&buffer, "schema");
4583 break;
4584
4585 case StatisticExtRelationId:
4586 appendStringInfoString(&buffer, "statistics object");
4587 break;
4588
4589 case TSParserRelationId:
4590 appendStringInfoString(&buffer, "text search parser");
4591 break;
4592
4593 case TSDictionaryRelationId:
4594 appendStringInfoString(&buffer, "text search dictionary");
4595 break;
4596
4597 case TSTemplateRelationId:
4598 appendStringInfoString(&buffer, "text search template");
4599 break;
4600
4601 case TSConfigRelationId:
4602 appendStringInfoString(&buffer, "text search configuration");
4603 break;
4604
4605 case AuthIdRelationId:
4606 appendStringInfoString(&buffer, "role");
4607 break;
4608
4609 case AuthMemRelationId:
4610 appendStringInfoString(&buffer, "role membership");
4611 break;
4612
4613 case DatabaseRelationId:
4614 appendStringInfoString(&buffer, "database");
4615 break;
4616
4617 case TableSpaceRelationId:
4618 appendStringInfoString(&buffer, "tablespace");
4619 break;
4620
4621 case ForeignDataWrapperRelationId:
4622 appendStringInfoString(&buffer, "foreign-data wrapper");
4623 break;
4624
4625 case ForeignServerRelationId:
4626 appendStringInfoString(&buffer, "server");
4627 break;
4628
4629 case UserMappingRelationId:
4630 appendStringInfoString(&buffer, "user mapping");
4631 break;
4632
4633 case DefaultAclRelationId:
4634 appendStringInfoString(&buffer, "default acl");
4635 break;
4636
4637 case ExtensionRelationId:
4638 appendStringInfoString(&buffer, "extension");
4639 break;
4640
4641 case EventTriggerRelationId:
4642 appendStringInfoString(&buffer, "event trigger");
4643 break;
4644
4645 case ParameterAclRelationId:
4646 appendStringInfoString(&buffer, "parameter ACL");
4647 break;
4648
4649 case PolicyRelationId:
4650 appendStringInfoString(&buffer, "policy");
4651 break;
4652
4653 case PublicationRelationId:
4654 appendStringInfoString(&buffer, "publication");
4655 break;
4656
4657 case PublicationNamespaceRelationId:
4658 appendStringInfoString(&buffer, "publication namespace");
4659 break;
4660
4661 case PublicationRelRelationId:
4662 appendStringInfoString(&buffer, "publication relation");
4663 break;
4664
4665 case SubscriptionRelationId:
4666 appendStringInfoString(&buffer, "subscription");
4667 break;
4668
4669 case TransformRelationId:
4670 appendStringInfoString(&buffer, "transform");
4671 break;
4672
4673 default:
4674 elog(ERROR, "unsupported object class: %u", object->classId);
4675 }
4676
4677 /* the result can never be empty */
4678 Assert(buffer.len > 0);
4679
4680 return buffer.data;
4681}
4682
4683/*
4684 * subroutine for getObjectTypeDescription: describe a relation type
4685 */
4686static void
4688 bool missing_ok)
4689{
4690 HeapTuple relTup;
4691 Form_pg_class relForm;
4692
4693 relTup = SearchSysCache1(RELOID,
4694 ObjectIdGetDatum(relid));
4695 if (!HeapTupleIsValid(relTup))
4696 {
4697 if (!missing_ok)
4698 elog(ERROR, "cache lookup failed for relation %u", relid);
4699
4700 /* fallback to "relation" for an undefined object */
4701 appendStringInfoString(buffer, "relation");
4702 return;
4703 }
4704 relForm = (Form_pg_class) GETSTRUCT(relTup);
4705
4706 switch (relForm->relkind)
4707 {
4708 case RELKIND_RELATION:
4709 case RELKIND_PARTITIONED_TABLE:
4710 appendStringInfoString(buffer, "table");
4711 break;
4712 case RELKIND_INDEX:
4713 case RELKIND_PARTITIONED_INDEX:
4714 appendStringInfoString(buffer, "index");
4715 break;
4716 case RELKIND_SEQUENCE:
4717 appendStringInfoString(buffer, "sequence");
4718 break;
4719 case RELKIND_TOASTVALUE:
4720 appendStringInfoString(buffer, "toast table");
4721 break;
4722 case RELKIND_VIEW:
4723 appendStringInfoString(buffer, "view");
4724 break;
4725 case RELKIND_MATVIEW:
4726 appendStringInfoString(buffer, "materialized view");
4727 break;
4728 case RELKIND_COMPOSITE_TYPE:
4729 appendStringInfoString(buffer, "composite type");
4730 break;
4731 case RELKIND_FOREIGN_TABLE:
4732 appendStringInfoString(buffer, "foreign table");
4733 break;
4734 default:
4735 /* shouldn't get here */
4736 appendStringInfoString(buffer, "relation");
4737 break;
4738 }
4739
4740 if (objectSubId != 0)
4741 appendStringInfoString(buffer, " column");
4742
4743 ReleaseSysCache(relTup);
4744}
4745
4746/*
4747 * subroutine for getObjectTypeDescription: describe a constraint type
4748 */
4749static void
4750getConstraintTypeDescription(StringInfo buffer, Oid constroid, bool missing_ok)
4751{
4752 Relation constrRel;
4753 HeapTuple constrTup;
4754 Form_pg_constraint constrForm;
4755
4756 constrRel = table_open(ConstraintRelationId, AccessShareLock);
4757 constrTup = get_catalog_object_by_oid(constrRel, Anum_pg_constraint_oid,
4758 constroid);
4759 if (!HeapTupleIsValid(constrTup))
4760 {
4761 if (!missing_ok)
4762 elog(ERROR, "cache lookup failed for constraint %u", constroid);
4763
4764 table_close(constrRel, AccessShareLock);
4765
4766 /* fallback to "constraint" for an undefined object */
4767 appendStringInfoString(buffer, "constraint");
4768 return;
4769 }
4770
4771 constrForm = (Form_pg_constraint) GETSTRUCT(constrTup);
4772
4773 if (OidIsValid(constrForm->conrelid))
4774 appendStringInfoString(buffer, "table constraint");
4775 else if (OidIsValid(constrForm->contypid))
4776 appendStringInfoString(buffer, "domain constraint");
4777 else
4778 elog(ERROR, "invalid constraint %u", constrForm->oid);
4779
4780 table_close(constrRel, AccessShareLock);
4781}
4782
4783/*
4784 * subroutine for getObjectTypeDescription: describe a procedure type
4785 */
4786static void
4788 bool missing_ok)
4789{
4790 HeapTuple procTup;
4791 Form_pg_proc procForm;
4792
4793 procTup = SearchSysCache1(PROCOID,
4794 ObjectIdGetDatum(procid));
4795 if (!HeapTupleIsValid(procTup))
4796 {
4797 if (!missing_ok)
4798 elog(ERROR, "cache lookup failed for procedure %u", procid);
4799
4800 /* fallback to "procedure" for an undefined object */
4801 appendStringInfoString(buffer, "routine");
4802 return;
4803 }
4804 procForm = (Form_pg_proc) GETSTRUCT(procTup);
4805
4806 if (procForm->prokind == PROKIND_AGGREGATE)
4807 appendStringInfoString(buffer, "aggregate");
4808 else if (procForm->prokind == PROKIND_PROCEDURE)
4809 appendStringInfoString(buffer, "procedure");
4810 else /* function or window function */
4811 appendStringInfoString(buffer, "function");
4812
4813 ReleaseSysCache(procTup);
4814}
4815
4816/*
4817 * Obtain a given object's identity, as a palloc'ed string.
4818 *
4819 * This is for machine consumption, so it's not translated. All elements are
4820 * schema-qualified when appropriate. Returns NULL if the object could not
4821 * be found.
4822 */
4823char *
4824getObjectIdentity(const ObjectAddress *object, bool missing_ok)
4825{
4826 return getObjectIdentityParts(object, NULL, NULL, missing_ok);
4827}
4828
4829/*
4830 * As above, but more detailed.
4831 *
4832 * There are two sets of return values: the identity itself as a palloc'd
4833 * string is returned. objname and objargs, if not NULL, are output parameters
4834 * that receive lists of C-strings that are useful to give back to
4835 * get_object_address() to reconstruct the ObjectAddress. Returns NULL if
4836 * the object could not be found.
4837 */
4838char *
4840 List **objname, List **objargs,
4841 bool missing_ok)
4842{
4843 StringInfoData buffer;
4844
4845 initStringInfo(&buffer);
4846
4847 /*
4848 * Make sure that both objname and objargs were passed, or none was; and
4849 * initialize them to empty lists. For objname this is useless because it
4850 * will be initialized in all cases inside the switch; but we do it anyway
4851 * so that we can test below that no branch leaves it unset.
4852 */
4853 Assert(PointerIsValid(objname) == PointerIsValid(objargs));
4854 if (objname)
4855 {
4856 *objname = NIL;
4857 *objargs = NIL;
4858 }
4859
4860 switch (object->classId)
4861 {
4862 case RelationRelationId:
4863 {
4864 char *attr = NULL;
4865
4866 /*
4867 * Check for the attribute first, so as if it is missing we
4868 * can skip the entire relation description.
4869 */
4870 if (object->objectSubId != 0)
4871 {
4872 attr = get_attname(object->objectId,
4873 object->objectSubId,
4874 missing_ok);
4875
4876 if (missing_ok && attr == NULL)
4877 break;
4878 }
4879
4880 getRelationIdentity(&buffer, object->objectId, objname,
4881 missing_ok);
4882 if (objname && *objname == NIL)
4883 break;
4884
4885 if (attr)
4886 {
4887 appendStringInfo(&buffer, ".%s",
4888 quote_identifier(attr));
4889 if (objname)
4890 *objname = lappend(*objname, attr);
4891 }
4892 }
4893 break;
4894
4895 case ProcedureRelationId:
4896 {
4899 flags);
4900
4901 if (proname == NULL)
4902 break;
4903
4905 if (objname)
4906 format_procedure_parts(object->objectId, objname, objargs,
4907 missing_ok);
4908 break;
4909 }
4910
4911 case TypeRelationId:
4912 {
4914 char *typeout;
4915
4916 typeout = format_type_extended(object->objectId, -1, flags);
4917
4918 if (typeout == NULL)
4919 break;
4920
4921 appendStringInfoString(&buffer, typeout);
4922 if (objname)
4923 *objname = list_make1(typeout);
4924 }
4925 break;
4926
4927 case CastRelationId:
4928 {
4929 Relation castRel;
4930 HeapTuple tup;
4931 Form_pg_cast castForm;
4932
4933 castRel = table_open(CastRelationId, AccessShareLock);
4934
4935 tup = get_catalog_object_by_oid(castRel, Anum_pg_cast_oid,
4936 object->objectId);
4937
4938 if (!HeapTupleIsValid(tup))
4939 {
4940 if (!missing_ok)
4941 elog(ERROR, "could not find tuple for cast %u",
4942 object->objectId);
4943
4944 table_close(castRel, AccessShareLock);
4945 break;
4946 }
4947
4948 castForm = (Form_pg_cast) GETSTRUCT(tup);
4949
4950 appendStringInfo(&buffer, "(%s AS %s)",
4951 format_type_be_qualified(castForm->castsource),
4952 format_type_be_qualified(castForm->casttarget));
4953
4954 if (objname)
4955 {
4956 *objname = list_make1(format_type_be_qualified(castForm->castsource));
4957 *objargs = list_make1(format_type_be_qualified(castForm->casttarget));
4958 }
4959
4960 table_close(castRel, AccessShareLock);
4961 break;
4962 }
4963
4964 case CollationRelationId:
4965 {
4966 HeapTuple collTup;
4967 Form_pg_collation coll;
4968 char *schema;
4969
4970 collTup = SearchSysCache1(COLLOID,
4971 ObjectIdGetDatum(object->objectId));
4972 if (!HeapTupleIsValid(collTup))
4973 {
4974 if (!missing_ok)
4975 elog(ERROR, "cache lookup failed for collation %u",
4976 object->objectId);
4977 break;
4978 }
4979 coll = (Form_pg_collation) GETSTRUCT(collTup);
4980 schema = get_namespace_name_or_temp(coll->collnamespace);
4981 appendStringInfoString(&buffer,
4983 NameStr(coll->collname)));
4984 if (objname)
4985 *objname = list_make2(schema,
4986 pstrdup(NameStr(coll->collname)));
4987 ReleaseSysCache(collTup);
4988 break;
4989 }
4990
4991 case ConstraintRelationId:
4992 {
4993 HeapTuple conTup;
4995
4996 conTup = SearchSysCache1(CONSTROID,
4997 ObjectIdGetDatum(object->objectId));
4998 if (!HeapTupleIsValid(conTup))
4999 {
5000 if (!missing_ok)
5001 elog(ERROR, "cache lookup failed for constraint %u",
5002 object->objectId);
5003 break;
5004 }
5005 con = (Form_pg_constraint) GETSTRUCT(conTup);
5006
5007 if (OidIsValid(con->conrelid))
5008 {
5009 appendStringInfo(&buffer, "%s on ",
5010 quote_identifier(NameStr(con->conname)));
5011 getRelationIdentity(&buffer, con->conrelid, objname,
5012 false);
5013 if (objname)
5014 *objname = lappend(*objname, pstrdup(NameStr(con->conname)));
5015 }
5016 else
5017 {
5018 ObjectAddress domain;
5019
5020 Assert(OidIsValid(con->contypid));
5021 domain.classId = TypeRelationId;
5022 domain.objectId = con->contypid;
5023 domain.objectSubId = 0;
5024
5025 appendStringInfo(&buffer, "%s on %s",
5026 quote_identifier(NameStr(con->conname)),
5027 getObjectIdentityParts(&domain, objname,
5028 objargs, false));
5029
5030 if (objname)
5031 *objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
5032 }
5033
5034 ReleaseSysCache(conTup);
5035 break;
5036 }
5037
5038 case ConversionRelationId:
5039 {
5040 HeapTuple conTup;
5041 Form_pg_conversion conForm;
5042 char *schema;
5043
5044 conTup = SearchSysCache1(CONVOID,
5045 ObjectIdGetDatum(object->objectId));
5046 if (!HeapTupleIsValid(conTup))
5047 {
5048 if (!missing_ok)
5049 elog(ERROR, "cache lookup failed for conversion %u",
5050 object->objectId);
5051 break;
5052 }
5053 conForm = (Form_pg_conversion) GETSTRUCT(conTup);
5054 schema = get_namespace_name_or_temp(conForm->connamespace);
5055 appendStringInfoString(&buffer,
5057 NameStr(conForm->conname)));
5058 if (objname)
5059 *objname = list_make2(schema,
5060 pstrdup(NameStr(conForm->conname)));
5061 ReleaseSysCache(conTup);
5062 break;
5063 }
5064
5065 case AttrDefaultRelationId:
5066 {
5067 ObjectAddress colobject;
5068
5069 colobject = GetAttrDefaultColumnAddress(object->objectId);
5070
5071 if (!OidIsValid(colobject.objectId))
5072 {
5073 if (!missing_ok)
5074 elog(ERROR, "could not find tuple for attrdef %u",
5075 object->objectId);
5076 break;
5077 }
5078
5079 appendStringInfo(&buffer, "for %s",
5080 getObjectIdentityParts(&colobject,
5081 objname, objargs,
5082 false));
5083 break;
5084 }
5085
5086 case LanguageRelationId:
5087 {
5088 HeapTuple langTup;
5089 Form_pg_language langForm;
5090
5091 langTup = SearchSysCache1(LANGOID,
5092 ObjectIdGetDatum(object->objectId));
5093 if (!HeapTupleIsValid(langTup))
5094 {
5095 if (!missing_ok)
5096 elog(ERROR, "cache lookup failed for language %u",
5097 object->objectId);
5098 break;
5099 }
5100 langForm = (Form_pg_language) GETSTRUCT(langTup);
5101 appendStringInfoString(&buffer,
5102 quote_identifier(NameStr(langForm->lanname)));
5103 if (objname)
5104 *objname = list_make1(pstrdup(NameStr(langForm->lanname)));
5105 ReleaseSysCache(langTup);
5106 break;
5107 }
5108
5109 case LargeObjectRelationId:
5110 if (!LargeObjectExists(object->objectId))
5111 break;
5112 appendStringInfo(&buffer, "%u",
5113 object->objectId);
5114 if (objname)
5115 *objname = list_make1(psprintf("%u", object->objectId));
5116 break;
5117
5118 case OperatorRelationId:
5119 {
5121 char *oprname = format_operator_extended(object->objectId,
5122 flags);
5123
5124 if (oprname == NULL)
5125 break;
5126
5127 appendStringInfoString(&buffer, oprname);
5128 if (objname)
5129 format_operator_parts(object->objectId, objname, objargs, missing_ok);
5130 break;
5131 }
5132
5133 case OperatorClassRelationId:
5134 {
5135 HeapTuple opcTup;
5136 Form_pg_opclass opcForm;
5137 HeapTuple amTup;
5138 Form_pg_am amForm;
5139 char *schema;
5140
5141 opcTup = SearchSysCache1(CLAOID,
5142 ObjectIdGetDatum(object->objectId));
5143 if (!HeapTupleIsValid(opcTup))
5144 {
5145 if (!missing_ok)
5146 elog(ERROR, "cache lookup failed for opclass %u",
5147 object->objectId);
5148 break;
5149 }
5150 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
5151 schema = get_namespace_name_or_temp(opcForm->opcnamespace);
5152
5153 amTup = SearchSysCache1(AMOID,
5154 ObjectIdGetDatum(opcForm->opcmethod));
5155 if (!HeapTupleIsValid(amTup))
5156 elog(ERROR, "cache lookup failed for access method %u",
5157 opcForm->opcmethod);
5158 amForm = (Form_pg_am) GETSTRUCT(amTup);
5159
5160 appendStringInfo(&buffer, "%s USING %s",
5162 NameStr(opcForm->opcname)),
5163 quote_identifier(NameStr(amForm->amname)));
5164 if (objname)
5165 *objname = list_make3(pstrdup(NameStr(amForm->amname)),
5166 schema,
5167 pstrdup(NameStr(opcForm->opcname)));
5168
5169 ReleaseSysCache(amTup);
5170 ReleaseSysCache(opcTup);
5171 break;
5172 }
5173
5174 case OperatorFamilyRelationId:
5175 getOpFamilyIdentity(&buffer, object->objectId, objname,
5176 missing_ok);
5177 break;
5178
5179 case AccessMethodRelationId:
5180 {
5181 char *amname;
5182
5183 amname = get_am_name(object->objectId);
5184 if (!amname)
5185 {
5186 if (!missing_ok)
5187 elog(ERROR, "cache lookup failed for access method %u",
5188 object->objectId);
5189 break;
5190 }
5191 appendStringInfoString(&buffer, quote_identifier(amname));
5192 if (objname)
5193 *objname = list_make1(amname);
5194 }
5195 break;
5196
5197 case AccessMethodOperatorRelationId:
5198 {
5199 Relation amopDesc;
5200 HeapTuple tup;
5201 ScanKeyData skey[1];
5202 SysScanDesc amscan;
5203 Form_pg_amop amopForm;
5204 StringInfoData opfam;
5205 char *ltype;
5206 char *rtype;
5207
5208 amopDesc = table_open(AccessMethodOperatorRelationId,
5210
5211 ScanKeyInit(&skey[0],
5212 Anum_pg_amop_oid,
5213 BTEqualStrategyNumber, F_OIDEQ,
5214 ObjectIdGetDatum(object->objectId));
5215
5216 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
5217 NULL, 1, skey);
5218
5219 tup = systable_getnext(amscan);
5220
5221 if (!HeapTupleIsValid(tup))
5222 {
5223 if (!missing_ok)
5224 elog(ERROR, "could not find tuple for amop entry %u",
5225 object->objectId);
5226
5227 systable_endscan(amscan);
5228 table_close(amopDesc, AccessShareLock);
5229 break;
5230 }
5231
5232 amopForm = (Form_pg_amop) GETSTRUCT(tup);
5233
5234 initStringInfo(&opfam);
5235 getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname,
5236 false);
5237
5238 ltype = format_type_be_qualified(amopForm->amoplefttype);
5239 rtype = format_type_be_qualified(amopForm->amoprighttype);
5240
5241 if (objname)
5242 {
5243 *objname = lappend(*objname,
5244 psprintf("%d", amopForm->amopstrategy));
5245 *objargs = list_make2(ltype, rtype);
5246 }
5247
5248 appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
5249 amopForm->amopstrategy,
5250 ltype, rtype, opfam.data);
5251
5252 pfree(opfam.data);
5253
5254 systable_endscan(amscan);
5255 table_close(amopDesc, AccessShareLock);
5256 break;
5257 }
5258
5259 case AccessMethodProcedureRelationId:
5260 {
5261 Relation amprocDesc;
5262 ScanKeyData skey[1];
5263 SysScanDesc amscan;
5264 HeapTuple tup;
5265 Form_pg_amproc amprocForm;
5266 StringInfoData opfam;
5267 char *ltype;
5268 char *rtype;
5269
5270 amprocDesc = table_open(AccessMethodProcedureRelationId,
5272
5273 ScanKeyInit(&skey[0],
5274 Anum_pg_amproc_oid,
5275 BTEqualStrategyNumber, F_OIDEQ,
5276 ObjectIdGetDatum(object->objectId));
5277
5278 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
5279 NULL, 1, skey);
5280
5281 tup = systable_getnext(amscan);
5282
5283 if (!HeapTupleIsValid(tup))
5284 {
5285 if (!missing_ok)
5286 elog(ERROR, "could not find tuple for amproc entry %u",
5287 object->objectId);
5288
5289 systable_endscan(amscan);
5290 table_close(amprocDesc, AccessShareLock);
5291 break;
5292 }
5293
5294 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
5295
5296 initStringInfo(&opfam);
5297 getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname,
5298 false);
5299
5300 ltype = format_type_be_qualified(amprocForm->amproclefttype);
5301 rtype = format_type_be_qualified(amprocForm->amprocrighttype);
5302
5303 if (objname)
5304 {
5305 *objname = lappend(*objname,
5306 psprintf("%d", amprocForm->amprocnum));
5307 *objargs = list_make2(ltype, rtype);
5308 }
5309
5310 appendStringInfo(&buffer, "function %d (%s, %s) of %s",
5311 amprocForm->amprocnum,
5312 ltype, rtype, opfam.data);
5313
5314 pfree(opfam.data);
5315
5316 systable_endscan(amscan);
5317 table_close(amprocDesc, AccessShareLock);
5318 break;
5319 }
5320
5321 case RewriteRelationId:
5322 {
5323 Relation ruleDesc;
5324 HeapTuple tup;
5326
5327 ruleDesc = table_open(RewriteRelationId, AccessShareLock);
5328
5329 tup = get_catalog_object_by_oid(ruleDesc, Anum_pg_rewrite_oid,
5330 object->objectId);
5331
5332 if (!HeapTupleIsValid(tup))
5333 {
5334 if (!missing_ok)
5335 elog(ERROR, "could not find tuple for rule %u",
5336 object->objectId);
5337
5338 table_close(ruleDesc, AccessShareLock);
5339 break;
5340 }
5341
5343
5344 appendStringInfo(&buffer, "%s on ",
5345 quote_identifier(NameStr(rule->rulename)));
5346 getRelationIdentity(&buffer, rule->ev_class, objname, false);
5347 if (objname)
5348 *objname = lappend(*objname, pstrdup(NameStr(rule->rulename)));
5349
5350 table_close(ruleDesc, AccessShareLock);
5351 break;
5352 }
5353
5354 case TriggerRelationId:
5355 {
5356 Relation trigDesc;
5357 HeapTuple tup;
5358 Form_pg_trigger trig;
5359
5360 trigDesc = table_open(TriggerRelationId, AccessShareLock);
5361
5362 tup = get_catalog_object_by_oid(trigDesc, Anum_pg_trigger_oid,
5363 object->objectId);
5364
5365 if (!HeapTupleIsValid(tup))
5366 {
5367 if (!missing_ok)
5368 elog(ERROR, "could not find tuple for trigger %u",
5369 object->objectId);
5370
5371 table_close(trigDesc, AccessShareLock);
5372 break;
5373 }
5374
5375 trig = (Form_pg_trigger) GETSTRUCT(tup);
5376
5377 appendStringInfo(&buffer, "%s on ",
5378 quote_identifier(NameStr(trig->tgname)));
5379 getRelationIdentity(&buffer, trig->tgrelid, objname, false);
5380 if (objname)
5381 *objname = lappend(*objname, pstrdup(NameStr(trig->tgname)));
5382
5383 table_close(trigDesc, AccessShareLock);
5384 break;
5385 }
5386
5387 case NamespaceRelationId:
5388 {
5389 char *nspname;
5390
5391 nspname = get_namespace_name_or_temp(object->objectId);
5392 if (!nspname)
5393 {
5394 if (!missing_ok)
5395 elog(ERROR, "cache lookup failed for namespace %u",
5396 object->objectId);
5397 break;
5398 }
5399 appendStringInfoString(&buffer,
5400 quote_identifier(nspname));
5401 if (objname)
5402 *objname = list_make1(nspname);
5403 break;
5404 }
5405
5406 case StatisticExtRelationId:
5407 {
5408 HeapTuple tup;
5409 Form_pg_statistic_ext formStatistic;
5410 char *schema;
5411
5412 tup = SearchSysCache1(STATEXTOID,
5413 ObjectIdGetDatum(object->objectId));
5414 if (!HeapTupleIsValid(tup))
5415 {
5416 if (!missing_ok)
5417 elog(ERROR, "cache lookup failed for statistics object %u",
5418 object->objectId);
5419 break;
5420 }
5421 formStatistic = (Form_pg_statistic_ext) GETSTRUCT(tup);
5422 schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
5423 appendStringInfoString(&buffer,
5425 NameStr(formStatistic->stxname)));
5426 if (objname)
5427 *objname = list_make2(schema,
5428 pstrdup(NameStr(formStatistic->stxname)));
5429 ReleaseSysCache(tup);
5430 }
5431 break;
5432
5433 case TSParserRelationId:
5434 {
5435 HeapTuple tup;
5436 Form_pg_ts_parser formParser;
5437 char *schema;
5438
5439 tup = SearchSysCache1(TSPARSEROID,
5440 ObjectIdGetDatum(object->objectId));
5441 if (!HeapTupleIsValid(tup))
5442 {
5443 if (!missing_ok)
5444 elog(ERROR, "cache lookup failed for text search parser %u",
5445 object->objectId);
5446 break;
5447 }
5448 formParser = (Form_pg_ts_parser) GETSTRUCT(tup);
5449 schema = get_namespace_name_or_temp(formParser->prsnamespace);
5450 appendStringInfoString(&buffer,
5452 NameStr(formParser->prsname)));
5453 if (objname)
5454 *objname = list_make2(schema,
5455 pstrdup(NameStr(formParser->prsname)));
5456 ReleaseSysCache(tup);
5457 break;
5458 }
5459
5460 case TSDictionaryRelationId:
5461 {
5462 HeapTuple tup;
5463 Form_pg_ts_dict formDict;
5464 char *schema;
5465
5466 tup = SearchSysCache1(TSDICTOID,
5467 ObjectIdGetDatum(object->objectId));
5468 if (!HeapTupleIsValid(tup))
5469 {
5470 if (!missing_ok)
5471 elog(ERROR, "cache lookup failed for text search dictionary %u",
5472 object->objectId);
5473 break;
5474 }
5475 formDict = (Form_pg_ts_dict) GETSTRUCT(tup);
5476 schema = get_namespace_name_or_temp(formDict->dictnamespace);
5477 appendStringInfoString(&buffer,
5479 NameStr(formDict->dictname)));
5480 if (objname)
5481 *objname = list_make2(schema,
5482 pstrdup(NameStr(formDict->dictname)));
5483 ReleaseSysCache(tup);
5484 break;
5485 }
5486
5487 case TSTemplateRelationId:
5488 {
5489 HeapTuple tup;
5490 Form_pg_ts_template formTmpl;
5491 char *schema;
5492
5493 tup = SearchSysCache1(TSTEMPLATEOID,
5494 ObjectIdGetDatum(object->objectId));
5495 if (!HeapTupleIsValid(tup))
5496 {
5497 if (!missing_ok)
5498 elog(ERROR, "cache lookup failed for text search template %u",
5499 object->objectId);
5500 break;
5501 }
5502 formTmpl = (Form_pg_ts_template) GETSTRUCT(tup);
5503 schema = get_namespace_name_or_temp(formTmpl->tmplnamespace);
5504 appendStringInfoString(&buffer,
5506 NameStr(formTmpl->tmplname)));
5507 if (objname)
5508 *objname = list_make2(schema,
5509 pstrdup(NameStr(formTmpl->tmplname)));
5510 ReleaseSysCache(tup);
5511 break;
5512 }
5513
5514 case TSConfigRelationId:
5515 {
5516 HeapTuple tup;
5517 Form_pg_ts_config formCfg;
5518 char *schema;
5519
5520 tup = SearchSysCache1(TSCONFIGOID,
5521 ObjectIdGetDatum(object->objectId));
5522 if (!HeapTupleIsValid(tup))
5523 {
5524 if (!missing_ok)
5525 elog(ERROR, "cache lookup failed for text search configuration %u",
5526 object->objectId);
5527 break;
5528 }
5529 formCfg = (Form_pg_ts_config) GETSTRUCT(tup);
5530 schema = get_namespace_name_or_temp(formCfg->cfgnamespace);
5531 appendStringInfoString(&buffer,
5533 NameStr(formCfg->cfgname)));
5534 if (objname)
5535 *objname = list_make2(schema,
5536 pstrdup(NameStr(formCfg->cfgname)));
5537 ReleaseSysCache(tup);
5538 break;
5539 }
5540
5541 case AuthIdRelationId:
5542 {
5543 char *username;
5544
5545 username = GetUserNameFromId(object->objectId, missing_ok);
5546 if (!username)
5547 break;
5548 if (objname)
5549 *objname = list_make1(username);
5550 appendStringInfoString(&buffer,
5552 break;
5553 }
5554
5555 case AuthMemRelationId:
5556 {
5557 Relation authMemDesc;
5558 ScanKeyData skey[1];
5559 SysScanDesc amscan;
5560 HeapTuple tup;
5561 Form_pg_auth_members amForm;
5562
5563 authMemDesc = table_open(AuthMemRelationId,
5565
5566 ScanKeyInit(&skey[0],
5567 Anum_pg_auth_members_oid,
5568 BTEqualStrategyNumber, F_OIDEQ,
5569 ObjectIdGetDatum(object->objectId));
5570
5571 amscan = systable_beginscan(authMemDesc, AuthMemOidIndexId, true,
5572 NULL, 1, skey);
5573
5574 tup = systable_getnext(amscan);
5575
5576 if (!HeapTupleIsValid(tup))
5577 {
5578 if (!missing_ok)
5579 elog(ERROR, "could not find tuple for pg_auth_members entry %u",
5580 object->objectId);
5581
5582 systable_endscan(amscan);
5583 table_close(authMemDesc, AccessShareLock);
5584 break;
5585 }
5586
5587 amForm = (Form_pg_auth_members) GETSTRUCT(tup);
5588
5589 appendStringInfo(&buffer, _("membership of role %s in role %s"),
5590 GetUserNameFromId(amForm->member, false),
5591 GetUserNameFromId(amForm->roleid, false));
5592
5593 systable_endscan(amscan);
5594 table_close(authMemDesc, AccessShareLock);
5595 break;
5596 }
5597
5598 case DatabaseRelationId:
5599 {
5600 char *datname;
5601
5603 if (!datname)
5604 {
5605 if (!missing_ok)
5606 elog(ERROR, "cache lookup failed for database %u",
5607 object->objectId);
5608 break;
5609 }
5610 if (objname)
5611 *objname = list_make1(datname);
5612 appendStringInfoString(&buffer,
5614 break;
5615 }
5616
5617 case TableSpaceRelationId:
5618 {
5619 char *tblspace;
5620
5621 tblspace = get_tablespace_name(object->objectId);
5622 if (!tblspace)
5623 {
5624 if (!missing_ok)
5625 elog(ERROR, "cache lookup failed for tablespace %u",
5626 object->objectId);
5627 break;
5628 }
5629 if (objname)
5630 *objname = list_make1(tblspace);
5631 appendStringInfoString(&buffer,
5632 quote_identifier(tblspace));
5633 break;
5634 }
5635
5636 case ForeignDataWrapperRelationId:
5637 {
5638 ForeignDataWrapper *fdw;
5639
5641 missing_ok);
5642 if (fdw)
5643 {
5645 if (objname)
5646 *objname = list_make1(pstrdup(fdw->fdwname));
5647 }
5648 break;
5649 }
5650
5651 case ForeignServerRelationId:
5652 {
5653 ForeignServer *srv;
5654
5655 srv = GetForeignServerExtended(object->objectId,
5656 missing_ok);
5657 if (srv)
5658 {
5659 appendStringInfoString(&buffer,
5661 if (objname)
5662 *objname = list_make1(pstrdup(srv->servername));
5663 }
5664 break;
5665 }
5666
5667 case UserMappingRelationId:
5668 {
5669 HeapTuple tup;
5670 Oid useid;
5671 Form_pg_user_mapping umform;
5672 ForeignServer *srv;
5673 const char *usename;
5674
5675 tup = SearchSysCache1(USERMAPPINGOID,
5676 ObjectIdGetDatum(object->objectId));
5677 if (!HeapTupleIsValid(tup))
5678 {
5679 if (!missing_ok)
5680 elog(ERROR, "cache lookup failed for user mapping %u",
5681 object->objectId);
5682 break;
5683 }
5684 umform = (Form_pg_user_mapping) GETSTRUCT(tup);
5685 useid = umform->umuser;
5686 srv = GetForeignServer(umform->umserver);
5687
5688 ReleaseSysCache(tup);
5689
5690 if (OidIsValid(useid))
5691 usename = GetUserNameFromId(useid, false);
5692 else
5693 usename = "public";
5694
5695 if (objname)
5696 {
5697 *objname = list_make1(pstrdup(usename));
5698 *objargs = list_make1(pstrdup(srv->servername));
5699 }
5700
5701 appendStringInfo(&buffer, "%s on server %s",
5702 quote_identifier(usename),
5703 srv->servername);
5704 break;
5705 }
5706
5707 case DefaultAclRelationId:
5708 {
5709 Relation defaclrel;
5710 ScanKeyData skey[1];
5711 SysScanDesc rcscan;
5712 HeapTuple tup;
5713 Form_pg_default_acl defacl;
5714 char *schema;
5715 char *username;
5716
5717 defaclrel = table_open(DefaultAclRelationId, AccessShareLock);
5718
5719 ScanKeyInit(&skey[0],
5720 Anum_pg_default_acl_oid,
5721 BTEqualStrategyNumber, F_OIDEQ,
5722 ObjectIdGetDatum(object->objectId));
5723
5724 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
5725 true, NULL, 1, skey);
5726
5727 tup = systable_getnext(rcscan);
5728
5729 if (!HeapTupleIsValid(tup))
5730 {
5731 if (!missing_ok)
5732 elog(ERROR, "could not find tuple for default ACL %u",
5733 object->objectId);
5734
5735 systable_endscan(rcscan);
5736 table_close(defaclrel, AccessShareLock);
5737 break;
5738 }
5739
5740 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
5741
5742 username = GetUserNameFromId(defacl->defaclrole, false);
5743 appendStringInfo(&buffer,
5744 "for role %s",
5746
5747 if (OidIsValid(defacl->defaclnamespace))
5748 {
5749 schema = get_namespace_name_or_temp(defacl->defaclnamespace);
5750 appendStringInfo(&buffer,
5751 " in schema %s",
5752 quote_identifier(schema));
5753 }
5754 else
5755 schema = NULL;
5756
5757 switch (defacl->defaclobjtype)
5758 {
5759 case DEFACLOBJ_RELATION:
5760 appendStringInfoString(&buffer,
5761 " on tables");
5762 break;
5763 case DEFACLOBJ_SEQUENCE:
5764 appendStringInfoString(&buffer,
5765 " on sequences");
5766 break;
5767 case DEFACLOBJ_FUNCTION:
5768 appendStringInfoString(&buffer,
5769 " on functions");
5770 break;
5771 case DEFACLOBJ_TYPE:
5772 appendStringInfoString(&buffer,
5773 " on types");
5774 break;
5775 case DEFACLOBJ_NAMESPACE:
5776 appendStringInfoString(&buffer,
5777 " on schemas");
5778 break;
5779 case DEFACLOBJ_LARGEOBJECT:
5780 appendStringInfoString(&buffer,
5781 " on large objects");
5782 break;
5783 }
5784
5785 if (objname)
5786 {
5787 *objname = list_make1(username);
5788 if (schema)
5789 *objname = lappend(*objname, schema);
5790 *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
5791 }
5792
5793 systable_endscan(rcscan);
5794 table_close(defaclrel, AccessShareLock);
5795 break;
5796 }
5797
5798 case ExtensionRelationId:
5799 {
5800 char *extname;
5801
5802 extname = get_extension_name(object->objectId);
5803 if (!extname)
5804 {
5805 if (!missing_ok)
5806 elog(ERROR, "cache lookup failed for extension %u",
5807 object->objectId);
5808 break;
5809 }
5810 appendStringInfoString(&buffer, quote_identifier(extname));
5811 if (objname)
5812 *objname = list_make1(extname);
5813 break;
5814 }
5815
5816 case EventTriggerRelationId:
5817 {
5818 HeapTuple tup;
5819 Form_pg_event_trigger trigForm;
5820 char *evtname;
5821
5822 tup = SearchSysCache1(EVENTTRIGGEROID,
5823 ObjectIdGetDatum(object->objectId));
5824 if (!HeapTupleIsValid(tup))
5825 {
5826 if (!missing_ok)
5827 elog(ERROR, "cache lookup failed for event trigger %u",
5828 object->objectId);
5829 break;
5830 }
5831 trigForm = (Form_pg_event_trigger) GETSTRUCT(tup);
5832 evtname = pstrdup(NameStr(trigForm->evtname));
5833 appendStringInfoString(&buffer, quote_identifier(evtname));
5834 if (objname)
5835 *objname = list_make1(evtname);
5836 ReleaseSysCache(tup);
5837 break;
5838 }
5839
5840 case ParameterAclRelationId:
5841 {
5842 HeapTuple tup;
5843 Datum nameDatum;
5844 char *parname;
5845
5846 tup = SearchSysCache1(PARAMETERACLOID,
5847 ObjectIdGetDatum(object->objectId));
5848 if (!HeapTupleIsValid(tup))
5849 {
5850 if (!missing_ok)
5851 elog(ERROR, "cache lookup failed for parameter ACL %u",
5852 object->objectId);
5853 break;
5854 }
5855 nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tup,
5856 Anum_pg_parameter_acl_parname);
5857 parname = TextDatumGetCString(nameDatum);
5858 appendStringInfoString(&buffer, parname);
5859 if (objname)
5860 *objname = list_make1(parname);
5861 ReleaseSysCache(tup);
5862 break;
5863 }
5864
5865 case PolicyRelationId:
5866 {
5867 Relation polDesc;
5868 HeapTuple tup;
5869 Form_pg_policy policy;
5870
5871 polDesc = table_open(PolicyRelationId, AccessShareLock);
5872
5873 tup = get_catalog_object_by_oid(polDesc, Anum_pg_policy_oid,
5874 object->objectId);
5875
5876 if (!HeapTupleIsValid(tup))
5877 {
5878 if (!missing_ok)
5879 elog(ERROR, "could not find tuple for policy %u",
5880 object->objectId);
5881
5882 table_close(polDesc, AccessShareLock);
5883 break;
5884 }
5885
5886 policy = (Form_pg_policy) GETSTRUCT(tup);
5887
5888 appendStringInfo(&buffer, "%s on ",
5889 quote_identifier(NameStr(policy->polname)));
5890 getRelationIdentity(&buffer, policy->polrelid, objname, false);
5891 if (objname)
5892 *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
5893
5894 table_close(polDesc, AccessShareLock);
5895 break;
5896 }
5897
5898 case PublicationRelationId:
5899 {
5900 char *pubname;
5901
5902 pubname = get_publication_name(object->objectId, missing_ok);
5903 if (pubname)
5904 {
5905 appendStringInfoString(&buffer,
5906 quote_identifier(pubname));
5907 if (objname)
5908 *objname = list_make1(pubname);
5909 }
5910 break;
5911 }
5912
5913 case PublicationNamespaceRelationId:
5914 {
5915 char *pubname;
5916 char *nspname;
5917
5918 if (!getPublicationSchemaInfo(object, missing_ok, &pubname,
5919 &nspname))
5920 break;
5921 appendStringInfo(&buffer, "%s in publication %s",
5922 nspname, pubname);
5923
5924 if (objargs)
5925 *objargs = list_make1(pubname);
5926 else
5927 pfree(pubname);
5928
5929 if (objname)
5930 *objname = list_make1(nspname);
5931 else
5932 pfree(nspname);
5933
5934 break;
5935 }
5936
5937 case PublicationRelRelationId:
5938 {
5939 HeapTuple tup;
5940 char *pubname;
5942
5943 tup = SearchSysCache1(PUBLICATIONREL,
5944 ObjectIdGetDatum(object->objectId));
5945 if (!HeapTupleIsValid(tup))
5946 {
5947 if (!missing_ok)
5948 elog(ERROR, "cache lookup failed for publication table %u",
5949 object->objectId);
5950 break;
5951 }
5952
5953 prform = (Form_pg_publication_rel) GETSTRUCT(tup);
5954 pubname = get_publication_name(prform->prpubid, false);
5955
5956 getRelationIdentity(&buffer, prform->prrelid, objname, false);
5957 appendStringInfo(&buffer, " in publication %s", pubname);
5958
5959 if (objargs)
5960 *objargs = list_make1(pubname);
5961
5962 ReleaseSysCache(tup);
5963 break;
5964 }
5965
5966 case SubscriptionRelationId:
5967 {
5968 char *subname;
5969
5970 subname = get_subscription_name(object->objectId, missing_ok);
5971 if (subname)
5972 {
5973 appendStringInfoString(&buffer,
5975 if (objname)
5976 *objname = list_make1(subname);
5977 }
5978 break;
5979 }
5980
5981 case TransformRelationId:
5982 {
5983 Relation transformDesc;
5984 HeapTuple tup;
5985 Form_pg_transform transform;
5986 char *transformLang;
5987 char *transformType;
5988
5989 transformDesc = table_open(TransformRelationId, AccessShareLock);
5990
5991 tup = get_catalog_object_by_oid(transformDesc,
5992 Anum_pg_transform_oid,
5993 object->objectId);
5994
5995 if (!HeapTupleIsValid(tup))
5996 {
5997 if (!missing_ok)
5998 elog(ERROR, "could not find tuple for transform %u",
5999 object->objectId);
6000
6001 table_close(transformDesc, AccessShareLock);
6002 break;
6003 }
6004
6005 transform = (Form_pg_transform) GETSTRUCT(tup);
6006
6007 transformType = format_type_be_qualified(transform->trftype);
6008 transformLang = get_language_name(transform->trflang, false);
6009
6010 appendStringInfo(&buffer, "for %s language %s",
6011 transformType,
6012 transformLang);
6013 if (objname)
6014 {
6015 *objname = list_make1(transformType);
6016 *objargs = list_make1(pstrdup(transformLang));
6017 }
6018
6019 table_close(transformDesc, AccessShareLock);
6020 }
6021 break;
6022
6023 default:
6024 elog(ERROR, "unsupported object class: %u", object->classId);
6025 }
6026
6027 if (!missing_ok)
6028 {
6029 /*
6030 * If a get_object_address() representation was requested, make sure
6031 * we are providing one. We don't check objargs, because many of the
6032 * cases above leave it as NIL.
6033 */
6034 if (objname && *objname == NIL)
6035 elog(ERROR, "requested object address for unsupported object class %u: text result \"%s\"",
6036 object->classId, buffer.data);
6037 }
6038 else
6039 {
6040 /* an empty buffer is equivalent to no object found */
6041 if (buffer.len == 0)
6042 {
6043 Assert((objname == NULL || *objname == NIL) &&
6044 (objargs == NULL || *objargs == NIL));
6045 return NULL;
6046 }
6047 }
6048
6049 return buffer.data;
6050}
6051
6052static void
6053getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object,
6054 bool missing_ok)
6055{
6056 HeapTuple opfTup;
6057 Form_pg_opfamily opfForm;
6058 HeapTuple amTup;
6059 Form_pg_am amForm;
6060 char *schema;
6061
6062 opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
6063 if (!HeapTupleIsValid(opfTup))
6064 {
6065 if (!missing_ok)
6066 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
6067 return;
6068 }
6069 opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
6070
6071 amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
6072 if (!HeapTupleIsValid(amTup))
6073 elog(ERROR, "cache lookup failed for access method %u",
6074 opfForm->opfmethod);
6075 amForm = (Form_pg_am) GETSTRUCT(amTup);
6076
6077 schema = get_namespace_name_or_temp(opfForm->opfnamespace);
6078 appendStringInfo(buffer, "%s USING %s",
6080 NameStr(opfForm->opfname)),
6081 NameStr(amForm->amname));
6082
6083 if (object)
6084 *object = list_make3(pstrdup(NameStr(amForm->amname)),
6085 pstrdup(schema),
6086 pstrdup(NameStr(opfForm->opfname)));
6087
6088 ReleaseSysCache(amTup);
6089 ReleaseSysCache(opfTup);
6090}
6091
6092/*
6093 * Append the relation identity (quoted qualified name) to the given
6094 * StringInfo.
6095 */
6096static void
6097getRelationIdentity(StringInfo buffer, Oid relid, List **object,
6098 bool missing_ok)
6099{
6100 HeapTuple relTup;
6101 Form_pg_class relForm;
6102 char *schema;
6103
6104 relTup = SearchSysCache1(RELOID,
6105 ObjectIdGetDatum(relid));
6106 if (!HeapTupleIsValid(relTup))
6107 {
6108 if (!missing_ok)
6109 elog(ERROR, "cache lookup failed for relation %u", relid);
6110
6111 if (object)
6112 *object = NIL;
6113 return;
6114 }
6115 relForm = (Form_pg_class) GETSTRUCT(relTup);
6116
6117 schema = get_namespace_name_or_temp(relForm->relnamespace);
6120 NameStr(relForm->relname)));
6121 if (object)
6122 *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
6123
6124 ReleaseSysCache(relTup);
6125}
6126
6127/*
6128 * Auxiliary function to build a TEXT array out of a list of C-strings.
6129 */
6130ArrayType *
6132{
6133 ArrayType *arr;
6134 Datum *datums;
6135 bool *nulls;
6136 int j = 0;
6137 ListCell *cell;
6138 MemoryContext memcxt;
6139 MemoryContext oldcxt;
6140 int lb[1];
6141
6142 /* Work in a temp context; easier than individually pfree'ing the Datums */
6144 "strlist to array",
6146 oldcxt = MemoryContextSwitchTo(memcxt);
6147
6148 datums = (Datum *) palloc(sizeof(Datum) * list_length(list));
6149 nulls = palloc(sizeof(bool) * list_length(list));
6150
6151 foreach(cell, list)
6152 {
6153 char *name = lfirst(cell);
6154
6155 if (name)
6156 {
6157 nulls[j] = false;
6158 datums[j++] = CStringGetTextDatum(name);
6159 }
6160 else
6161 nulls[j] = true;
6162 }
6163
6164 MemoryContextSwitchTo(oldcxt);
6165
6166 lb[0] = 1;
6167 arr = construct_md_array(datums, nulls, 1, &j,
6168 lb, TEXTOID, -1, false, TYPALIGN_INT);
6169
6170 MemoryContextDelete(memcxt);
6171
6172 return arr;
6173}
6174
6175/*
6176 * get_relkind_objtype
6177 *
6178 * Return the object type for the relkind given by the caller.
6179 *
6180 * If an unexpected relkind is passed, we say OBJECT_TABLE rather than
6181 * failing. That's because this is mostly used for generating error messages
6182 * for failed ACL checks on relations, and we'd rather produce a generic
6183 * message saying "table" than fail entirely.
6184 */
6187{
6188 switch (relkind)
6189 {
6190 case RELKIND_RELATION:
6191 case RELKIND_PARTITIONED_TABLE:
6192 return OBJECT_TABLE;
6193 case RELKIND_INDEX:
6194 case RELKIND_PARTITIONED_INDEX:
6195 return OBJECT_INDEX;
6196 case RELKIND_SEQUENCE:
6197 return OBJECT_SEQUENCE;
6198 case RELKIND_VIEW:
6199 return OBJECT_VIEW;
6200 case RELKIND_MATVIEW:
6201 return OBJECT_MATVIEW;
6202 case RELKIND_FOREIGN_TABLE:
6203 return OBJECT_FOREIGN_TABLE;
6204 case RELKIND_TOASTVALUE:
6205 return OBJECT_TABLE;
6206 default:
6207 /* Per above, don't raise an error */
6208 return OBJECT_TABLE;
6209 }
6210}
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:5398
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5536
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2639
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4075
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2958
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4154
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)
Definition: arrayfuncs.c:3580
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3494
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1472
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1426
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define FORMAT_TYPE_ALLOW_INVALID
Definition: builtins.h:125
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define FORMAT_TYPE_INVALID_AS_NULL
Definition: builtins.h:127
#define FORMAT_TYPE_FORCE_QUALIFY
Definition: builtins.h:126
#define NameStr(name)
Definition: c.h:717
uint16 bits16
Definition: c.h:510
#define PointerIsValid(pointer)
Definition: c.h:734
int32_t int32
Definition: c.h:498
uint64_t uint64
Definition: c.h:503
#define lengthof(array)
Definition: c.h:759
#define OidIsValid(objectId)
Definition: c.h:746
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:304
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:3141
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3188
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define _(x)
Definition: elog.c:91
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
Oid get_event_trigger_oid(const char *trigname, bool missing_ok)
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:164
char * get_extension_name(Oid ext_oid)
Definition: extension.c:186
#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:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:182
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:704
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:111
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
Definition: foreign.c:49
ForeignServer * GetForeignServerExtended(Oid serverid, bits16 flags)
Definition: foreign.c:123
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:681
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
Definition: format_type.c:112
char * format_type_be_qualified(Oid type_oid)
Definition: format_type.c:353
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:904
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
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:1082
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1002
void LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
Definition: lmgr.c:562
void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1142
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1062
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define InplaceUpdateTupleLock
Definition: lockdefs.h:48
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition: lsyscache.c:1099
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:950
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2143
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition: lsyscache.c:3765
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1253
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3530
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:919
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition: lsyscache.c:3815
char * get_subscription_name(Oid subid, bool missing_ok)
Definition: lsyscache.c:3835
char * get_publication_name(Oid pubid, bool missing_ok)
Definition: lsyscache.c:3785
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3506
char * pstrdup(const char *in)
Definition: mcxt.c:2325
void pfree(void *pointer)
Definition: mcxt.c:2150
void * palloc(Size size)
Definition: mcxt.c:1943
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:1039
char * NameListToString(const List *names)
Definition: namespace.c:3594
bool TSTemplateIsVisible(Oid tmplId)
Definition: namespace.c:3065
bool OpfamilyIsVisible(Oid opfid)
Definition: namespace.c:2256
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2407
bool ConversionIsVisible(Oid conid)
Definition: namespace.c:2509
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition: namespace.c:2575
Oid get_collation_oid(List *collname, bool missing_ok)
Definition: namespace.c:3971
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3535
bool RelationIsVisible(Oid relid)
Definition: namespace.c:913
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:2154
bool TSParserIsVisible(Oid prsId)
Definition: namespace.c:2774
Oid get_conversion_oid(List *conname, bool missing_ok)
Definition: namespace.c:4025
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2861
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2716
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:3152
bool TSConfigIsVisible(Oid cfgid)
Definition: namespace.c:3210
bool StatisticsObjIsVisible(Oid stxid)
Definition: namespace.c:2632
bool TSDictionaryIsVisible(Oid dictId)
Definition: namespace.c:2919
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition: namespace.c:3007
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
static void getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok)
int get_object_catcache_name(Oid class_id)
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)
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)
int get_object_catcache_oid(Oid class_id)
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)
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)
Definition: objectaddress.h:40
Oid oidparse(Node *node)
Definition: oid.c:235
Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
Definition: opclasscmds.c:220
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:139
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2206
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:133
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
Definition: parsenodes.h:2316
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2331
@ OBJECT_FDW
Definition: parsenodes.h:2333
@ OBJECT_TSPARSER
Definition: parsenodes.h:2364
@ OBJECT_COLLATION
Definition: parsenodes.h:2324
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2367
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2317
@ OBJECT_OPCLASS
Definition: parsenodes.h:2341
@ OBJECT_DEFACL
Definition: parsenodes.h:2328
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2318
@ OBJECT_MATVIEW
Definition: parsenodes.h:2340
@ OBJECT_SCHEMA
Definition: parsenodes.h:2353
@ OBJECT_POLICY
Definition: parsenodes.h:2345
@ OBJECT_OPERATOR
Definition: parsenodes.h:2342
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2335
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2362
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2343
@ OBJECT_DOMAIN
Definition: parsenodes.h:2329
@ OBJECT_COLUMN
Definition: parsenodes.h:2323
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2359
@ OBJECT_ROLE
Definition: parsenodes.h:2350
@ OBJECT_ROUTINE
Definition: parsenodes.h:2351
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2339
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2348
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2346
@ OBJECT_EXTENSION
Definition: parsenodes.h:2332
@ OBJECT_INDEX
Definition: parsenodes.h:2337
@ OBJECT_DEFAULT
Definition: parsenodes.h:2327
@ OBJECT_DATABASE
Definition: parsenodes.h:2326
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2354
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2365
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2338
@ OBJECT_AMOP
Definition: parsenodes.h:2319
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2349
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2334
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2363
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2321
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2347
@ OBJECT_RULE
Definition: parsenodes.h:2352
@ OBJECT_CONVERSION
Definition: parsenodes.h:2325
@ OBJECT_AMPROC
Definition: parsenodes.h:2320
@ OBJECT_TABLE
Definition: parsenodes.h:2358
@ OBJECT_VIEW
Definition: parsenodes.h:2368
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2344
@ OBJECT_TYPE
Definition: parsenodes.h:2366
@ OBJECT_FUNCTION
Definition: parsenodes.h:2336
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2357
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2330
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2355
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2356
@ OBJECT_CAST
Definition: parsenodes.h:2322
@ OBJECT_TRIGGER
Definition: parsenodes.h:2361
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2360
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
Oid GetAttrDefaultOid(Oid relid, AttrNumber attnum)
Definition: pg_attrdef.c:278
ObjectAddress GetAttrDefaultColumnAddress(Oid attrdefoid)
Definition: pg_attrdef.c:320
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_auth_members * Form_pg_auth_members
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
FormData_pg_cast * Form_pg_cast
Definition: pg_cast.h:57
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:156
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
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)
FormData_pg_constraint * Form_pg_constraint
FormData_pg_conversion * Form_pg_conversion
Definition: pg_conversion.h:61
NameData datname
Definition: pg_database.h:35
FormData_pg_default_acl * Form_pg_default_acl
FormData_pg_event_trigger * Form_pg_event_trigger
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
bool LargeObjectExists(Oid loid)
#define lfirst(lc)
Definition: pg_list.h:172
#define llast(l)
Definition: pg_list.h:198
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define lsecond_node(type, l)
Definition: pg_list.h:186
#define lthird(l)
Definition: pg_list.h:188
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216
#define lsecond(l)
Definition: pg_list.h:183
#define list_make2(x1, x2)
Definition: pg_list.h:214
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
Oid ParameterAclLookup(const char *parameter, bool missing_ok)
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
NameData proname
Definition: pg_proc.h:35
Publication * GetPublicationByName(const char *pubname, bool missing_ok)
FormData_pg_publication_namespace * Form_pg_publication_namespace
FormData_pg_publication_rel * Form_pg_publication_rel
FormData_pg_rewrite * Form_pg_rewrite
Definition: pg_rewrite.h:52
FormData_pg_statistic_ext * Form_pg_statistic_ext
NameData subname
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:80
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55
FormData_pg_ts_template * Form_pg_ts_template
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
FormData_pg_user_mapping * Form_pg_user_mapping
Oid get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
Definition: policy.c:1204
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
static Name DatumGetName(Datum X)
Definition: postgres.h:365
uintptr_t Datum
Definition: postgres.h:69
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:247
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:177
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
static Datum CharGetDatum(char X)
Definition: postgres.h:127
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:226
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
char * format_procedure_extended(Oid procedure_oid, bits16 flags)
Definition: regproc.c:326
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:299
char * format_operator_extended(Oid operator_oid, bits16 flags)
Definition: regproc.c:722
void format_operator_parts(Oid operator_oid, List **objnames, List **objargs, bool missing_ok)
Definition: regproc.c:806
void format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs, bool missing_ok)
Definition: regproc.c:398
char * format_operator(Oid operator_oid)
Definition: regproc.c:793
#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)
Definition: ruleutils.c:13103
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:13019
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
uint64 SharedInvalidMessageCounter
Definition: sinval.c:24
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition: relation.c:172
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:137
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
char * fdwname
Definition: foreign.h:28
char * servername
Definition: foreign.h:39
Oid serverid
Definition: foreign.h:36
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
Definition: nodes.h:135
const char * class_descr
Definition: objectaddress.c:99
AttrNumber attnum_owner
AttrNumber attnum_namespace
AttrNumber attnum_acl
AttrNumber attnum_name
AttrNumber attnum_oid
char * relname
Definition: primnodes.h:83
char * catalogname
Definition: primnodes.h:77
char * schemaname
Definition: primnodes.h:80
Form_pg_class rd_rel
Definition: rel.h:111
Definition: value.h:64
TupleConstr * constr
Definition: tupdesc.h:141
Definition: type.h:96
ObjectType tm_type
const char * tm_name
Definition: localtime.c:73
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
Definition: syscache.c:566
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCacheLockedCopy1(int cacheId, Datum key1)
Definition: syscache.c:404
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:243
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:254
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
#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:1370
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:192
const char * description
const char * type
const char * name