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