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