Header And Logo

PostgreSQL
| The world's most advanced open source database.

dropcmds.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * dropcmds.c
00004  *    handle various "DROP" operations
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/catalog/dropcmds.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 #include "access/heapam.h"
00019 #include "access/htup_details.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/namespace.h"
00022 #include "catalog/objectaddress.h"
00023 #include "catalog/pg_class.h"
00024 #include "catalog/pg_proc.h"
00025 #include "commands/defrem.h"
00026 #include "miscadmin.h"
00027 #include "nodes/makefuncs.h"
00028 #include "parser/parse_type.h"
00029 #include "utils/builtins.h"
00030 #include "utils/syscache.h"
00031 
00032 static void does_not_exist_skipping(ObjectType objtype,
00033                         List *objname, List *objargs);
00034 
00035 /*
00036  * Drop one or more objects.
00037  *
00038  * We don't currently handle all object types here.  Relations, for example,
00039  * require special handling, because (for example) indexes have additional
00040  * locking requirements.
00041  *
00042  * We look up all the objects first, and then delete them in a single
00043  * performMultipleDeletions() call.  This avoids unnecessary DROP RESTRICT
00044  * errors if there are dependencies between them.
00045  */
00046 void
00047 RemoveObjects(DropStmt *stmt)
00048 {
00049     ObjectAddresses *objects;
00050     ListCell   *cell1;
00051     ListCell   *cell2 = NULL;
00052 
00053     objects = new_object_addresses();
00054 
00055     foreach(cell1, stmt->objects)
00056     {
00057         ObjectAddress address;
00058         List       *objname = lfirst(cell1);
00059         List       *objargs = NIL;
00060         Relation    relation = NULL;
00061         Oid         namespaceId;
00062 
00063         if (stmt->arguments)
00064         {
00065             cell2 = (!cell2 ? list_head(stmt->arguments) : lnext(cell2));
00066             objargs = lfirst(cell2);
00067         }
00068 
00069         /* Get an ObjectAddress for the object. */
00070         address = get_object_address(stmt->removeType,
00071                                      objname, objargs,
00072                                      &relation,
00073                                      AccessExclusiveLock,
00074                                      stmt->missing_ok);
00075 
00076         /* Issue NOTICE if supplied object was not found. */
00077         if (!OidIsValid(address.objectId))
00078         {
00079             does_not_exist_skipping(stmt->removeType, objname, objargs);
00080             continue;
00081         }
00082 
00083         /*
00084          * Although COMMENT ON FUNCTION, SECURITY LABEL ON FUNCTION, etc. are
00085          * happy to operate on an aggregate as on any other function, we have
00086          * historically not allowed this for DROP FUNCTION.
00087          */
00088         if (stmt->removeType == OBJECT_FUNCTION)
00089         {
00090             Oid         funcOid = address.objectId;
00091             HeapTuple   tup;
00092 
00093             tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
00094             if (!HeapTupleIsValid(tup)) /* should not happen */
00095                 elog(ERROR, "cache lookup failed for function %u", funcOid);
00096 
00097             if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
00098                 ereport(ERROR,
00099                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00100                          errmsg("\"%s\" is an aggregate function",
00101                                 NameListToString(objname)),
00102                 errhint("Use DROP AGGREGATE to drop aggregate functions.")));
00103 
00104             ReleaseSysCache(tup);
00105         }
00106 
00107         /* Check permissions. */
00108         namespaceId = get_object_namespace(&address);
00109         if (!OidIsValid(namespaceId) ||
00110             !pg_namespace_ownercheck(namespaceId, GetUserId()))
00111             check_object_ownership(GetUserId(), stmt->removeType, address,
00112                                    objname, objargs, relation);
00113 
00114         /* Release any relcache reference count, but keep lock until commit. */
00115         if (relation)
00116             heap_close(relation, NoLock);
00117 
00118         add_exact_object_address(&address, objects);
00119     }
00120 
00121     /* Here we really delete them. */
00122     performMultipleDeletions(objects, stmt->behavior, 0);
00123 
00124     free_object_addresses(objects);
00125 }
00126 
00127 /*
00128  * Generate a NOTICE stating that the named object was not found, and is
00129  * being skipped.  This is only relevant when "IF EXISTS" is used; otherwise,
00130  * get_object_address() will throw an ERROR.
00131  */
00132 static void
00133 does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
00134 {
00135     const char *msg = NULL;
00136     char       *name = NULL;
00137     char       *args = NULL;
00138 
00139     switch (objtype)
00140     {
00141         case OBJECT_TYPE:
00142         case OBJECT_DOMAIN:
00143             msg = gettext_noop("type \"%s\" does not exist, skipping");
00144             name = TypeNameToString(makeTypeNameFromNameList(objname));
00145             break;
00146         case OBJECT_COLLATION:
00147             msg = gettext_noop("collation \"%s\" does not exist, skipping");
00148             name = NameListToString(objname);
00149             break;
00150         case OBJECT_CONVERSION:
00151             msg = gettext_noop("conversion \"%s\" does not exist, skipping");
00152             name = NameListToString(objname);
00153             break;
00154         case OBJECT_SCHEMA:
00155             msg = gettext_noop("schema \"%s\" does not exist, skipping");
00156             name = NameListToString(objname);
00157             break;
00158         case OBJECT_TSPARSER:
00159             msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
00160             name = NameListToString(objname);
00161             break;
00162         case OBJECT_TSDICTIONARY:
00163             msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
00164             name = NameListToString(objname);
00165             break;
00166         case OBJECT_TSTEMPLATE:
00167             msg = gettext_noop("text search template \"%s\" does not exist, skipping");
00168             name = NameListToString(objname);
00169             break;
00170         case OBJECT_TSCONFIGURATION:
00171             msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
00172             name = NameListToString(objname);
00173             break;
00174         case OBJECT_EXTENSION:
00175             msg = gettext_noop("extension \"%s\" does not exist, skipping");
00176             name = NameListToString(objname);
00177             break;
00178         case OBJECT_FUNCTION:
00179             msg = gettext_noop("function %s(%s) does not exist, skipping");
00180             name = NameListToString(objname);
00181             args = TypeNameListToString(objargs);
00182             break;
00183         case OBJECT_AGGREGATE:
00184             msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
00185             name = NameListToString(objname);
00186             args = TypeNameListToString(objargs);
00187             break;
00188         case OBJECT_OPERATOR:
00189             msg = gettext_noop("operator %s does not exist, skipping");
00190             name = NameListToString(objname);
00191             break;
00192         case OBJECT_LANGUAGE:
00193             msg = gettext_noop("language \"%s\" does not exist, skipping");
00194             name = NameListToString(objname);
00195             break;
00196         case OBJECT_CAST:
00197             msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
00198             name = format_type_be(typenameTypeId(NULL,
00199                                             (TypeName *) linitial(objname)));
00200             args = format_type_be(typenameTypeId(NULL,
00201                                             (TypeName *) linitial(objargs)));
00202             break;
00203         case OBJECT_TRIGGER:
00204             msg = gettext_noop("trigger \"%s\" for table \"%s\" does not exist, skipping");
00205             name = strVal(llast(objname));
00206             args = NameListToString(list_truncate(list_copy(objname),
00207                                                   list_length(objname) - 1));
00208             break;
00209         case OBJECT_EVENT_TRIGGER:
00210             msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
00211             name = NameListToString(objname);
00212             break;
00213         case OBJECT_RULE:
00214             msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
00215             name = strVal(llast(objname));
00216             args = NameListToString(list_truncate(list_copy(objname),
00217                                                   list_length(objname) - 1));
00218             break;
00219         case OBJECT_FDW:
00220             msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping");
00221             name = NameListToString(objname);
00222             break;
00223         case OBJECT_FOREIGN_SERVER:
00224             msg = gettext_noop("server \"%s\" does not exist, skipping");
00225             name = NameListToString(objname);
00226             break;
00227         case OBJECT_OPCLASS:
00228             msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
00229             name = NameListToString(objname);
00230             args = strVal(linitial(objargs));
00231             break;
00232         case OBJECT_OPFAMILY:
00233             msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
00234             name = NameListToString(objname);
00235             args = strVal(linitial(objargs));
00236             break;
00237         default:
00238             elog(ERROR, "unexpected object type (%d)", (int) objtype);
00239             break;
00240     }
00241 
00242     if (!args)
00243         ereport(NOTICE, (errmsg(msg, name)));
00244     else
00245         ereport(NOTICE, (errmsg(msg, name, args)));
00246 }