Commit 0cefb50f authored by Tom Lane's avatar Tom Lane

Refactor the handling of the various DropStmt variants so that when multiple

objects are specified, we drop them all in a single performMultipleDeletions
call.  This makes the RESTRICT/CASCADE checks more relaxed: it's not counted
as a cascade if one of the later objects has a dependency on an earlier one.
NOTICE messages about such cases go away, too.

In passing, fix the permissions check for DROP CONVERSION, which for some
reason was never made role-aware, and omitted the namespace-owner exemption
too.

Alex Hunsaker, with further fiddling by me.
parent 95ce4ee9
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.75 2008/06/11 21:53:48 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.76 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -259,6 +259,10 @@ performMultipleDeletions(const ObjectAddresses *objects, ...@@ -259,6 +259,10 @@ performMultipleDeletions(const ObjectAddresses *objects,
ObjectAddresses *targetObjects; ObjectAddresses *targetObjects;
int i; int i;
/* No work if no objects... */
if (objects->numrefs <= 0)
return;
/* /*
* We save some cycles by opening pg_depend just once and passing the * We save some cycles by opening pg_depend just once and passing the
* Relation pointer down to all the recursive deletion steps. * Relation pointer down to all the recursive deletion steps.
...@@ -295,11 +299,14 @@ performMultipleDeletions(const ObjectAddresses *objects, ...@@ -295,11 +299,14 @@ performMultipleDeletions(const ObjectAddresses *objects,
/* /*
* Check if deletion is allowed, and report about cascaded deletes. * Check if deletion is allowed, and report about cascaded deletes.
*
* If there's exactly one object being deleted, report it the same
* way as in performDeletion(), else we have to be vaguer.
*/ */
reportDependentObjects(targetObjects, reportDependentObjects(targetObjects,
behavior, behavior,
NOTICE, NOTICE,
NULL); (objects->numrefs == 1 ? objects->refs : NULL));
/* /*
* Delete all the objects in the proper order. * Delete all the objects in the proper order.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.43 2008/05/12 00:00:47 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.44 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "access/sysattr.h" #include "access/sysattr.h"
#include "catalog/dependency.h" #include "catalog/dependency.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_conversion.h" #include "catalog/pg_conversion.h"
#include "catalog/pg_conversion_fn.h" #include "catalog/pg_conversion_fn.h"
#include "catalog/pg_namespace.h" #include "catalog/pg_namespace.h"
...@@ -138,40 +137,6 @@ ConversionCreate(const char *conname, Oid connamespace, ...@@ -138,40 +137,6 @@ ConversionCreate(const char *conname, Oid connamespace,
return oid; return oid;
} }
/*
* ConversionDrop
*
* Drop a conversion after doing permission checks.
*/
void
ConversionDrop(Oid conversionOid, DropBehavior behavior)
{
HeapTuple tuple;
ObjectAddress object;
tuple = SearchSysCache(CONVOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
if (!superuser() &&
((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
NameStr(((Form_pg_conversion) GETSTRUCT(tuple))->conname));
ReleaseSysCache(tuple);
/*
* Do the deletion
*/
object.classId = ConversionRelationId;
object.objectId = conversionOid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
/* /*
* RemoveConversionById * RemoveConversionById
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.33 2008/03/27 03:57:33 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.34 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -99,31 +99,73 @@ CreateConversionCommand(CreateConversionStmt *stmt) ...@@ -99,31 +99,73 @@ CreateConversionCommand(CreateConversionStmt *stmt)
* DROP CONVERSION * DROP CONVERSION
*/ */
void void
DropConversionCommand(List *name, DropBehavior behavior, bool missing_ok) DropConversionsCommand(DropStmt *drop)
{ {
Oid conversionOid; ObjectAddresses *objects;
ListCell *cell;
conversionOid = FindConversionByName(name); /*
if (!OidIsValid(conversionOid)) * First we identify all the conversions, then we delete them in a single
* performMultipleDeletions() call. This is to avoid unwanted
* DROP RESTRICT errors if one of the conversions depends on another.
* (Not that that is very likely, but we may as well do this consistently.)
*/
objects = new_object_addresses();
foreach(cell, drop->objects)
{ {
if (!missing_ok) List *name = (List *) lfirst(cell);
{ Oid conversionOid;
ereport(ERROR, HeapTuple tuple;
(errcode(ERRCODE_UNDEFINED_OBJECT), Form_pg_conversion con;
errmsg("conversion \"%s\" does not exist", ObjectAddress object;
NameListToString(name))));
} conversionOid = FindConversionByName(name);
else
if (!OidIsValid(conversionOid))
{ {
ereport(NOTICE, if (!drop->missing_ok)
(errmsg("conversion \"%s\" does not exist, skipping", {
NameListToString(name)))); ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("conversion \"%s\" does not exist",
NameListToString(name))));
}
else
{
ereport(NOTICE,
(errmsg("conversion \"%s\" does not exist, skipping",
NameListToString(name))));
}
continue;
} }
return; tuple = SearchSysCache(CONVOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for conversion %u",
conversionOid);
con = (Form_pg_conversion) GETSTRUCT(tuple);
/* Permission check: must own conversion or its namespace */
if (!pg_conversion_ownercheck(conversionOid, GetUserId()) &&
!pg_namespace_ownercheck(con->connamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
NameStr(con->conname));
object.classId = ConversionRelationId;
object.objectId = conversionOid;
object.objectSubId = 0;
add_exact_object_address(&object, objects);
ReleaseSysCache(tuple);
} }
ConversionDrop(conversionOid, behavior); performMultipleDeletions(objects, drop->behavior);
free_object_addresses(objects);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.176 2008/05/12 20:01:59 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.177 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "access/transam.h" #include "access/transam.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h" #include "catalog/heap.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
...@@ -1256,33 +1255,6 @@ relationHasPrimaryKey(Relation rel) ...@@ -1256,33 +1255,6 @@ relationHasPrimaryKey(Relation rel)
return result; return result;
} }
/*
* RemoveIndex
* Deletes an index.
*/
void
RemoveIndex(RangeVar *relation, DropBehavior behavior)
{
Oid indOid;
char relkind;
ObjectAddress object;
indOid = RangeVarGetRelid(relation, false);
relkind = get_rel_relkind(indOid);
if (relkind != RELKIND_INDEX)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not an index",
relation->relname)));
object.classId = RelationRelationId;
object.objectId = indOid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
/* /*
* ReindexIndex * ReindexIndex
* Recreate a specific index. * Recreate a specific index.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.49 2008/01/03 21:23:15 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.50 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -148,57 +148,76 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) ...@@ -148,57 +148,76 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
/* /*
* RemoveSchema * RemoveSchemas
* Removes a schema. * Implements DROP SCHEMA.
*/ */
void void
RemoveSchema(List *names, DropBehavior behavior, bool missing_ok) RemoveSchemas(DropStmt *drop)
{ {
char *namespaceName; ObjectAddresses *objects;
Oid namespaceId; ListCell *cell;
ObjectAddress object;
if (list_length(names) != 1) /*
ereport(ERROR, * First we identify all the schemas, then we delete them in a single
(errcode(ERRCODE_SYNTAX_ERROR), * performMultipleDeletions() call. This is to avoid unwanted
errmsg("schema name cannot be qualified"))); * DROP RESTRICT errors if one of the schemas depends on another.
namespaceName = strVal(linitial(names)); */
objects = new_object_addresses();
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(namespaceName), foreach(cell, drop->objects)
0, 0, 0);
if (!OidIsValid(namespaceId))
{ {
if (!missing_ok) List *names = (List *) lfirst(cell);
{ char *namespaceName;
Oid namespaceId;
ObjectAddress object;
if (list_length(names) != 1)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("schema \"%s\" does not exist", namespaceName))); errmsg("schema name cannot be qualified")));
} namespaceName = strVal(linitial(names));
else
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(namespaceName),
0, 0, 0);
if (!OidIsValid(namespaceId))
{ {
ereport(NOTICE, if (!drop->missing_ok)
(errmsg("schema \"%s\" does not exist, skipping", {
namespaceName))); ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("schema \"%s\" does not exist",
namespaceName)));
}
else
{
ereport(NOTICE,
(errmsg("schema \"%s\" does not exist, skipping",
namespaceName)));
}
continue;
} }
return; /* Permission check */
} if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
namespaceName);
/* Permission check */ object.classId = NamespaceRelationId;
if (!pg_namespace_ownercheck(namespaceId, GetUserId())) object.objectId = namespaceId;
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, object.objectSubId = 0;
namespaceName);
add_exact_object_address(&object, objects);
}
/* /*
* Do the deletion. Objects contained in the schema are removed by means * Do the deletions. Objects contained in the schema(s) are removed by
* of their dependency links to the schema. * means of their dependency links to the schema.
*/ */
object.classId = NamespaceRelationId; performMultipleDeletions(objects, drop->behavior);
object.objectId = namespaceId;
object.objectSubId = 0;
performDeletion(&object, behavior); free_object_addresses(objects);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.255 2008/05/19 04:14:24 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.256 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "rewrite/rewriteDefine.h" #include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteHandler.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -168,6 +169,53 @@ typedef struct NewColumnValue ...@@ -168,6 +169,53 @@ typedef struct NewColumnValue
ExprState *exprstate; /* execution state */ ExprState *exprstate; /* execution state */
} NewColumnValue; } NewColumnValue;
/*
* Error-reporting support for RemoveRelations
*/
struct dropmsgstrings
{
char kind;
int nonexistent_code;
const char *nonexistent_msg;
const char *skipping_msg;
const char *nota_msg;
const char *drophint_msg;
};
static const struct dropmsgstrings dropmsgstringarray[] = {
{RELKIND_RELATION,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("table \"%s\" does not exist"),
gettext_noop("table \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a table"),
gettext_noop("Use DROP TABLE to remove a table.")},
{RELKIND_SEQUENCE,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("sequence \"%s\" does not exist"),
gettext_noop("sequence \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a sequence"),
gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
{RELKIND_VIEW,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("view \"%s\" does not exist"),
gettext_noop("view \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a view"),
gettext_noop("Use DROP VIEW to remove a view.")},
{RELKIND_INDEX,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("index \"%s\" does not exist"),
gettext_noop("index \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not an index"),
gettext_noop("Use DROP INDEX to remove an index.")},
{RELKIND_COMPOSITE_TYPE,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("type \"%s\" does not exist"),
gettext_noop("type \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a type"),
gettext_noop("Use DROP TYPE to remove a type.")},
{'\0', 0, NULL, NULL, NULL, NULL}
};
static void truncate_check_rel(Relation rel); static void truncate_check_rel(Relation rel);
static List *MergeAttributes(List *schema, List *supers, bool istemp, static List *MergeAttributes(List *schema, List *supers, bool istemp,
...@@ -497,22 +545,175 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -497,22 +545,175 @@ DefineRelation(CreateStmt *stmt, char relkind)
} }
/* /*
* RemoveRelation * Emit the right error or warning message for a "DROP" command issued on a
* Deletes a relation. * non-existent relation
*/
static void
DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok)
{
const struct dropmsgstrings *rentry;
for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
{
if (rentry->kind == rightkind)
{
if (!missing_ok)
{
ereport(ERROR,
(errcode(rentry->nonexistent_code),
errmsg(rentry->nonexistent_msg, relname)));
}
else
{
ereport(NOTICE, (errmsg(rentry->skipping_msg, relname)));
break;
}
}
}
Assert(rentry->kind != '\0'); /* Should be impossible */
}
/*
* Emit the right error message for a "DROP" command issued on a
* relation of the wrong type
*/
static void
DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
{
const struct dropmsgstrings *rentry;
const struct dropmsgstrings *wentry;
for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
if (rentry->kind == rightkind)
break;
Assert(rentry->kind != '\0');
for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
if (wentry->kind == wrongkind)
break;
/* wrongkind could be something we don't have in our table... */
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg(rentry->nota_msg, relname),
(wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
}
/*
* RemoveRelations
* Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW
*/ */
void void
RemoveRelation(const RangeVar *relation, DropBehavior behavior) RemoveRelations(DropStmt *drop)
{ {
Oid relOid; ObjectAddresses *objects;
ObjectAddress object; char relkind;
ListCell *cell;
relOid = RangeVarGetRelid(relation, false); /*
* First we identify all the relations, then we delete them in a single
* performMultipleDeletions() call. This is to avoid unwanted
* DROP RESTRICT errors if one of the relations depends on another.
*/
object.classId = RelationRelationId; /* Determine required relkind */
object.objectId = relOid; switch (drop->removeType)
object.objectSubId = 0; {
case OBJECT_TABLE:
relkind = RELKIND_RELATION;
break;
performDeletion(&object, behavior); case OBJECT_INDEX:
relkind = RELKIND_INDEX;
break;
case OBJECT_SEQUENCE:
relkind = RELKIND_SEQUENCE;
break;
case OBJECT_VIEW:
relkind = RELKIND_VIEW;
break;
default:
elog(ERROR, "unrecognized drop object type: %d",
(int) drop->removeType);
relkind = 0; /* keep compiler quiet */
break;
}
/* Lock and validate each relation; build a list of object addresses */
objects = new_object_addresses();
foreach(cell, drop->objects)
{
RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
Oid relOid;
HeapTuple tuple;
Form_pg_class classform;
ObjectAddress obj;
/*
* These next few steps are a great deal like relation_openrv, but we
* don't bother building a relcache entry since we don't need it.
*
* Check for shared-cache-inval messages before trying to access the
* relation. This is needed to cover the case where the name
* identifies a rel that has been dropped and recreated since the
* start of our transaction: if we don't flush the old syscache entry,
* then we'll latch onto that entry and suffer an error later.
*/
AcceptInvalidationMessages();
/* Look up the appropriate relation using namespace search */
relOid = RangeVarGetRelid(rel, true);
/* Not there? */
if (!OidIsValid(relOid))
{
DropErrorMsgNonExistent(rel->relname, relkind, drop->missing_ok);
continue;
}
/* Get the lock before trying to fetch the syscache entry */
LockRelationOid(relOid, AccessExclusiveLock);
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relOid);
classform = (Form_pg_class) GETSTRUCT(tuple);
if (classform->relkind != relkind)
DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
/* Allow DROP to either table owner or schema owner */
if (!pg_class_ownercheck(relOid, GetUserId()) &&
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
rel->relname);
if (!allowSystemTableMods && IsSystemClass(classform))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
rel->relname)));
/* OK, we're ready to delete this one */
obj.classId = RelationRelationId;
obj.objectId = relOid;
obj.objectSubId = 0;
add_exact_object_address(&obj, objects);
ReleaseSysCache(tuple);
}
performMultipleDeletions(objects, drop->behavior);
free_object_addresses(objects);
} }
/* /*
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.118 2008/05/09 23:32:04 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.119 2008/06/14 18:04:33 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -483,66 +483,93 @@ DefineType(List *names, List *parameters) ...@@ -483,66 +483,93 @@ DefineType(List *names, List *parameters)
/* /*
* RemoveType * RemoveTypes
* Removes a datatype. * Implements DROP TYPE and DROP DOMAIN
*
* Note: if DOMAIN is specified, we enforce that each type is a domain, but
* we don't enforce the converse for DROP TYPE
*/ */
void void
RemoveType(List *names, DropBehavior behavior, bool missing_ok) RemoveTypes(DropStmt *drop)
{ {
TypeName *typename; ObjectAddresses *objects;
Oid typeoid; ListCell *cell;
HeapTuple tup;
ObjectAddress object;
Form_pg_type typ;
/* Make a TypeName so we can use standard type lookup machinery */ /*
typename = makeTypeNameFromNameList(names); * First we identify all the types, then we delete them in a single
* performMultipleDeletions() call. This is to avoid unwanted
* DROP RESTRICT errors if one of the types depends on another.
*/
objects = new_object_addresses();
/* Use LookupTypeName here so that shell types can be removed. */ foreach(cell, drop->objects)
tup = LookupTypeName(NULL, typename, NULL);
if (tup == NULL)
{ {
if (!missing_ok) List *names = (List *) lfirst(cell);
TypeName *typename;
Oid typeoid;
HeapTuple tup;
ObjectAddress object;
Form_pg_type typ;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */
tup = LookupTypeName(NULL, typename, NULL);
if (tup == NULL)
{ {
ereport(ERROR, if (!drop->missing_ok)
(errcode(ERRCODE_UNDEFINED_OBJECT), {
errmsg("type \"%s\" does not exist", ereport(ERROR,
TypeNameToString(typename)))); (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typename))));
}
else
{
ereport(NOTICE,
(errmsg("type \"%s\" does not exist, skipping",
TypeNameToString(typename))));
}
continue;
} }
else
typeoid = typeTypeId(tup);
typ = (Form_pg_type) GETSTRUCT(tup);
/* Permission check: must own type or its namespace */
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!pg_namespace_ownercheck(typ->typnamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
TypeNameToString(typename));
if (drop->removeType == OBJECT_DOMAIN)
{ {
ereport(NOTICE, /* Check that this is actually a domain */
(errmsg("type \"%s\" does not exist, skipping", if (typ->typtype != TYPTYPE_DOMAIN)
TypeNameToString(typename)))); ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a domain",
TypeNameToString(typename))));
} }
return; /*
} * Note: we need no special check for array types here, as the normal
* treatment of internal dependencies handles it just fine
typeoid = typeTypeId(tup); */
typ = (Form_pg_type) GETSTRUCT(tup);
/* Permission check: must own type or its namespace */ object.classId = TypeRelationId;
if (!pg_type_ownercheck(typeoid, GetUserId()) && object.objectId = typeoid;
!pg_namespace_ownercheck(typ->typnamespace, GetUserId())) object.objectSubId = 0;
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
TypeNameToString(typename));
/* add_exact_object_address(&object, objects);
* Note: we need no special check for array types here, as the normal
* treatment of internal dependencies handles it just fine
*/
ReleaseSysCache(tup); ReleaseSysCache(tup);
}
/* performMultipleDeletions(objects, drop->behavior);
* Do the deletion
*/
object.classId = TypeRelationId;
object.objectId = typeoid;
object.objectSubId = 0;
performDeletion(&object, behavior); free_object_addresses(objects);
} }
...@@ -923,75 +950,6 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -923,75 +950,6 @@ DefineDomain(CreateDomainStmt *stmt)
} }
/*
* RemoveDomain
* Removes a domain.
*
* This is identical to RemoveType except we insist it be a domain.
*/
void
RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
{
TypeName *typename;
Oid typeoid;
HeapTuple tup;
char typtype;
ObjectAddress object;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */
tup = LookupTypeName(NULL, typename, NULL);
if (tup == NULL)
{
if (!missing_ok)
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typename))));
}
else
{
ereport(NOTICE,
(errmsg("type \"%s\" does not exist, skipping",
TypeNameToString(typename))));
}
return;
}
typeoid = typeTypeId(tup);
/* Permission check: must own type or its namespace */
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
TypeNameToString(typename));
/* Check that this is actually a domain */
typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
if (typtype != TYPTYPE_DOMAIN)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a domain",
TypeNameToString(typename))));
ReleaseSysCache(tup);
/*
* Do the deletion
*/
object.classId = TypeRelationId;
object.objectId = typeoid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
/* /*
* DefineEnum * DefineEnum
* Registers a new enum. * Registers a new enum.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.104 2008/01/01 19:45:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.105 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "access/heapam.h" #include "access/heapam.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
...@@ -446,26 +445,3 @@ DefineView(ViewStmt *stmt, const char *queryString) ...@@ -446,26 +445,3 @@ DefineView(ViewStmt *stmt, const char *queryString)
*/ */
DefineViewRules(viewOid, viewParse, stmt->replace); DefineViewRules(viewOid, viewParse, stmt->replace);
} }
/*
* RemoveView
*
* Remove a view given its name
*
* We just have to drop the relation; the associated rules will be
* cleaned up automatically.
*/
void
RemoveView(const RangeVar *view, DropBehavior behavior)
{
Oid viewOid;
ObjectAddress object;
viewOid = RangeVarGetRelid(view, false);
object.classId = RelationRelationId;
object.objectId = viewOid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.292 2008/06/05 15:47:32 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.293 2008/06/14 18:04:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -57,161 +57,6 @@ ...@@ -57,161 +57,6 @@
#include "utils/syscache.h" #include "utils/syscache.h"
/*
* Error-checking support for DROP commands
*/
struct msgstrings
{
char kind;
int nonexistent_code;
const char *nonexistent_msg;
const char *skipping_msg;
const char *nota_msg;
const char *drophint_msg;
};
static const struct msgstrings msgstringarray[] = {
{RELKIND_RELATION,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("table \"%s\" does not exist"),
gettext_noop("table \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a table"),
gettext_noop("Use DROP TABLE to remove a table.")},
{RELKIND_SEQUENCE,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("sequence \"%s\" does not exist"),
gettext_noop("sequence \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a sequence"),
gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
{RELKIND_VIEW,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("view \"%s\" does not exist"),
gettext_noop("view \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a view"),
gettext_noop("Use DROP VIEW to remove a view.")},
{RELKIND_INDEX,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("index \"%s\" does not exist"),
gettext_noop("index \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not an index"),
gettext_noop("Use DROP INDEX to remove an index.")},
{RELKIND_COMPOSITE_TYPE,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("type \"%s\" does not exist"),
gettext_noop("type \"%s\" does not exist, skipping"),
gettext_noop("\"%s\" is not a type"),
gettext_noop("Use DROP TYPE to remove a type.")},
{'\0', 0, NULL, NULL, NULL}
};
/*
* Emit the right error message for a "DROP" command issued on a
* relation of the wrong type
*/
static void
DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
{
const struct msgstrings *rentry;
const struct msgstrings *wentry;
for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
if (rentry->kind == rightkind)
break;
Assert(rentry->kind != '\0');
for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
if (wentry->kind == wrongkind)
break;
/* wrongkind could be something we don't have in our table... */
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg(rentry->nota_msg, relname),
(wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
}
/*
* Emit the right error message for a "DROP" command issued on a
* non-existent relation
*/
static void
DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
{
const struct msgstrings *rentry;
for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
{
if (rentry->kind == rightkind)
{
if (!missing_ok)
{
ereport(ERROR,
(errcode(rentry->nonexistent_code),
errmsg(rentry->nonexistent_msg, rel->relname)));
}
else
{
ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
break;
}
}
}
Assert(rentry->kind != '\0'); /* Should be impossible */
}
/*
* returns false if missing_ok is true and the object does not exist,
* true if object exists and permissions are OK,
* errors otherwise
*
*/
static bool
CheckDropPermissions(RangeVar *rel, char rightkind, bool missing_ok)
{
Oid relOid;
HeapTuple tuple;
Form_pg_class classform;
relOid = RangeVarGetRelid(rel, true);
if (!OidIsValid(relOid))
{
DropErrorMsgNonExistent(rel, rightkind, missing_ok);
return false;
}
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relOid);
classform = (Form_pg_class) GETSTRUCT(tuple);
if (classform->relkind != rightkind)
DropErrorMsgWrongType(rel->relname, classform->relkind,
rightkind);
/* Allow DROP to either table owner or schema owner */
if (!pg_class_ownercheck(relOid, GetUserId()) &&
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
rel->relname);
if (!allowSystemTableMods && IsSystemClass(classform))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
rel->relname)));
ReleaseSysCache(tuple);
return true;
}
/* /*
* Verify user has ownership of specified relation, else ereport. * Verify user has ownership of specified relation, else ereport.
* *
...@@ -603,96 +448,49 @@ ProcessUtility(Node *parsetree, ...@@ -603,96 +448,49 @@ ProcessUtility(Node *parsetree,
case T_DropStmt: case T_DropStmt:
{ {
DropStmt *stmt = (DropStmt *) parsetree; DropStmt *stmt = (DropStmt *) parsetree;
ListCell *arg;
foreach(arg, stmt->objects) switch (stmt->removeType)
{ {
List *names = (List *) lfirst(arg); case OBJECT_TABLE:
RangeVar *rel; case OBJECT_SEQUENCE:
case OBJECT_VIEW:
case OBJECT_INDEX:
RemoveRelations(stmt);
break;
switch (stmt->removeType) case OBJECT_TYPE:
{ case OBJECT_DOMAIN:
case OBJECT_TABLE: RemoveTypes(stmt);
rel = makeRangeVarFromNameList(names); break;
if (CheckDropPermissions(rel, RELKIND_RELATION,
stmt->missing_ok)) case OBJECT_CONVERSION:
RemoveRelation(rel, stmt->behavior); DropConversionsCommand(stmt);
break; break;
case OBJECT_SEQUENCE: case OBJECT_SCHEMA:
rel = makeRangeVarFromNameList(names); RemoveSchemas(stmt);
if (CheckDropPermissions(rel, RELKIND_SEQUENCE, break;
stmt->missing_ok))
RemoveRelation(rel, stmt->behavior); case OBJECT_TSPARSER:
break; RemoveTSParsers(stmt);
break;
case OBJECT_VIEW:
rel = makeRangeVarFromNameList(names); case OBJECT_TSDICTIONARY:
if (CheckDropPermissions(rel, RELKIND_VIEW, RemoveTSDictionaries(stmt);
stmt->missing_ok)) break;
RemoveView(rel, stmt->behavior);
break; case OBJECT_TSTEMPLATE:
RemoveTSTemplates(stmt);
case OBJECT_INDEX: break;
rel = makeRangeVarFromNameList(names);
if (CheckDropPermissions(rel, RELKIND_INDEX,
stmt->missing_ok))
RemoveIndex(rel, stmt->behavior);
break;
case OBJECT_TYPE:
/* RemoveType does its own permissions checks */
RemoveType(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_DOMAIN:
/* RemoveDomain does its own permissions checks */
RemoveDomain(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_CONVERSION:
DropConversionCommand(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_SCHEMA:
/* RemoveSchema does its own permissions checks */
RemoveSchema(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSPARSER:
RemoveTSParser(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSDICTIONARY:
RemoveTSDictionary(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSTEMPLATE:
RemoveTSTemplate(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSCONFIGURATION:
RemoveTSConfiguration(names, stmt->behavior,
stmt->missing_ok);
break;
default:
elog(ERROR, "unrecognized drop object type: %d",
(int) stmt->removeType);
break;
}
/* case OBJECT_TSCONFIGURATION:
* We used to need to do CommandCounterIncrement() here, RemoveTSConfigurations(stmt);
* but now it's done inside performDeletion(). break;
*/
default:
elog(ERROR, "unrecognized drop object type: %d",
(int) stmt->removeType);
break;
} }
} }
break; break;
......
...@@ -7,20 +7,17 @@ ...@@ -7,20 +7,17 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_conversion_fn.h,v 1.1 2008/03/27 03:57:34 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_conversion_fn.h,v 1.2 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PG_CONVERSION_FN_H #ifndef PG_CONVERSION_FN_H
#define PG_CONVERSION_FN_H #define PG_CONVERSION_FN_H
#include "nodes/parsenodes.h"
extern Oid ConversionCreate(const char *conname, Oid connamespace, extern Oid ConversionCreate(const char *conname, Oid connamespace,
Oid conowner, Oid conowner,
int32 conforencoding, int32 contoencoding, int32 conforencoding, int32 contoencoding,
Oid conproc, bool def); Oid conproc, bool def);
extern void ConversionDrop(Oid conversionOid, DropBehavior behavior);
extern void RemoveConversionById(Oid conversionOid); extern void RemoveConversionById(Oid conversionOid);
extern Oid FindConversion(const char *conname, Oid connamespace); extern Oid FindConversion(const char *conname, Oid connamespace);
extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding, int32 to_encoding); extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding, int32 to_encoding);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.16 2008/01/01 19:45:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.17 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,8 +18,7 @@ ...@@ -18,8 +18,7 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree); extern void CreateConversionCommand(CreateConversionStmt *parsetree);
extern void DropConversionCommand(List *conversion_name, extern void DropConversionsCommand(DropStmt *drop);
DropBehavior behavior, bool missing_ok);
extern void RenameConversion(List *name, const char *newname); extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId); extern void AlterConversionOwner(List *name, Oid newOwnerId);
extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId); extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.88 2008/01/01 19:45:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.89 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -34,7 +34,6 @@ extern void DefineIndex(RangeVar *heapRelation, ...@@ -34,7 +34,6 @@ extern void DefineIndex(RangeVar *heapRelation,
bool skip_build, bool skip_build,
bool quiet, bool quiet,
bool concurrent); bool concurrent);
extern void RemoveIndex(RangeVar *relation, DropBehavior behavior);
extern void ReindexIndex(RangeVar *indexRelation); extern void ReindexIndex(RangeVar *indexRelation);
extern void ReindexTable(RangeVar *relation); extern void ReindexTable(RangeVar *relation);
extern void ReindexDatabase(const char *databaseName, extern void ReindexDatabase(const char *databaseName,
...@@ -94,28 +93,24 @@ extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwn ...@@ -94,28 +93,24 @@ extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwn
/* commands/tsearchcmds.c */ /* commands/tsearchcmds.c */
extern void DefineTSParser(List *names, List *parameters); extern void DefineTSParser(List *names, List *parameters);
extern void RenameTSParser(List *oldname, const char *newname); extern void RenameTSParser(List *oldname, const char *newname);
extern void RemoveTSParser(List *names, DropBehavior behavior, extern void RemoveTSParsers(DropStmt *drop);
bool missing_ok);
extern void RemoveTSParserById(Oid prsId); extern void RemoveTSParserById(Oid prsId);
extern void DefineTSDictionary(List *names, List *parameters); extern void DefineTSDictionary(List *names, List *parameters);
extern void RenameTSDictionary(List *oldname, const char *newname); extern void RenameTSDictionary(List *oldname, const char *newname);
extern void RemoveTSDictionary(List *names, DropBehavior behavior, extern void RemoveTSDictionaries(DropStmt *drop);
bool missing_ok);
extern void RemoveTSDictionaryById(Oid dictId); extern void RemoveTSDictionaryById(Oid dictId);
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt); extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId); extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
extern void DefineTSTemplate(List *names, List *parameters); extern void DefineTSTemplate(List *names, List *parameters);
extern void RenameTSTemplate(List *oldname, const char *newname); extern void RenameTSTemplate(List *oldname, const char *newname);
extern void RemoveTSTemplate(List *names, DropBehavior behavior, extern void RemoveTSTemplates(DropStmt *stmt);
bool missing_ok);
extern void RemoveTSTemplateById(Oid tmplId); extern void RemoveTSTemplateById(Oid tmplId);
extern void DefineTSConfiguration(List *names, List *parameters); extern void DefineTSConfiguration(List *names, List *parameters);
extern void RenameTSConfiguration(List *oldname, const char *newname); extern void RenameTSConfiguration(List *oldname, const char *newname);
extern void RemoveTSConfiguration(List *names, DropBehavior behavior, extern void RemoveTSConfigurations(DropStmt *stmt);
bool missing_ok);
extern void RemoveTSConfigurationById(Oid cfgId); extern void RemoveTSConfigurationById(Oid cfgId);
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt); extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId); extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.18 2008/01/01 19:45:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.19 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree, extern void CreateSchemaCommand(CreateSchemaStmt *parsetree,
const char *queryString); const char *queryString);
extern void RemoveSchema(List *names, DropBehavior behavior, bool missing_ok); extern void RemoveSchemas(DropStmt *drop);
extern void RemoveSchemaById(Oid schemaOid); extern void RemoveSchemaById(Oid schemaOid);
extern void RenameSchema(const char *oldname, const char *newname); extern void RenameSchema(const char *oldname, const char *newname);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.38 2008/03/19 18:38:30 tgl Exp $ * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.39 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
extern Oid DefineRelation(CreateStmt *stmt, char relkind); extern Oid DefineRelation(CreateStmt *stmt, char relkind);
extern void RemoveRelation(const RangeVar *relation, DropBehavior behavior); extern void RemoveRelations(DropStmt *drop);
extern void AlterTable(AlterTableStmt *stmt); extern void AlterTable(AlterTableStmt *stmt);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.23 2008/03/19 18:38:30 tgl Exp $ * $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.24 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,10 +20,9 @@ ...@@ -20,10 +20,9 @@
#define DEFAULT_TYPDELIM ',' #define DEFAULT_TYPDELIM ','
extern void DefineType(List *names, List *parameters); extern void DefineType(List *names, List *parameters);
extern void RemoveType(List *names, DropBehavior behavior, bool missing_ok); extern void RemoveTypes(DropStmt *drop);
extern void RemoveTypeById(Oid typeOid); extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt); extern void DefineDomain(CreateDomainStmt *stmt);
extern void RemoveDomain(List *names, DropBehavior behavior, bool missing_ok);
extern void DefineEnum(CreateEnumStmt *stmt); extern void DefineEnum(CreateEnumStmt *stmt);
extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist); extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/view.h,v 1.26 2008/01/01 19:45:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/view.h,v 1.27 2008/06/14 18:04:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -17,6 +17,5 @@ ...@@ -17,6 +17,5 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
extern void DefineView(ViewStmt *stmt, const char *queryString); extern void DefineView(ViewStmt *stmt, const char *queryString);
extern void RemoveView(const RangeVar *view, DropBehavior behavior);
#endif /* VIEW_H */ #endif /* VIEW_H */
...@@ -1086,8 +1086,7 @@ INSERT INTO fktable VALUES (100, 200); ...@@ -1086,8 +1086,7 @@ INSERT INTO fktable VALUES (100, 200);
COMMIT; COMMIT;
ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey" ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey"
DETAIL: Key (fk)=(200) is not present in table "pktable". DETAIL: Key (fk)=(200) is not present in table "pktable".
DROP TABLE pktable, fktable CASCADE; DROP TABLE pktable, fktable;
NOTICE: drop cascades to constraint fktable_fk_fkey on table fktable
-- test notice about expensive referential integrity checks, -- test notice about expensive referential integrity checks,
-- where the index cannot be used because of type incompatibilities. -- where the index cannot be used because of type incompatibilities.
CREATE TEMP TABLE pktable ( CREATE TEMP TABLE pktable (
...@@ -1156,17 +1155,7 @@ ALTER TABLE fktable ADD CONSTRAINT fk_241_132 ...@@ -1156,17 +1155,7 @@ ALTER TABLE fktable ADD CONSTRAINT fk_241_132
FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2); FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2);
ERROR: foreign key constraint "fk_241_132" cannot be implemented ERROR: foreign key constraint "fk_241_132" cannot be implemented
DETAIL: Key columns "x2" and "id1" are of incompatible types: character varying and integer. DETAIL: Key columns "x2" and "id1" are of incompatible types: character varying and integer.
DROP TABLE pktable, fktable CASCADE; DROP TABLE pktable, fktable;
NOTICE: drop cascades to 9 other objects
DETAIL: drop cascades to constraint fktable_x3_fkey on table fktable
drop cascades to constraint fk_1_3 on table fktable
drop cascades to constraint fktable_x2_fkey on table fktable
drop cascades to constraint fk_4_2 on table fktable
drop cascades to constraint fktable_x1_fkey on table fktable
drop cascades to constraint fk_5_1 on table fktable
drop cascades to constraint fk_123_123 on table fktable
drop cascades to constraint fk_213_213 on table fktable
drop cascades to constraint fk_253_213 on table fktable
-- test a tricky case: we can elide firing the FK check trigger during -- test a tricky case: we can elide firing the FK check trigger during
-- an UPDATE if the UPDATE did not change the foreign key -- an UPDATE if the UPDATE did not change the foreign key
-- field. However, we can't do this if our transaction was the one that -- field. However, we can't do this if our transaction was the one that
......
...@@ -141,12 +141,6 @@ SELECT * FROM trunc_e; ...@@ -141,12 +141,6 @@ SELECT * FROM trunc_e;
(0 rows) (0 rows)
DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE; DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to constraint trunc_b_a_fkey on table trunc_b
drop cascades to constraint trunc_e_a_fkey on table trunc_e
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to constraint trunc_d_a_fkey on table trunc_d
drop cascades to constraint trunc_e_b_fkey on table trunc_e
-- Test ON TRUNCATE triggers -- Test ON TRUNCATE triggers
CREATE TABLE trunc_trigger_test (f1 int, f2 text, f3 text); CREATE TABLE trunc_trigger_test (f1 int, f2 text, f3 text);
CREATE TABLE trunc_trigger_log (tgop text, tglevel text, tgwhen text, CREATE TABLE trunc_trigger_log (tgop text, tglevel text, tgwhen text,
......
...@@ -724,7 +724,7 @@ INSERT INTO fktable VALUES (100, 200); ...@@ -724,7 +724,7 @@ INSERT INTO fktable VALUES (100, 200);
-- error here on commit -- error here on commit
COMMIT; COMMIT;
DROP TABLE pktable, fktable CASCADE; DROP TABLE pktable, fktable;
-- test notice about expensive referential integrity checks, -- test notice about expensive referential integrity checks,
-- where the index cannot be used because of type incompatibilities. -- where the index cannot be used because of type incompatibilities.
...@@ -799,7 +799,7 @@ FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1); ...@@ -799,7 +799,7 @@ FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1);
ALTER TABLE fktable ADD CONSTRAINT fk_241_132 ALTER TABLE fktable ADD CONSTRAINT fk_241_132
FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2); FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2);
DROP TABLE pktable, fktable CASCADE; DROP TABLE pktable, fktable;
-- test a tricky case: we can elide firing the FK check trigger during -- test a tricky case: we can elide firing the FK check trigger during
-- an UPDATE if the UPDATE did not change the foreign key -- an UPDATE if the UPDATE did not change the foreign key
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment