Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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