mirror of https://github.com/postgres/postgres
This gets rid of a significant amount of duplicative code. KaiGai Kohei, reviewed in earlier versions by Dimitri Fontaine, with further review and cleanup by me.pull/1/head
parent
3301c83536
commit
82a4a777d9
@ -0,0 +1,147 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* dropcmds.c |
||||
* handle various "DROP" operations |
||||
* |
||||
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* |
||||
* IDENTIFICATION |
||||
* src/backend/catalog/dropcmds.c |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include "access/heapam.h" |
||||
#include "catalog/dependency.h" |
||||
#include "catalog/namespace.h" |
||||
#include "catalog/objectaddress.h" |
||||
#include "catalog/pg_class.h" |
||||
#include "commands/defrem.h" |
||||
#include "miscadmin.h" |
||||
#include "nodes/makefuncs.h" |
||||
#include "parser/parse_type.h" |
||||
#include "utils/acl.h" |
||||
|
||||
static void does_not_exist_skipping(ObjectType objtype, List *objname); |
||||
|
||||
/*
|
||||
* Drop one or more objects. |
||||
* |
||||
* We don't currently handle all object types here. Relations, for example, |
||||
* require special handling, because (for example) indexes have additional |
||||
* locking requirements. |
||||
* |
||||
* We look up all the objects first, and then delete them in a single |
||||
* performMultipleDeletions() call. This avoids unnecessary DROP RESTRICT |
||||
* errors if there are dependencies between them. |
||||
*/ |
||||
void |
||||
RemoveObjects(DropStmt *stmt) |
||||
{ |
||||
ObjectAddresses *objects; |
||||
ListCell *cell1; |
||||
|
||||
objects = new_object_addresses(); |
||||
|
||||
foreach(cell1, stmt->objects) |
||||
{ |
||||
ObjectAddress address; |
||||
List *objname = lfirst(cell1); |
||||
Relation relation = NULL; |
||||
Oid namespaceId; |
||||
|
||||
/* Get an ObjectAddress for the object. */ |
||||
address = get_object_address(stmt->removeType, |
||||
objname, NIL, |
||||
&relation, |
||||
AccessExclusiveLock, |
||||
stmt->missing_ok); |
||||
|
||||
/* Issue NOTICE if supplied object was not found. */ |
||||
if (!OidIsValid(address.objectId)) |
||||
{ |
||||
does_not_exist_skipping(stmt->removeType, objname); |
||||
continue; |
||||
} |
||||
|
||||
/* Check permissions. */ |
||||
namespaceId = get_object_namespace(&address); |
||||
if (!OidIsValid(namespaceId) || |
||||
!pg_namespace_ownercheck(namespaceId, GetUserId())) |
||||
check_object_ownership(GetUserId(), stmt->removeType, address, |
||||
objname, NIL, relation); |
||||
|
||||
/* Release any relcache reference count, but keep lock until commit. */ |
||||
if (relation) |
||||
heap_close(relation, NoLock); |
||||
|
||||
add_exact_object_address(&address, objects); |
||||
} |
||||
|
||||
/* Here we really delete them. */ |
||||
performMultipleDeletions(objects, stmt->behavior); |
||||
|
||||
free_object_addresses(objects); |
||||
} |
||||
|
||||
/*
|
||||
* Generate a NOTICE stating that the named object was not found, and is |
||||
* being skipped. This is only relevant when "IF EXISTS" is used; otherwise, |
||||
* get_object_address() will throw an ERROR. |
||||
*/ |
||||
static void |
||||
does_not_exist_skipping(ObjectType objtype, List *objname) |
||||
{ |
||||
const char *msg = NULL; |
||||
char *name = NULL; |
||||
|
||||
switch (objtype) |
||||
{ |
||||
case OBJECT_TYPE: |
||||
case OBJECT_DOMAIN: |
||||
msg = gettext_noop("type \"%s\" does not exist, skipping"); |
||||
name = TypeNameToString(makeTypeNameFromNameList(objname)); |
||||
break; |
||||
case OBJECT_COLLATION: |
||||
msg = gettext_noop("collation \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_CONVERSION: |
||||
msg = gettext_noop("conversion \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_SCHEMA: |
||||
msg = gettext_noop("schema \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_TSPARSER: |
||||
msg = gettext_noop("text search parser \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_TSDICTIONARY: |
||||
msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_TSTEMPLATE: |
||||
msg = gettext_noop("text search template \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_TSCONFIGURATION: |
||||
msg = gettext_noop("text search configuration \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
case OBJECT_EXTENSION: |
||||
msg = gettext_noop("extension \"%s\" does not exist, skipping"); |
||||
name = NameListToString(objname); |
||||
break; |
||||
default: |
||||
elog(ERROR, "unexpected object type (%d)", (int)objtype); |
||||
break; |
||||
} |
||||
|
||||
ereport(NOTICE, (errmsg(msg, name))); |
||||
} |
Loading…
Reference in new issue