Ther attached patch is for comment. It implements "drop if exists" as
has recently been discussed. Illustration:
andrew=# drop table blurflx;
ERROR: table "blurflx" does not exist
andrew=# drop table if exists blurflx;
DROP TABLE
andrew=# create table blurflx ( x text);
CREATE TABLE
andrew=# drop table if exists blurflx;
DROP TABLE
andrew=# drop table blurflx;
ERROR: table "blurflx" does not exist
andrew=#
If the patch is acceptable I will work up some documentation and
regression tests.
cheers
andrew
Index: src/backend/commands/conversioncmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v
retrieving revision 1.23
diff -c -r1.23 conversioncmds.c
*** src/backend/commands/conversioncmds.c 15 Oct 2005 02:49:15 -0000 1.23
--- src/backend/commands/conversioncmds.c 14 Nov 2005 14:09:52 -0000
***************
*** 98,113 ****
* DROP CONVERSION
*/
void
! DropConversionCommand(List *name, DropBehavior behavior)
{
Oid conversionOid;
conversionOid = FindConversionByName(name);
if (!OidIsValid(conversionOid))
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("conversion \"%s\" does not exist",
! NameListToString(name))));
ConversionDrop(conversionOid, behavior);
}
--- 98,118 ----
* DROP CONVERSION
*/
void
! DropConversionCommand(List *name, DropBehavior behavior, bool missing_ok)
{
Oid conversionOid;
conversionOid = FindConversionByName(name);
if (!OidIsValid(conversionOid))
! {
! if (missing_ok)
! return;
! else
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("conversion \"%s\" does not exist",
! NameListToString(name))));
! }
ConversionDrop(conversionOid, behavior);
}
Index: src/backend/commands/schemacmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v
retrieving revision 1.35
diff -c -r1.35 schemacmds.c
*** src/backend/commands/schemacmds.c 15 Oct 2005 02:49:15 -0000 1.35
--- src/backend/commands/schemacmds.c 14 Nov 2005 14:09:52 -0000
***************
*** 147,153 ****
* Removes a schema.
*/
void
! RemoveSchema(List *names, DropBehavior behavior)
{
char *namespaceName;
Oid namespaceId;
--- 147,153 ----
* Removes a schema.
*/
void
! RemoveSchema(List *names, DropBehavior behavior, bool missing_ok)
{
char *namespaceName;
Oid namespaceId;
***************
*** 163,171 ****
CStringGetDatum(namespaceName),
0, 0, 0);
if (!OidIsValid(namespaceId))
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_SCHEMA),
! errmsg("schema \"%s\" does not exist", namespaceName)));
/* Permission check */
if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
--- 163,176 ----
CStringGetDatum(namespaceName),
0, 0, 0);
if (!OidIsValid(namespaceId))
! {
! if (missing_ok)
! return;
! else
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_SCHEMA),
! errmsg("schema \"%s\" does not exist", namespaceName)));
! }
/* Permission check */
if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.82
diff -c -r1.82 typecmds.c
*** src/backend/commands/typecmds.c 18 Oct 2005 01:06:24 -0000 1.82
--- src/backend/commands/typecmds.c 14 Nov 2005 14:09:54 -0000
***************
*** 398,404 ****
* Removes a datatype.
*/
void
! RemoveType(List *names, DropBehavior behavior)
{
TypeName *typename;
Oid typeoid;
--- 398,404 ----
* Removes a datatype.
*/
void
! RemoveType(List *names, DropBehavior behavior, bool missing_ok)
{
TypeName *typename;
Oid typeoid;
***************
*** 414,423 ****
/* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("type \"%s\" does not exist",
! TypeNameToString(typename))));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
--- 414,428 ----
/* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
! {
! if (missing_ok)
! return;
! else
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("type \"%s\" does not exist",
! TypeNameToString(typename))));
! }
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
***************
*** 779,785 ****
* This is identical to RemoveType except we insist it be a domain.
*/
void
! RemoveDomain(List *names, DropBehavior behavior)
{
TypeName *typename;
Oid typeoid;
--- 784,790 ----
* 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;
***************
*** 796,805 ****
/* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("type \"%s\" does not exist",
! TypeNameToString(typename))));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
--- 801,815 ----
/* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
! {
! if (missing_ok)
! return;
! else
! ereport(ERROR,
! (errcode(ERRCODE_UNDEFINED_OBJECT),
! errmsg("type \"%s\" does not exist",
! TypeNameToString(typename))));
! }
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.511
diff -c -r2.511 gram.y
*** src/backend/parser/gram.y 23 Sep 2005 22:25:25 -0000 2.511
--- src/backend/parser/gram.y 14 Nov 2005 14:10:00 -0000
***************
*** 362,368 ****
HANDLER HAVING HEADER HOLD HOUR_P
! ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
INDEX INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
INTERVAL INTO INVOKER IS ISNULL ISOLATION
--- 362,368 ----
HANDLER HAVING HEADER HOLD HOUR_P
! IF ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
INDEX INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
INTERVAL INTO INVOKER IS ISNULL ISOLATION
***************
*** 2822,2837 ****
*
*****************************************************************************/
! DropStmt: DROP drop_type any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->objects = $3;
n->behavior = $4;
$$ = (Node *)n;
}
;
drop_type: TABLE { $$ = OBJECT_TABLE; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
| VIEW { $$ = OBJECT_VIEW; }
--- 2822,2848 ----
*
*****************************************************************************/
! DropStmt: DROP drop_type IF EXISTS any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
+ n->missing_ok = TRUE;
+ n->objects = $5;
+ n->behavior = $6;
+ $$ = (Node *)n;
+ }
+ | DROP drop_type any_name_list opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = $2;
+ n->missing_ok = FALSE;
n->objects = $3;
n->behavior = $4;
$$ = (Node *)n;
}
;
+
drop_type: TABLE { $$ = OBJECT_TABLE; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
| VIEW { $$ = OBJECT_VIEW; }
***************
*** 8149,8154 ****
--- 8160,8166 ----
| HEADER
| HOLD
| HOUR_P
+ | IF
| IMMEDIATE
| IMMUTABLE
| IMPLICIT_P
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.166
diff -c -r1.166 keywords.c
*** src/backend/parser/keywords.c 15 Oct 2005 02:49:22 -0000 1.166
--- src/backend/parser/keywords.c 14 Nov 2005 14:10:00 -0000
***************
*** 160,165 ****
--- 160,166 ----
{"header", HEADER},
{"hold", HOLD},
{"hour", HOUR_P},
+ {"if",IF},
{"ilike", ILIKE},
{"immediate", IMMEDIATE},
{"immutable", IMMUTABLE},
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.245
diff -c -r1.245 utility.c
*** src/backend/tcop/utility.c 15 Oct 2005 02:49:27 -0000 1.245
--- src/backend/tcop/utility.c 14 Nov 2005 14:10:00 -0000
***************
*** 147,154 ****
Assert(false); /* Should be impossible */
}
! static void
! CheckDropPermissions(RangeVar *rel, char rightkind)
{
Oid relOid;
HeapTuple tuple;
--- 147,161 ----
Assert(false); /* 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;
***************
*** 156,162 ****
relOid = RangeVarGetRelid(rel, true);
if (!OidIsValid(relOid))
! DropErrorMsgNonExistent(rel, rightkind);
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
--- 163,174 ----
relOid = RangeVarGetRelid(rel, true);
if (!OidIsValid(relOid))
! {
! if (!missing_ok)
! DropErrorMsgNonExistent(rel, rightkind);
! else
! return false;
! }
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
***************
*** 183,188 ****
--- 195,202 ----
rel->relname)));
ReleaseSysCache(tuple);
+
+ return true;
}
/*
***************
*** 528,558 ****
{
case OBJECT_TABLE:
rel = makeRangeVarFromNameList(names);
! CheckDropPermissions(rel, RELKIND_RELATION);
! RemoveRelation(rel, stmt->behavior);
break;
case OBJECT_SEQUENCE:
rel = makeRangeVarFromNameList(names);
! CheckDropPermissions(rel, RELKIND_SEQUENCE);
! RemoveRelation(rel, stmt->behavior);
break;
case OBJECT_VIEW:
rel = makeRangeVarFromNameList(names);
! CheckDropPermissions(rel, RELKIND_VIEW);
! RemoveView(rel, stmt->behavior);
break;
case OBJECT_INDEX:
rel = makeRangeVarFromNameList(names);
! CheckDropPermissions(rel, RELKIND_INDEX);
! RemoveIndex(rel, stmt->behavior);
break;
case OBJECT_TYPE:
/* RemoveType does its own permissions checks */
! RemoveType(names, stmt->behavior);
break;
case OBJECT_DOMAIN:
--- 542,577 ----
{
case OBJECT_TABLE:
rel = makeRangeVarFromNameList(names);
! if (CheckDropPermissions(rel, RELKIND_RELATION,
! stmt->missing_ok))
! RemoveRelation(rel, stmt->behavior);
break;
case OBJECT_SEQUENCE:
rel = makeRangeVarFromNameList(names);
! if (CheckDropPermissions(rel, RELKIND_SEQUENCE,
! stmt->missing_ok))
! RemoveRelation(rel, stmt->behavior);
break;
case OBJECT_VIEW:
rel = makeRangeVarFromNameList(names);
! if (CheckDropPermissions(rel, RELKIND_VIEW,
! stmt->missing_ok))
! RemoveView(rel, stmt->behavior);
break;
case OBJECT_INDEX:
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:
***************
*** 560,570 ****
/*
* RemoveDomain does its own permissions checks
*/
! RemoveDomain(names, stmt->behavior);
break;
case OBJECT_CONVERSION:
! DropConversionCommand(names, stmt->behavior);
break;
case OBJECT_SCHEMA:
--- 579,591 ----
/*
* 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:
***************
*** 572,578 ****
/*
* RemoveSchema does its own permissions checks
*/
! RemoveSchema(names, stmt->behavior);
break;
default:
--- 593,600 ----
/*
* RemoveSchema does its own permissions checks
*/
! RemoveSchema(names, stmt->behavior,
! stmt->missing_ok);
break;
default:
Index: src/include/commands/conversioncmds.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/conversioncmds.h,v
retrieving revision 1.10
diff -c -r1.10 conversioncmds.h
*** src/include/commands/conversioncmds.h 28 Jun 2005 05:09:12 -0000 1.10
--- src/include/commands/conversioncmds.h 14 Nov 2005 14:10:02 -0000
***************
*** 18,24 ****
#include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
! extern void DropConversionCommand(List *conversion_name, DropBehavior behavior);
extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId);
--- 18,25 ----
#include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
! extern void DropConversionCommand(List *conversion_name,
! DropBehavior behavior, bool missing_ok);
extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId);
Index: src/include/commands/schemacmds.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/schemacmds.h,v
retrieving revision 1.10
diff -c -r1.10 schemacmds.h
*** src/include/commands/schemacmds.h 28 Jun 2005 05:09:12 -0000 1.10
--- src/include/commands/schemacmds.h 14 Nov 2005 14:10:02 -0000
***************
*** 19,25 ****
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
! extern void RemoveSchema(List *names, DropBehavior behavior);
extern void RemoveSchemaById(Oid schemaOid);
extern void RenameSchema(const char *oldname, const char *newname);
--- 19,25 ----
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
! extern void RemoveSchema(List *names, DropBehavior behavior, bool missing_ok);
extern void RemoveSchemaById(Oid schemaOid);
extern void RenameSchema(const char *oldname, const char *newname);
Index: src/include/commands/typecmds.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/typecmds.h,v
retrieving revision 1.14
diff -c -r1.14 typecmds.h
*** src/include/commands/typecmds.h 15 Oct 2005 02:49:44 -0000 1.14
--- src/include/commands/typecmds.h 14 Nov 2005 14:10:02 -0000
***************
*** 20,29 ****
#define DEFAULT_TYPDELIM ','
extern void DefineType(List *names, List *parameters);
! extern void RemoveType(List *names, DropBehavior behavior);
extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt);
! extern void RemoveDomain(List *names, DropBehavior behavior);
extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
extern void AlterDomainDefault(List *names, Node *defaultRaw);
--- 20,29 ----
#define DEFAULT_TYPDELIM ','
extern void DefineType(List *names, List *parameters);
! extern void RemoveType(List *names, DropBehavior behavior, bool missing_ok);
extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt);
! extern void RemoveDomain(List *names, DropBehavior behavior, bool missing_ok);
extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
extern void AlterDomainDefault(List *names, Node *defaultRaw);
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.292
diff -c -r1.292 parsenodes.h
*** src/include/nodes/parsenodes.h 26 Oct 2005 19:21:55 -0000 1.292
--- src/include/nodes/parsenodes.h 14 Nov 2005 14:10:04 -0000
***************
*** 1278,1283 ****
--- 1278,1284 ----
List *objects; /* list of sublists of names (as Values) */
ObjectType removeType; /* object type */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+ bool missing_ok; /* skip error if object is missing? */
} DropStmt;
/* ----------------------
---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly