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