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