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