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