]> granicus.if.org Git - postgresql/blob - src/backend/catalog/objectaddress.c
Run pgindent on 9.2 source tree in preparation for first 9.3
[postgresql] / src / backend / catalog / objectaddress.c
1 /*-------------------------------------------------------------------------
2  *
3  * objectaddress.c
4  *        functions for working with ObjectAddresses
5  *
6  * Portions Copyright (c) 1996-2012, 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/sysattr.h"
19 #include "catalog/catalog.h"
20 #include "catalog/indexing.h"
21 #include "catalog/objectaddress.h"
22 #include "catalog/pg_authid.h"
23 #include "catalog/pg_cast.h"
24 #include "catalog/pg_collation.h"
25 #include "catalog/pg_constraint.h"
26 #include "catalog/pg_conversion.h"
27 #include "catalog/pg_database.h"
28 #include "catalog/pg_extension.h"
29 #include "catalog/pg_foreign_data_wrapper.h"
30 #include "catalog/pg_foreign_server.h"
31 #include "catalog/pg_language.h"
32 #include "catalog/pg_largeobject.h"
33 #include "catalog/pg_largeobject_metadata.h"
34 #include "catalog/pg_namespace.h"
35 #include "catalog/pg_opclass.h"
36 #include "catalog/pg_opfamily.h"
37 #include "catalog/pg_operator.h"
38 #include "catalog/pg_proc.h"
39 #include "catalog/pg_rewrite.h"
40 #include "catalog/pg_tablespace.h"
41 #include "catalog/pg_trigger.h"
42 #include "catalog/pg_ts_config.h"
43 #include "catalog/pg_ts_dict.h"
44 #include "catalog/pg_ts_parser.h"
45 #include "catalog/pg_ts_template.h"
46 #include "catalog/pg_type.h"
47 #include "commands/dbcommands.h"
48 #include "commands/defrem.h"
49 #include "commands/extension.h"
50 #include "commands/proclang.h"
51 #include "commands/tablespace.h"
52 #include "commands/trigger.h"
53 #include "foreign/foreign.h"
54 #include "libpq/be-fsstubs.h"
55 #include "miscadmin.h"
56 #include "nodes/makefuncs.h"
57 #include "parser/parse_func.h"
58 #include "parser/parse_oper.h"
59 #include "parser/parse_type.h"
60 #include "rewrite/rewriteSupport.h"
61 #include "storage/lmgr.h"
62 #include "storage/sinval.h"
63 #include "utils/acl.h"
64 #include "utils/builtins.h"
65 #include "utils/fmgroids.h"
66 #include "utils/lsyscache.h"
67 #include "utils/syscache.h"
68 #include "utils/tqual.h"
69
70 /*
71  * ObjectProperty
72  *
73  * This array provides a common part of system object structure; to help
74  * consolidate routines to handle various kind of object classes.
75  */
76 typedef struct
77 {
78         Oid                     class_oid;              /* oid of catalog */
79         Oid                     oid_index_oid;  /* oid of index on system oid column */
80         int                     oid_catcache_id;        /* id of catcache on system oid column  */
81         AttrNumber      attnum_namespace;               /* attnum of namespace field */
82 } ObjectPropertyType;
83
84 static ObjectPropertyType ObjectProperty[] =
85 {
86         {
87                 CastRelationId,
88                 CastOidIndexId,
89                 -1,
90                 InvalidAttrNumber
91         },
92         {
93                 CollationRelationId,
94                 CollationOidIndexId,
95                 COLLOID,
96                 Anum_pg_collation_collnamespace
97         },
98         {
99                 ConstraintRelationId,
100                 ConstraintOidIndexId,
101                 CONSTROID,
102                 Anum_pg_constraint_connamespace
103         },
104         {
105                 ConversionRelationId,
106                 ConversionOidIndexId,
107                 CONVOID,
108                 Anum_pg_conversion_connamespace
109         },
110         {
111                 DatabaseRelationId,
112                 DatabaseOidIndexId,
113                 DATABASEOID,
114                 InvalidAttrNumber
115         },
116         {
117                 ExtensionRelationId,
118                 ExtensionOidIndexId,
119                 -1,
120                 InvalidAttrNumber               /* extension doesn't belong to extnamespace */
121         },
122         {
123                 ForeignDataWrapperRelationId,
124                 ForeignDataWrapperOidIndexId,
125                 FOREIGNDATAWRAPPEROID,
126                 InvalidAttrNumber
127         },
128         {
129                 ForeignServerRelationId,
130                 ForeignServerOidIndexId,
131                 FOREIGNSERVEROID,
132                 InvalidAttrNumber
133         },
134         {
135                 ProcedureRelationId,
136                 ProcedureOidIndexId,
137                 PROCOID,
138                 Anum_pg_proc_pronamespace
139         },
140         {
141                 LanguageRelationId,
142                 LanguageOidIndexId,
143                 LANGOID,
144                 InvalidAttrNumber,
145         },
146         {
147                 LargeObjectMetadataRelationId,
148                 LargeObjectMetadataOidIndexId,
149                 -1,
150                 InvalidAttrNumber
151         },
152         {
153                 OperatorClassRelationId,
154                 OpclassOidIndexId,
155                 CLAOID,
156                 Anum_pg_opclass_opcnamespace,
157         },
158         {
159                 OperatorRelationId,
160                 OperatorOidIndexId,
161                 OPEROID,
162                 Anum_pg_operator_oprnamespace
163         },
164         {
165                 OperatorFamilyRelationId,
166                 OpfamilyOidIndexId,
167                 OPFAMILYOID,
168                 Anum_pg_opfamily_opfnamespace
169         },
170         {
171                 AuthIdRelationId,
172                 AuthIdOidIndexId,
173                 AUTHOID,
174                 InvalidAttrNumber
175         },
176         {
177                 RewriteRelationId,
178                 RewriteOidIndexId,
179                 -1,
180                 InvalidAttrNumber
181         },
182         {
183                 NamespaceRelationId,
184                 NamespaceOidIndexId,
185                 NAMESPACEOID,
186                 InvalidAttrNumber
187         },
188         {
189                 RelationRelationId,
190                 ClassOidIndexId,
191                 RELOID,
192                 Anum_pg_class_relnamespace
193         },
194         {
195                 TableSpaceRelationId,
196                 TablespaceOidIndexId,
197                 TABLESPACEOID,
198                 InvalidAttrNumber
199         },
200         {
201                 TriggerRelationId,
202                 TriggerOidIndexId,
203                 -1,
204                 InvalidAttrNumber
205         },
206         {
207                 TSConfigRelationId,
208                 TSConfigOidIndexId,
209                 TSCONFIGOID,
210                 Anum_pg_ts_config_cfgnamespace
211         },
212         {
213                 TSDictionaryRelationId,
214                 TSDictionaryOidIndexId,
215                 TSDICTOID,
216                 Anum_pg_ts_dict_dictnamespace
217         },
218         {
219                 TSParserRelationId,
220                 TSParserOidIndexId,
221                 TSPARSEROID,
222                 Anum_pg_ts_parser_prsnamespace
223         },
224         {
225                 TSTemplateRelationId,
226                 TSTemplateOidIndexId,
227                 TSTEMPLATEOID,
228                 Anum_pg_ts_template_tmplnamespace,
229         },
230         {
231                 TypeRelationId,
232                 TypeOidIndexId,
233                 TYPEOID,
234                 Anum_pg_type_typnamespace
235         }
236 };
237
238 static ObjectAddress get_object_address_unqualified(ObjectType objtype,
239                                                            List *qualname, bool missing_ok);
240 static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
241                                                            List *objname, Relation *relp,
242                                                            LOCKMODE lockmode, bool missing_ok);
243 static ObjectAddress get_object_address_relobject(ObjectType objtype,
244                                                          List *objname, Relation *relp, bool missing_ok);
245 static ObjectAddress get_object_address_attribute(ObjectType objtype,
246                                                          List *objname, Relation *relp,
247                                                          LOCKMODE lockmode, bool missing_ok);
248 static ObjectAddress get_object_address_type(ObjectType objtype,
249                                                 List *objname, bool missing_ok);
250 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
251                                                 List *objargs, bool missing_ok);
252 static ObjectPropertyType *get_object_property_data(Oid class_id);
253
254 /*
255  * Translate an object name and arguments (as passed by the parser) to an
256  * ObjectAddress.
257  *
258  * The returned object will be locked using the specified lockmode.  If a
259  * sub-object is looked up, the parent object will be locked instead.
260  *
261  * If the object is a relation or a child object of a relation (e.g. an
262  * attribute or contraint), the relation is also opened and *relp receives
263  * the open relcache entry pointer; otherwise, *relp is set to NULL.  This
264  * is a bit grotty but it makes life simpler, since the caller will
265  * typically need the relcache entry too.  Caller must close the relcache
266  * entry when done with it.  The relation is locked with the specified lockmode
267  * if the target object is the relation itself or an attribute, but for other
268  * child objects, only AccessShareLock is acquired on the relation.
269  *
270  * We don't currently provide a function to release the locks acquired here;
271  * typically, the lock must be held until commit to guard against a concurrent
272  * drop operation.
273  */
274 ObjectAddress
275 get_object_address(ObjectType objtype, List *objname, List *objargs,
276                                    Relation *relp, LOCKMODE lockmode, bool missing_ok)
277 {
278         ObjectAddress address;
279         ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
280         Relation        relation = NULL;
281         uint64          inval_count;
282
283         /* Some kind of lock must be taken. */
284         Assert(lockmode != NoLock);
285
286         for (;;)
287         {
288                 /*
289                  * Remember this value, so that, after looking up the object name and
290                  * locking it, we can check whether any invalidation messages have
291                  * been processed that might require a do-over.
292                  */
293                 inval_count = SharedInvalidMessageCounter;
294
295                 /* Look up object address. */
296                 switch (objtype)
297                 {
298                         case OBJECT_INDEX:
299                         case OBJECT_SEQUENCE:
300                         case OBJECT_TABLE:
301                         case OBJECT_VIEW:
302                         case OBJECT_FOREIGN_TABLE:
303                                 address =
304                                         get_relation_by_qualified_name(objtype, objname,
305                                                                                                    &relation, lockmode,
306                                                                                                    missing_ok);
307                                 break;
308                         case OBJECT_COLUMN:
309                                 address =
310                                         get_object_address_attribute(objtype, objname,
311                                                                                                  &relation, lockmode,
312                                                                                                  missing_ok);
313                                 break;
314                         case OBJECT_RULE:
315                         case OBJECT_TRIGGER:
316                         case OBJECT_CONSTRAINT:
317                                 address = get_object_address_relobject(objtype, objname,
318                                                                                                            &relation, missing_ok);
319                                 break;
320                         case OBJECT_DATABASE:
321                         case OBJECT_EXTENSION:
322                         case OBJECT_TABLESPACE:
323                         case OBJECT_ROLE:
324                         case OBJECT_SCHEMA:
325                         case OBJECT_LANGUAGE:
326                         case OBJECT_FDW:
327                         case OBJECT_FOREIGN_SERVER:
328                                 address = get_object_address_unqualified(objtype,
329                                                                                                                  objname, missing_ok);
330                                 break;
331                         case OBJECT_TYPE:
332                         case OBJECT_DOMAIN:
333                                 address = get_object_address_type(objtype, objname, missing_ok);
334                                 break;
335                         case OBJECT_AGGREGATE:
336                                 address.classId = ProcedureRelationId;
337                                 address.objectId =
338                                         LookupAggNameTypeNames(objname, objargs, missing_ok);
339                                 address.objectSubId = 0;
340                                 break;
341                         case OBJECT_FUNCTION:
342                                 address.classId = ProcedureRelationId;
343                                 address.objectId =
344                                         LookupFuncNameTypeNames(objname, objargs, missing_ok);
345                                 address.objectSubId = 0;
346                                 break;
347                         case OBJECT_OPERATOR:
348                                 Assert(list_length(objargs) == 2);
349                                 address.classId = OperatorRelationId;
350                                 address.objectId =
351                                         LookupOperNameTypeNames(NULL, objname,
352                                                                                         (TypeName *) linitial(objargs),
353                                                                                         (TypeName *) lsecond(objargs),
354                                                                                         missing_ok, -1);
355                                 address.objectSubId = 0;
356                                 break;
357                         case OBJECT_COLLATION:
358                                 address.classId = CollationRelationId;
359                                 address.objectId = get_collation_oid(objname, missing_ok);
360                                 address.objectSubId = 0;
361                                 break;
362                         case OBJECT_CONVERSION:
363                                 address.classId = ConversionRelationId;
364                                 address.objectId = get_conversion_oid(objname, missing_ok);
365                                 address.objectSubId = 0;
366                                 break;
367                         case OBJECT_OPCLASS:
368                         case OBJECT_OPFAMILY:
369                                 address = get_object_address_opcf(objtype,
370                                                                                            objname, objargs, missing_ok);
371                                 break;
372                         case OBJECT_LARGEOBJECT:
373                                 Assert(list_length(objname) == 1);
374                                 address.classId = LargeObjectRelationId;
375                                 address.objectId = oidparse(linitial(objname));
376                                 address.objectSubId = 0;
377                                 if (!LargeObjectExists(address.objectId))
378                                 {
379                                         if (!missing_ok)
380                                                 ereport(ERROR,
381                                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
382                                                                  errmsg("large object %u does not exist",
383                                                                                 address.objectId)));
384                                 }
385                                 break;
386                         case OBJECT_CAST:
387                                 {
388                                         TypeName   *sourcetype = (TypeName *) linitial(objname);
389                                         TypeName   *targettype = (TypeName *) linitial(objargs);
390                                         Oid                     sourcetypeid = typenameTypeId(NULL, sourcetype);
391                                         Oid                     targettypeid = typenameTypeId(NULL, targettype);
392
393                                         address.classId = CastRelationId;
394                                         address.objectId =
395                                                 get_cast_oid(sourcetypeid, targettypeid, missing_ok);
396                                         address.objectSubId = 0;
397                                 }
398                                 break;
399                         case OBJECT_TSPARSER:
400                                 address.classId = TSParserRelationId;
401                                 address.objectId = get_ts_parser_oid(objname, missing_ok);
402                                 address.objectSubId = 0;
403                                 break;
404                         case OBJECT_TSDICTIONARY:
405                                 address.classId = TSDictionaryRelationId;
406                                 address.objectId = get_ts_dict_oid(objname, missing_ok);
407                                 address.objectSubId = 0;
408                                 break;
409                         case OBJECT_TSTEMPLATE:
410                                 address.classId = TSTemplateRelationId;
411                                 address.objectId = get_ts_template_oid(objname, missing_ok);
412                                 address.objectSubId = 0;
413                                 break;
414                         case OBJECT_TSCONFIGURATION:
415                                 address.classId = TSConfigRelationId;
416                                 address.objectId = get_ts_config_oid(objname, missing_ok);
417                                 address.objectSubId = 0;
418                                 break;
419                         default:
420                                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
421                                 /* placate compiler, in case it thinks elog might return */
422                                 address.classId = InvalidOid;
423                                 address.objectId = InvalidOid;
424                                 address.objectSubId = 0;
425                 }
426
427                 /*
428                  * If we could not find the supplied object, return without locking.
429                  */
430                 if (!OidIsValid(address.objectId))
431                 {
432                         Assert(missing_ok);
433                         return address;
434                 }
435
436                 /*
437                  * If we're retrying, see if we got the same answer as last time.  If
438                  * so, we're done; if not, we locked the wrong thing, so give up our
439                  * lock.
440                  */
441                 if (OidIsValid(old_address.classId))
442                 {
443                         if (old_address.classId == address.classId
444                                 && old_address.objectId == address.objectId
445                                 && old_address.objectSubId == address.objectSubId)
446                                 break;
447                         if (old_address.classId != RelationRelationId)
448                         {
449                                 if (IsSharedRelation(old_address.classId))
450                                         UnlockSharedObject(old_address.classId,
451                                                                            old_address.objectId,
452                                                                            0, lockmode);
453                                 else
454                                         UnlockDatabaseObject(old_address.classId,
455                                                                                  old_address.objectId,
456                                                                                  0, lockmode);
457                         }
458                 }
459
460                 /*
461                  * If we're dealing with a relation or attribute, then the relation is
462                  * already locked.      Otherwise, we lock it now.
463                  */
464                 if (address.classId != RelationRelationId)
465                 {
466                         if (IsSharedRelation(address.classId))
467                                 LockSharedObject(address.classId, address.objectId, 0,
468                                                                  lockmode);
469                         else
470                                 LockDatabaseObject(address.classId, address.objectId, 0,
471                                                                    lockmode);
472                 }
473
474                 /*
475                  * At this point, we've resolved the name to an OID and locked the
476                  * corresponding database object.  However, it's possible that by the
477                  * time we acquire the lock on the object, concurrent DDL has modified
478                  * the database in such a way that the name we originally looked up no
479                  * longer resolves to that OID.
480                  *
481                  * We can be certain that this isn't an issue if (a) no shared
482                  * invalidation messages have been processed or (b) we've locked a
483                  * relation somewhere along the line.  All the relation name lookups
484                  * in this module ultimately use RangeVarGetRelid() to acquire a
485                  * relation lock, and that function protects against the same kinds of
486                  * races we're worried about here.  Even when operating on a
487                  * constraint, rule, or trigger, we still acquire AccessShareLock on
488                  * the relation, which is enough to freeze out any concurrent DDL.
489                  *
490                  * In all other cases, however, it's possible that the name we looked
491                  * up no longer refers to the object we locked, so we retry the lookup
492                  * and see whether we get the same answer.
493                  */
494                 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
495                         break;
496                 old_address = address;
497         }
498
499         /* Return the object address and the relation. */
500         *relp = relation;
501         return address;
502 }
503
504 /*
505  * Find an ObjectAddress for a type of object that is identified by an
506  * unqualified name.
507  */
508 static ObjectAddress
509 get_object_address_unqualified(ObjectType objtype,
510                                                            List *qualname, bool missing_ok)
511 {
512         const char *name;
513         ObjectAddress address;
514
515         /*
516          * The types of names handled by this function are not permitted to be
517          * schema-qualified or catalog-qualified.
518          */
519         if (list_length(qualname) != 1)
520         {
521                 const char *msg;
522
523                 switch (objtype)
524                 {
525                         case OBJECT_DATABASE:
526                                 msg = gettext_noop("database name cannot be qualified");
527                                 break;
528                         case OBJECT_EXTENSION:
529                                 msg = gettext_noop("extension name cannot be qualified");
530                                 break;
531                         case OBJECT_TABLESPACE:
532                                 msg = gettext_noop("tablespace name cannot be qualified");
533                                 break;
534                         case OBJECT_ROLE:
535                                 msg = gettext_noop("role name cannot be qualified");
536                                 break;
537                         case OBJECT_SCHEMA:
538                                 msg = gettext_noop("schema name cannot be qualified");
539                                 break;
540                         case OBJECT_LANGUAGE:
541                                 msg = gettext_noop("language name cannot be qualified");
542                                 break;
543                         case OBJECT_FDW:
544                                 msg = gettext_noop("foreign-data wrapper name cannot be qualified");
545                                 break;
546                         case OBJECT_FOREIGN_SERVER:
547                                 msg = gettext_noop("server name cannot be qualified");
548                                 break;
549                         default:
550                                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
551                                 msg = NULL;             /* placate compiler */
552                 }
553                 ereport(ERROR,
554                                 (errcode(ERRCODE_SYNTAX_ERROR),
555                                  errmsg("%s", _(msg))));
556         }
557
558         /* Format is valid, extract the actual name. */
559         name = strVal(linitial(qualname));
560
561         /* Translate name to OID. */
562         switch (objtype)
563         {
564                 case OBJECT_DATABASE:
565                         address.classId = DatabaseRelationId;
566                         address.objectId = get_database_oid(name, missing_ok);
567                         address.objectSubId = 0;
568                         break;
569                 case OBJECT_EXTENSION:
570                         address.classId = ExtensionRelationId;
571                         address.objectId = get_extension_oid(name, missing_ok);
572                         address.objectSubId = 0;
573                         break;
574                 case OBJECT_TABLESPACE:
575                         address.classId = TableSpaceRelationId;
576                         address.objectId = get_tablespace_oid(name, missing_ok);
577                         address.objectSubId = 0;
578                         break;
579                 case OBJECT_ROLE:
580                         address.classId = AuthIdRelationId;
581                         address.objectId = get_role_oid(name, missing_ok);
582                         address.objectSubId = 0;
583                         break;
584                 case OBJECT_SCHEMA:
585                         address.classId = NamespaceRelationId;
586                         address.objectId = get_namespace_oid(name, missing_ok);
587                         address.objectSubId = 0;
588                         break;
589                 case OBJECT_LANGUAGE:
590                         address.classId = LanguageRelationId;
591                         address.objectId = get_language_oid(name, missing_ok);
592                         address.objectSubId = 0;
593                         break;
594                 case OBJECT_FDW:
595                         address.classId = ForeignDataWrapperRelationId;
596                         address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
597                         address.objectSubId = 0;
598                         break;
599                 case OBJECT_FOREIGN_SERVER:
600                         address.classId = ForeignServerRelationId;
601                         address.objectId = get_foreign_server_oid(name, missing_ok);
602                         address.objectSubId = 0;
603                         break;
604                 default:
605                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
606                         /* placate compiler, which doesn't know elog won't return */
607                         address.classId = InvalidOid;
608                         address.objectId = InvalidOid;
609                         address.objectSubId = 0;
610         }
611
612         return address;
613 }
614
615 /*
616  * Locate a relation by qualified name.
617  */
618 static ObjectAddress
619 get_relation_by_qualified_name(ObjectType objtype, List *objname,
620                                                            Relation *relp, LOCKMODE lockmode,
621                                                            bool missing_ok)
622 {
623         Relation        relation;
624         ObjectAddress address;
625
626         address.classId = RelationRelationId;
627         address.objectId = InvalidOid;
628         address.objectSubId = 0;
629
630         relation = relation_openrv_extended(makeRangeVarFromNameList(objname),
631                                                                                 lockmode, missing_ok);
632         if (!relation)
633                 return address;
634
635         switch (objtype)
636         {
637                 case OBJECT_INDEX:
638                         if (relation->rd_rel->relkind != RELKIND_INDEX)
639                                 ereport(ERROR,
640                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
641                                                  errmsg("\"%s\" is not an index",
642                                                                 RelationGetRelationName(relation))));
643                         break;
644                 case OBJECT_SEQUENCE:
645                         if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
646                                 ereport(ERROR,
647                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
648                                                  errmsg("\"%s\" is not a sequence",
649                                                                 RelationGetRelationName(relation))));
650                         break;
651                 case OBJECT_TABLE:
652                         if (relation->rd_rel->relkind != RELKIND_RELATION)
653                                 ereport(ERROR,
654                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
655                                                  errmsg("\"%s\" is not a table",
656                                                                 RelationGetRelationName(relation))));
657                         break;
658                 case OBJECT_VIEW:
659                         if (relation->rd_rel->relkind != RELKIND_VIEW)
660                                 ereport(ERROR,
661                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
662                                                  errmsg("\"%s\" is not a view",
663                                                                 RelationGetRelationName(relation))));
664                         break;
665                 case OBJECT_FOREIGN_TABLE:
666                         if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
667                                 ereport(ERROR,
668                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
669                                                  errmsg("\"%s\" is not a foreign table",
670                                                                 RelationGetRelationName(relation))));
671                         break;
672                 default:
673                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
674                         break;
675         }
676
677         /* Done. */
678         address.objectId = RelationGetRelid(relation);
679         *relp = relation;
680
681         return address;
682 }
683
684 /*
685  * Find object address for an object that is attached to a relation.
686  *
687  * Note that we take only an AccessShareLock on the relation.  We need not
688  * pass down the LOCKMODE from get_object_address(), because that is the lock
689  * mode for the object itself, not the relation to which it is attached.
690  */
691 static ObjectAddress
692 get_object_address_relobject(ObjectType objtype, List *objname,
693                                                          Relation *relp, bool missing_ok)
694 {
695         ObjectAddress address;
696         Relation        relation = NULL;
697         int                     nnames;
698         const char *depname;
699
700         /* Extract name of dependent object. */
701         depname = strVal(lfirst(list_tail(objname)));
702
703         /* Separate relation name from dependent object name. */
704         nnames = list_length(objname);
705         if (nnames < 2)
706         {
707                 Oid                     reloid;
708
709                 /*
710                  * For compatibility with very old releases, we sometimes allow users
711                  * to attempt to specify a rule without mentioning the relation name.
712                  * If there's only rule by that name in the entire database, this will
713                  * work.  But objects other than rules don't get this special
714                  * treatment.
715                  */
716                 if (objtype != OBJECT_RULE)
717                         elog(ERROR, "must specify relation and object name");
718                 address.classId = RewriteRelationId;
719                 address.objectId =
720                         get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
721                 address.objectSubId = 0;
722
723                 /*
724                  * Caller is expecting to get back the relation, even though we didn't
725                  * end up using it to find the rule.
726                  */
727                 if (OidIsValid(address.objectId))
728                         relation = heap_open(reloid, AccessShareLock);
729         }
730         else
731         {
732                 List       *relname;
733                 Oid                     reloid;
734
735                 /* Extract relation name and open relation. */
736                 relname = list_truncate(list_copy(objname), nnames - 1);
737                 relation = heap_openrv(makeRangeVarFromNameList(relname),
738                                                            AccessShareLock);
739                 reloid = RelationGetRelid(relation);
740
741                 switch (objtype)
742                 {
743                         case OBJECT_RULE:
744                                 address.classId = RewriteRelationId;
745                                 address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
746                                 address.objectSubId = 0;
747                                 break;
748                         case OBJECT_TRIGGER:
749                                 address.classId = TriggerRelationId;
750                                 address.objectId = get_trigger_oid(reloid, depname, missing_ok);
751                                 address.objectSubId = 0;
752                                 break;
753                         case OBJECT_CONSTRAINT:
754                                 address.classId = ConstraintRelationId;
755                                 address.objectId =
756                                         get_relation_constraint_oid(reloid, depname, missing_ok);
757                                 address.objectSubId = 0;
758                                 break;
759                         default:
760                                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
761                                 /* placate compiler, which doesn't know elog won't return */
762                                 address.classId = InvalidOid;
763                                 address.objectId = InvalidOid;
764                                 address.objectSubId = 0;
765                 }
766
767                 /* Avoid relcache leak when object not found. */
768                 if (!OidIsValid(address.objectId))
769                 {
770                         heap_close(relation, AccessShareLock);
771                         relation = NULL;        /* department of accident prevention */
772                         return address;
773                 }
774         }
775
776         /* Done. */
777         *relp = relation;
778         return address;
779 }
780
781 /*
782  * Find the ObjectAddress for an attribute.
783  */
784 static ObjectAddress
785 get_object_address_attribute(ObjectType objtype, List *objname,
786                                                          Relation *relp, LOCKMODE lockmode,
787                                                          bool missing_ok)
788 {
789         ObjectAddress address;
790         List       *relname;
791         Oid                     reloid;
792         Relation        relation;
793         const char *attname;
794         AttrNumber      attnum;
795
796         /* Extract relation name and open relation. */
797         if (list_length(objname) < 2)
798                 ereport(ERROR,
799                                 (errcode(ERRCODE_SYNTAX_ERROR),
800                                  errmsg("column name must be qualified")));
801         attname = strVal(lfirst(list_tail(objname)));
802         relname = list_truncate(list_copy(objname), list_length(objname) - 1);
803         relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
804         reloid = RelationGetRelid(relation);
805
806         /* Look up attribute and construct return value. */
807         attnum = get_attnum(reloid, attname);
808         if (attnum == InvalidAttrNumber)
809         {
810                 if (!missing_ok)
811                         ereport(ERROR,
812                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
813                                          errmsg("column \"%s\" of relation \"%s\" does not exist",
814                                                         attname, NameListToString(relname))));
815
816                 address.classId = RelationRelationId;
817                 address.objectId = InvalidOid;
818                 address.objectSubId = InvalidAttrNumber;
819                 return address;
820         }
821
822         address.classId = RelationRelationId;
823         address.objectId = reloid;
824         address.objectSubId = attnum;
825
826         *relp = relation;
827         return address;
828 }
829
830 /*
831  * Find the ObjectAddress for a type or domain
832  */
833 static ObjectAddress
834 get_object_address_type(ObjectType objtype,
835                                                 List *objname, bool missing_ok)
836 {
837         ObjectAddress address;
838         TypeName   *typename;
839         Type            tup;
840
841         typename = makeTypeNameFromNameList(objname);
842
843         address.classId = TypeRelationId;
844         address.objectId = InvalidOid;
845         address.objectSubId = 0;
846
847         tup = LookupTypeName(NULL, typename, NULL);
848         if (!HeapTupleIsValid(tup))
849         {
850                 if (!missing_ok)
851                         ereport(ERROR,
852                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
853                                          errmsg("type \"%s\" does not exist",
854                                                         TypeNameToString(typename))));
855                 return address;
856         }
857         address.objectId = typeTypeId(tup);
858
859         if (objtype == OBJECT_DOMAIN)
860         {
861                 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
862                         ereport(ERROR,
863                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
864                                          errmsg("\"%s\" is not a domain",
865                                                         TypeNameToString(typename))));
866         }
867
868         ReleaseSysCache(tup);
869
870         return address;
871 }
872
873 /*
874  * Find the ObjectAddress for an opclass or opfamily.
875  */
876 static ObjectAddress
877 get_object_address_opcf(ObjectType objtype,
878                                                 List *objname, List *objargs, bool missing_ok)
879 {
880         Oid                     amoid;
881         ObjectAddress address;
882
883         Assert(list_length(objargs) == 1);
884         amoid = get_am_oid(strVal(linitial(objargs)), false);
885
886         switch (objtype)
887         {
888                 case OBJECT_OPCLASS:
889                         address.classId = OperatorClassRelationId;
890                         address.objectId = get_opclass_oid(amoid, objname, missing_ok);
891                         address.objectSubId = 0;
892                         break;
893                 case OBJECT_OPFAMILY:
894                         address.classId = OperatorFamilyRelationId;
895                         address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
896                         address.objectSubId = 0;
897                         break;
898                 default:
899                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
900                         /* placate compiler, which doesn't know elog won't return */
901                         address.classId = InvalidOid;
902                         address.objectId = InvalidOid;
903                         address.objectSubId = 0;
904         }
905
906         return address;
907 }
908
909 /*
910  * Check ownership of an object previously identified by get_object_address.
911  */
912 void
913 check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
914                                            List *objname, List *objargs, Relation relation)
915 {
916         switch (objtype)
917         {
918                 case OBJECT_INDEX:
919                 case OBJECT_SEQUENCE:
920                 case OBJECT_TABLE:
921                 case OBJECT_VIEW:
922                 case OBJECT_FOREIGN_TABLE:
923                 case OBJECT_COLUMN:
924                 case OBJECT_RULE:
925                 case OBJECT_TRIGGER:
926                 case OBJECT_CONSTRAINT:
927                         if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
928                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
929                                                            RelationGetRelationName(relation));
930                         break;
931                 case OBJECT_DATABASE:
932                         if (!pg_database_ownercheck(address.objectId, roleid))
933                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
934                                                            NameListToString(objname));
935                         break;
936                 case OBJECT_TYPE:
937                 case OBJECT_DOMAIN:
938                 case OBJECT_ATTRIBUTE:
939                         if (!pg_type_ownercheck(address.objectId, roleid))
940                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
941                                                            format_type_be(address.objectId));
942                         break;
943                 case OBJECT_AGGREGATE:
944                 case OBJECT_FUNCTION:
945                         if (!pg_proc_ownercheck(address.objectId, roleid))
946                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
947                                                            NameListToString(objname));
948                         break;
949                 case OBJECT_OPERATOR:
950                         if (!pg_oper_ownercheck(address.objectId, roleid))
951                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
952                                                            NameListToString(objname));
953                         break;
954                 case OBJECT_SCHEMA:
955                         if (!pg_namespace_ownercheck(address.objectId, roleid))
956                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
957                                                            NameListToString(objname));
958                         break;
959                 case OBJECT_COLLATION:
960                         if (!pg_collation_ownercheck(address.objectId, roleid))
961                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
962                                                            NameListToString(objname));
963                         break;
964                 case OBJECT_CONVERSION:
965                         if (!pg_conversion_ownercheck(address.objectId, roleid))
966                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
967                                                            NameListToString(objname));
968                         break;
969                 case OBJECT_EXTENSION:
970                         if (!pg_extension_ownercheck(address.objectId, roleid))
971                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
972                                                            NameListToString(objname));
973                         break;
974                 case OBJECT_FDW:
975                         if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
976                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
977                                                            NameListToString(objname));
978                         break;
979                 case OBJECT_FOREIGN_SERVER:
980                         if (!pg_foreign_server_ownercheck(address.objectId, roleid))
981                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
982                                                            NameListToString(objname));
983                         break;
984                 case OBJECT_LANGUAGE:
985                         if (!pg_language_ownercheck(address.objectId, roleid))
986                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
987                                                            NameListToString(objname));
988                         break;
989                 case OBJECT_OPCLASS:
990                         if (!pg_opclass_ownercheck(address.objectId, roleid))
991                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
992                                                            NameListToString(objname));
993                         break;
994                 case OBJECT_OPFAMILY:
995                         if (!pg_opfamily_ownercheck(address.objectId, roleid))
996                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
997                                                            NameListToString(objname));
998                         break;
999                 case OBJECT_LARGEOBJECT:
1000                         if (!lo_compat_privileges &&
1001                                 !pg_largeobject_ownercheck(address.objectId, roleid))
1002                                 ereport(ERROR,
1003                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1004                                                  errmsg("must be owner of large object %u",
1005                                                                 address.objectId)));
1006                         break;
1007                 case OBJECT_CAST:
1008                         {
1009                                 /* We can only check permissions on the source/target types */
1010                                 TypeName   *sourcetype = (TypeName *) linitial(objname);
1011                                 TypeName   *targettype = (TypeName *) linitial(objargs);
1012                                 Oid                     sourcetypeid = typenameTypeId(NULL, sourcetype);
1013                                 Oid                     targettypeid = typenameTypeId(NULL, targettype);
1014
1015                                 if (!pg_type_ownercheck(sourcetypeid, roleid)
1016                                         && !pg_type_ownercheck(targettypeid, roleid))
1017                                         ereport(ERROR,
1018                                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1019                                                          errmsg("must be owner of type %s or type %s",
1020                                                                         format_type_be(sourcetypeid),
1021                                                                         format_type_be(targettypeid))));
1022                         }
1023                         break;
1024                 case OBJECT_TABLESPACE:
1025                         if (!pg_tablespace_ownercheck(address.objectId, roleid))
1026                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
1027                                                            NameListToString(objname));
1028                         break;
1029                 case OBJECT_TSDICTIONARY:
1030                         if (!pg_ts_dict_ownercheck(address.objectId, roleid))
1031                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
1032                                                            NameListToString(objname));
1033                         break;
1034                 case OBJECT_TSCONFIGURATION:
1035                         if (!pg_ts_config_ownercheck(address.objectId, roleid))
1036                                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
1037                                                            NameListToString(objname));
1038                         break;
1039                 case OBJECT_ROLE:
1040
1041                         /*
1042                          * We treat roles as being "owned" by those with CREATEROLE priv,
1043                          * except that superusers are only owned by superusers.
1044                          */
1045                         if (superuser_arg(address.objectId))
1046                         {
1047                                 if (!superuser_arg(roleid))
1048                                         ereport(ERROR,
1049                                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1050                                                          errmsg("must be superuser")));
1051                         }
1052                         else
1053                         {
1054                                 if (!has_createrole_privilege(roleid))
1055                                         ereport(ERROR,
1056                                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1057                                                          errmsg("must have CREATEROLE privilege")));
1058                         }
1059                         break;
1060                 case OBJECT_TSPARSER:
1061                 case OBJECT_TSTEMPLATE:
1062                         /* We treat these object types as being owned by superusers */
1063                         if (!superuser_arg(roleid))
1064                                 ereport(ERROR,
1065                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1066                                                  errmsg("must be superuser")));
1067                         break;
1068                 default:
1069                         elog(ERROR, "unrecognized object type: %d",
1070                                  (int) objtype);
1071         }
1072 }
1073
1074 /*
1075  * get_object_namespace
1076  *
1077  * Find the schema containing the specified object.  For non-schema objects,
1078  * this function returns InvalidOid.
1079  */
1080 Oid
1081 get_object_namespace(const ObjectAddress *address)
1082 {
1083         int                     cache;
1084         HeapTuple       tuple;
1085         bool            isnull;
1086         Oid                     oid;
1087         ObjectPropertyType *property;
1088
1089         /* If not owned by a namespace, just return InvalidOid. */
1090         property = get_object_property_data(address->classId);
1091         if (property->attnum_namespace == InvalidAttrNumber)
1092                 return InvalidOid;
1093
1094         /* Currently, we can only handle object types with system caches. */
1095         cache = property->oid_catcache_id;
1096         Assert(cache != -1);
1097
1098         /* Fetch tuple from syscache and extract namespace attribute. */
1099         tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
1100         if (!HeapTupleIsValid(tuple))
1101                 elog(ERROR, "cache lookup failed for cache %d oid %u",
1102                          cache, address->objectId);
1103         oid = DatumGetObjectId(SysCacheGetAttr(cache,
1104                                                                                    tuple,
1105                                                                                    property->attnum_namespace,
1106                                                                                    &isnull));
1107         Assert(!isnull);
1108         ReleaseSysCache(tuple);
1109
1110         return oid;
1111 }
1112
1113 /*
1114  * Find ObjectProperty structure by class_id.
1115  */
1116 static ObjectPropertyType *
1117 get_object_property_data(Oid class_id)
1118 {
1119         int                     index;
1120
1121         for (index = 0; index < lengthof(ObjectProperty); index++)
1122                 if (ObjectProperty[index].class_oid == class_id)
1123                         return &ObjectProperty[index];
1124
1125         elog(ERROR, "unrecognized class id: %u", class_id);
1126         return NULL;                            /* not reached */
1127 }