]> granicus.if.org Git - postgresql/blob - src/backend/catalog/objectaddress.c
c4608f7f1732e2f9022a29c4c68180dac20c2183
[postgresql] / src / backend / catalog / objectaddress.c
1 /*-------------------------------------------------------------------------
2  *
3  * objectaddress.c
4  *        functions for working with ObjectAddresses
5  *
6  * Portions Copyright (c) 1996-2011, 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/heapam.h"
19 #include "access/sysattr.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/namespace.h"
24 #include "catalog/objectaddress.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_cast.h"
27 #include "catalog/pg_class.h"
28 #include "catalog/pg_constraint.h"
29 #include "catalog/pg_conversion.h"
30 #include "catalog/pg_database.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/proclang.h"
50 #include "commands/tablespace.h"
51 #include "commands/trigger.h"
52 #include "nodes/makefuncs.h"
53 #include "parser/parse_func.h"
54 #include "parser/parse_oper.h"
55 #include "parser/parse_type.h"
56 #include "rewrite/rewriteSupport.h"
57 #include "storage/lmgr.h"
58 #include "utils/acl.h"
59 #include "utils/builtins.h"
60 #include "utils/fmgroids.h"
61 #include "utils/lsyscache.h"
62 #include "utils/syscache.h"
63 #include "utils/rel.h"
64 #include "utils/tqual.h"
65
66 static ObjectAddress get_object_address_unqualified(ObjectType objtype,
67                                                            List *qualname);
68 static Relation get_relation_by_qualified_name(ObjectType objtype,
69                                                            List *objname, LOCKMODE lockmode);
70 static ObjectAddress get_object_address_relobject(ObjectType objtype,
71                                                          List *objname, Relation *relp);
72 static ObjectAddress get_object_address_attribute(ObjectType objtype,
73                                                          List *objname, Relation *relp, LOCKMODE lockmode);
74 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
75                                                 List *objargs);
76 static bool object_exists(ObjectAddress address);
77
78 /*
79  * Translate an object name and arguments (as passed by the parser) to an
80  * ObjectAddress.
81  *
82  * The returned object will be locked using the specified lockmode.  If a
83  * sub-object is looked up, the parent object will be locked instead.
84  *
85  * If the object is a relation or a child object of a relation (e.g. an
86  * attribute or contraint), the relation is also opened and *relp receives
87  * the open relcache entry pointer; otherwise, *relp is set to NULL.  This
88  * is a bit grotty but it makes life simpler, since the caller will
89  * typically need the relcache entry too.  Caller must close the relcache
90  * entry when done with it.  The relation is locked with the specified lockmode
91  * if the target object is the relation itself or an attribute, but for other
92  * child objects, only AccessShareLock is acquired on the relation.
93  *
94  * We don't currently provide a function to release the locks acquired here;
95  * typically, the lock must be held until commit to guard against a concurrent
96  * drop operation.
97  */
98 ObjectAddress
99 get_object_address(ObjectType objtype, List *objname, List *objargs,
100                                    Relation *relp, LOCKMODE lockmode)
101 {
102         ObjectAddress   address;
103         Relation                relation = NULL;
104
105         /* Some kind of lock must be taken. */
106         Assert(lockmode != NoLock);
107
108         switch (objtype)
109         {
110                 case OBJECT_INDEX:
111                 case OBJECT_SEQUENCE:
112                 case OBJECT_TABLE:
113                 case OBJECT_VIEW:
114                 case OBJECT_FOREIGN_TABLE:
115                         relation =
116                                 get_relation_by_qualified_name(objtype, objname, lockmode);
117                         address.classId = RelationRelationId;
118                         address.objectId = RelationGetRelid(relation);
119                         address.objectSubId = 0;
120                         break;
121                 case OBJECT_COLUMN:
122                         address =
123                                 get_object_address_attribute(objtype, objname, &relation,
124                                         lockmode);
125                         break;
126                 case OBJECT_RULE:
127                 case OBJECT_TRIGGER:
128                 case OBJECT_CONSTRAINT:
129                         address = get_object_address_relobject(objtype, objname, &relation);
130                         break;
131                 case OBJECT_DATABASE:
132                 case OBJECT_TABLESPACE:
133                 case OBJECT_ROLE:
134                 case OBJECT_SCHEMA:
135                 case OBJECT_LANGUAGE:
136                         address = get_object_address_unqualified(objtype, objname);
137                         break;
138                 case OBJECT_TYPE:
139                         address.classId = TypeRelationId;
140                         address.objectId =
141                                 typenameTypeId(NULL, makeTypeNameFromNameList(objname));
142                         address.objectSubId = 0;
143                         break;
144                 case OBJECT_AGGREGATE:
145                         address.classId = ProcedureRelationId;
146                         address.objectId = LookupAggNameTypeNames(objname, objargs, false);
147                         address.objectSubId = 0;
148                         break;
149                 case OBJECT_FUNCTION:
150                         address.classId = ProcedureRelationId;
151                         address.objectId = LookupFuncNameTypeNames(objname, objargs, false);
152                         address.objectSubId = 0;
153                         break;
154                 case OBJECT_OPERATOR:
155                         Assert(list_length(objargs) == 2);
156                         address.classId = OperatorRelationId;
157                         address.objectId =
158                                 LookupOperNameTypeNames(NULL, objname,
159                                                                                 (TypeName *) linitial(objargs),
160                                                                                 (TypeName *) lsecond(objargs),
161                                                                                 false, -1);
162                         address.objectSubId = 0;
163                         break;
164                 case OBJECT_CONVERSION:
165                         address.classId = ConversionRelationId;
166                         address.objectId = get_conversion_oid(objname, false);
167                         address.objectSubId = 0;
168                         break;
169                 case OBJECT_OPCLASS:
170                 case OBJECT_OPFAMILY:
171                         address = get_object_address_opcf(objtype, objname, objargs);
172                         break;
173                 case OBJECT_LARGEOBJECT:
174                         Assert(list_length(objname) == 1);
175                         address.classId = LargeObjectRelationId;
176                         address.objectId = oidparse(linitial(objname));
177                         address.objectSubId = 0;
178                         if (!LargeObjectExists(address.objectId))
179                                 ereport(ERROR,
180                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
181                                                  errmsg("large object %u does not exist",
182                                                                 address.objectId)));
183                         break;
184                 case OBJECT_CAST:
185                         {
186                                 TypeName *sourcetype = (TypeName *) linitial(objname);
187                                 TypeName *targettype = (TypeName *) linitial(objargs);
188                                 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
189                                 Oid targettypeid = typenameTypeId(NULL, targettype);
190
191                                 address.classId = CastRelationId;
192                                 address.objectId =
193                                         get_cast_oid(sourcetypeid, targettypeid, false);
194                                 address.objectSubId = 0;
195                         }
196                         break;
197                 case OBJECT_TSPARSER:
198                         address.classId = TSParserRelationId;
199                         address.objectId = get_ts_parser_oid(objname, false);
200                         address.objectSubId = 0;
201                         break;
202                 case OBJECT_TSDICTIONARY:
203                         address.classId = TSDictionaryRelationId;
204                         address.objectId = get_ts_dict_oid(objname, false);
205                         address.objectSubId = 0;
206                         break;
207                 case OBJECT_TSTEMPLATE:
208                         address.classId = TSTemplateRelationId;
209                         address.objectId = get_ts_template_oid(objname, false);
210                         address.objectSubId = 0;
211                         break;
212                 case OBJECT_TSCONFIGURATION:
213                         address.classId = TSConfigRelationId;
214                         address.objectId = get_ts_config_oid(objname, false);
215                         address.objectSubId = 0;
216                         break;
217                 default:
218                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
219                         /* placate compiler, in case it thinks elog might return */
220                         address.classId = InvalidOid;
221                         address.objectId = InvalidOid;
222                         address.objectSubId = 0;
223         }
224
225         /*
226          * If we're dealing with a relation or attribute, then the relation is
227          * already locked.  If we're dealing with any other type of object, we need
228          * to lock it and then verify that it still exists.
229          */
230         if (address.classId != RelationRelationId)
231         {
232                 if (IsSharedRelation(address.classId))
233                         LockSharedObject(address.classId, address.objectId, 0, lockmode);
234                 else
235                         LockDatabaseObject(address.classId, address.objectId, 0, lockmode);
236                 /* Did it go away while we were waiting for the lock? */
237                 if (!object_exists(address))
238                         elog(ERROR, "cache lookup failed for class %u object %u subobj %d",
239                                  address.classId, address.objectId, address.objectSubId);
240         }
241
242         /* Return the object address and the relation. */
243         *relp = relation;
244         return address;
245 }
246
247 /*
248  * Find an ObjectAddress for a type of object that is identified by an
249  * unqualified name.
250  */
251 static ObjectAddress
252 get_object_address_unqualified(ObjectType objtype, List *qualname)
253 {
254         const char *name;
255         ObjectAddress address;
256
257         /*
258          * The types of names handled by this function are not permitted to be
259          * schema-qualified or catalog-qualified.
260          */
261         if (list_length(qualname) != 1)
262         {
263                 const char *msg;
264
265                 switch (objtype)
266                 {
267                         case OBJECT_DATABASE:
268                                 msg = gettext_noop("database name cannot be qualified");
269                                 break;
270                         case OBJECT_TABLESPACE:
271                                 msg = gettext_noop("tablespace name cannot be qualified");
272                                 break;
273                         case OBJECT_ROLE:
274                                 msg = gettext_noop("role name cannot be qualified");
275                                 break;
276                         case OBJECT_SCHEMA:
277                                 msg = gettext_noop("schema name cannot be qualified");
278                                 break;
279                         case OBJECT_LANGUAGE:
280                                 msg = gettext_noop("language name cannot be qualified");
281                                 break;
282                         default:
283                                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
284                                 msg = NULL;                     /* placate compiler */
285                 }
286                 ereport(ERROR,
287                                 (errcode(ERRCODE_SYNTAX_ERROR),
288                                  errmsg("%s", _(msg))));
289         }
290
291         /* Format is valid, extract the actual name. */
292         name = strVal(linitial(qualname));
293
294         /* Translate name to OID. */
295         switch (objtype)
296         {
297                 case OBJECT_DATABASE:
298                         address.classId = DatabaseRelationId;
299                         address.objectId = get_database_oid(name, false);
300                         address.objectSubId = 0;
301                         break;
302                 case OBJECT_TABLESPACE:
303                         address.classId = TableSpaceRelationId;
304                         address.objectId = get_tablespace_oid(name, false);
305                         address.objectSubId = 0;
306                         break;
307                 case OBJECT_ROLE:
308                         address.classId = AuthIdRelationId;
309                         address.objectId = get_role_oid(name, false);
310                         address.objectSubId = 0;
311                         break;
312                 case OBJECT_SCHEMA:
313                         address.classId = NamespaceRelationId;
314                         address.objectId = get_namespace_oid(name, false);
315                         address.objectSubId = 0;
316                         break;
317                 case OBJECT_LANGUAGE:
318                         address.classId = LanguageRelationId;
319                         address.objectId = get_language_oid(name, false);
320                         address.objectSubId = 0;
321                         break;
322                 default:
323                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
324                         /* placate compiler, which doesn't know elog won't return */
325                         address.classId = InvalidOid;
326                         address.objectId = InvalidOid;
327                         address.objectSubId = 0;
328         }
329
330         return address;
331 }
332
333 /*
334  * Locate a relation by qualified name.
335  */
336 static Relation
337 get_relation_by_qualified_name(ObjectType objtype, List *objname,
338                                                            LOCKMODE lockmode)
339 {
340         Relation relation;
341
342         relation = relation_openrv(makeRangeVarFromNameList(objname), lockmode);
343         switch (objtype)
344         {
345                 case OBJECT_INDEX:
346                         if (relation->rd_rel->relkind != RELKIND_INDEX)
347                                 ereport(ERROR,
348                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
349                                                  errmsg("\"%s\" is not an index",
350                                                                 RelationGetRelationName(relation))));
351                         break;
352                 case OBJECT_SEQUENCE:
353                         if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
354                                 ereport(ERROR,
355                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
356                                                  errmsg("\"%s\" is not a sequence",
357                                                                 RelationGetRelationName(relation))));
358                         break;
359                 case OBJECT_TABLE:
360                         if (relation->rd_rel->relkind != RELKIND_RELATION)
361                                 ereport(ERROR,
362                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
363                                                  errmsg("\"%s\" is not a table",
364                                                                 RelationGetRelationName(relation))));
365                         break;
366                 case OBJECT_VIEW:
367                         if (relation->rd_rel->relkind != RELKIND_VIEW)
368                                 ereport(ERROR,
369                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
370                                                  errmsg("\"%s\" is not a view",
371                                                                 RelationGetRelationName(relation))));
372                         break;
373                 case OBJECT_FOREIGN_TABLE:
374                         if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
375                                 ereport(ERROR,
376                                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
377                                                  errmsg("\"%s\" is not a foreign table",
378                                                                 RelationGetRelationName(relation))));
379                         break;
380                 default:
381                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
382                         break;
383         }
384
385         return relation;
386 }
387
388 /*
389  * Find object address for an object that is attached to a relation.
390  *
391  * Note that we take only an AccessShareLock on the relation.  We need not
392  * pass down the LOCKMODE from get_object_address(), because that is the lock
393  * mode for the object itself, not the relation to which it is attached.
394  */
395 static ObjectAddress
396 get_object_address_relobject(ObjectType objtype, List *objname, Relation *relp)
397 {
398         ObjectAddress address;
399         Relation        relation = NULL;
400         int                     nnames;
401         const char *depname;
402
403         /* Extract name of dependent object. */
404         depname = strVal(lfirst(list_tail(objname)));
405
406         /* Separate relation name from dependent object name. */
407         nnames = list_length(objname);
408         if (nnames < 2)
409         {
410                 Oid             reloid;
411
412                 /*
413                  * For compatibility with very old releases, we sometimes allow users
414                  * to attempt to specify a rule without mentioning the relation name.
415                  * If there's only rule by that name in the entire database, this will
416                  * work.  But objects other than rules don't get this special
417                  * treatment.
418                  */
419                 if (objtype != OBJECT_RULE)
420                         elog(ERROR, "must specify relation and object name");
421                 address.classId = RewriteRelationId;
422                 address.objectId = get_rewrite_oid_without_relid(depname, &reloid);
423                 address.objectSubId = 0;
424                 relation = heap_open(reloid, AccessShareLock);
425         }
426         else
427         {
428                 List       *relname;
429                 Oid                     reloid;
430
431                 /* Extract relation name and open relation. */
432                 relname = list_truncate(list_copy(objname), nnames - 1);
433                 relation = heap_openrv(makeRangeVarFromNameList(relname),
434                                                            AccessShareLock);
435                 reloid = RelationGetRelid(relation);
436
437                 switch (objtype)
438                 {
439                         case OBJECT_RULE:
440                                 address.classId = RewriteRelationId;
441                                 address.objectId = get_rewrite_oid(reloid, depname, false);
442                                 address.objectSubId = 0;
443                                 break;
444                         case OBJECT_TRIGGER:
445                                 address.classId = TriggerRelationId;
446                                 address.objectId = get_trigger_oid(reloid, depname, false);
447                                 address.objectSubId = 0;
448                                 break;
449                         case OBJECT_CONSTRAINT:
450                                 address.classId = ConstraintRelationId;
451                                 address.objectId = get_constraint_oid(reloid, depname, false);
452                                 address.objectSubId = 0;
453                                 break;
454                         default:
455                                 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
456                                 /* placate compiler, which doesn't know elog won't return */
457                                 address.classId = InvalidOid;
458                                 address.objectId = InvalidOid;
459                                 address.objectSubId = 0;
460                 }
461         }
462
463         /* Done. */
464         *relp = relation;
465         return address;
466 }
467
468 /*
469  * Find the ObjectAddress for an attribute.
470  */
471 static ObjectAddress
472 get_object_address_attribute(ObjectType objtype, List *objname,
473                                                          Relation *relp, LOCKMODE lockmode)
474 {
475         ObjectAddress   address;
476         List       *relname;
477         Oid                     reloid;
478         Relation        relation;
479         const char *attname;
480
481         /* Extract relation name and open relation. */
482         attname = strVal(lfirst(list_tail(objname)));
483         relname = list_truncate(list_copy(objname), list_length(objname) - 1);
484         relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
485         reloid = RelationGetRelid(relation);
486
487         /* Look up attribute and construct return value. */
488         address.classId = RelationRelationId;
489         address.objectId = reloid;
490         address.objectSubId = get_attnum(reloid, attname);
491         if (address.objectSubId == InvalidAttrNumber)
492                 ereport(ERROR,
493                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
494                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
495                                  attname, RelationGetRelationName(relation))));
496
497         *relp = relation;
498         return address;
499 }
500
501 /*
502  * Find the ObjectAddress for an opclass or opfamily.
503  */
504 static ObjectAddress
505 get_object_address_opcf(ObjectType objtype, List *objname, List *objargs)
506 {
507         Oid                     amoid;
508         ObjectAddress address;
509
510         Assert(list_length(objargs) == 1);
511         amoid = get_am_oid(strVal(linitial(objargs)), false);
512
513         switch (objtype)
514         {
515                 case OBJECT_OPCLASS:
516                         address.classId = OperatorClassRelationId;
517                         address.objectId = get_opclass_oid(amoid, objname, false);
518                         address.objectSubId = 0;
519                         break;
520                 case OBJECT_OPFAMILY:
521                         address.classId = OperatorFamilyRelationId;
522                         address.objectId = get_opfamily_oid(amoid, objname, false);
523                         address.objectSubId = 0;
524                         break;
525                 default:
526                         elog(ERROR, "unrecognized objtype: %d", (int) objtype);
527                         /* placate compiler, which doesn't know elog won't return */
528                         address.classId = InvalidOid;
529                         address.objectId = InvalidOid;
530                         address.objectSubId = 0;
531         }
532
533         return address;
534 }
535
536 /*
537  * Test whether an object exists.
538  */
539 static bool
540 object_exists(ObjectAddress address)
541 {
542         int                     cache = -1;
543         Oid                     indexoid = InvalidOid;
544         Relation        rel;
545         ScanKeyData     skey[1];
546         SysScanDesc     sd;
547         bool            found;
548
549         /* Sub-objects require special treatment. */
550         if (address.objectSubId != 0)
551         {
552                 HeapTuple       atttup;
553
554                 /* Currently, attributes are the only sub-objects. */
555                 Assert(address.classId == RelationRelationId);
556                 atttup = SearchSysCache2(ATTNUM, ObjectIdGetDatum(address.objectId),
557                                                                  Int16GetDatum(address.objectSubId));
558                 if (!HeapTupleIsValid(atttup))
559                         found = false;
560                 else
561                 {
562                         found = ((Form_pg_attribute) GETSTRUCT(atttup))->attisdropped;
563                         ReleaseSysCache(atttup);
564                 }
565                 return found;
566         }
567
568         /*
569          * For object types that have a relevant syscache, we use it; for
570          * everything else, we'll have to do an index-scan.  This switch
571          * sets either the cache to be used for the syscache lookup, or the
572          * index to be used for the index scan.
573          */
574         switch (address.classId)
575         {
576                 case RelationRelationId:
577                         cache = RELOID;
578                         break;
579                 case RewriteRelationId:
580                         indexoid = RewriteOidIndexId;
581                         break;
582                 case TriggerRelationId:
583                         indexoid = TriggerOidIndexId;
584                         break;
585                 case ConstraintRelationId:
586                         cache = CONSTROID;
587                         break;
588                 case DatabaseRelationId:
589                         cache = DATABASEOID;
590                         break;
591                 case TableSpaceRelationId:
592                         cache = TABLESPACEOID;
593                         break;
594                 case AuthIdRelationId:
595                         cache = AUTHOID;
596                         break;
597                 case NamespaceRelationId:
598                         cache = NAMESPACEOID;
599                         break;
600                 case LanguageRelationId:
601                         cache = LANGOID;
602                         break;
603                 case TypeRelationId:
604                         cache = TYPEOID;
605                         break;
606                 case ProcedureRelationId:
607                         cache = PROCOID;
608                         break;
609                 case OperatorRelationId:
610                         cache = OPEROID;
611                         break;
612                 case ConversionRelationId:
613                         cache = CONVOID;
614                         break;
615                 case OperatorClassRelationId:
616                         cache = CLAOID;
617                         break;
618                 case OperatorFamilyRelationId:
619                         cache = OPFAMILYOID;
620                         break;
621                 case LargeObjectRelationId:
622                         /*
623                          * Weird backward compatibility hack: ObjectAddress notation uses
624                          * LargeObjectRelationId for large objects, but since PostgreSQL
625                          * 9.0, the relevant catalog is actually
626                          * LargeObjectMetadataRelationId.
627                          */
628                         address.classId = LargeObjectMetadataRelationId;
629                         indexoid = LargeObjectMetadataOidIndexId;
630                         break;
631                 case CastRelationId:
632                         indexoid = CastOidIndexId;
633                         break;
634                 case TSParserRelationId:
635                         cache = TSPARSEROID;
636                         break;
637                 case TSDictionaryRelationId:
638                         cache = TSDICTOID;
639                         break;
640                 case TSTemplateRelationId:
641                         cache = TSTEMPLATEOID;
642                         break;
643                 case TSConfigRelationId:
644                         cache = TSCONFIGOID;
645                         break;
646                 default:
647                         elog(ERROR, "unrecognized classid: %u", address.classId);
648         }
649
650         /* Found a syscache? */
651         if (cache != -1)
652                 return SearchSysCacheExists1(cache, ObjectIdGetDatum(address.objectId));
653
654         /* No syscache, so examine the table directly. */
655         Assert(OidIsValid(indexoid));
656         ScanKeyInit(&skey[0],
657                                 ObjectIdAttributeNumber,
658                                 BTEqualStrategyNumber, F_OIDEQ,
659                                 ObjectIdGetDatum(address.objectId));
660         rel = heap_open(address.classId, AccessShareLock);
661         sd = systable_beginscan(rel, indexoid, true, SnapshotNow, 1, skey);
662         found = HeapTupleIsValid(systable_getnext(sd));
663         systable_endscan(sd);
664         heap_close(rel, AccessShareLock);
665         return found;
666 }