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