diff --git a/doc/src/sgml/ref/drop_table.sgml b/doc/src/sgml/ref/drop_table.sgml
index 7e0b85d6af..5f5a7aa821 100644
--- a/doc/src/sgml/ref/drop_table.sgml
+++ b/doc/src/sgml/ref/drop_table.sgml
@@ -1,5 +1,5 @@
@@ -39,7 +39,7 @@ DROP TABLE name [, ...]
name
- The name of an existing table or view to drop.
+ The name of an existing table to drop.
@@ -68,11 +68,11 @@ DROP
-ERROR Relation "name" Does Not Exist!
+ERROR: table "name" is nonexistent
- If the specified table or view does not exist in the database.
+ If the specified table does not exist in the database.
@@ -89,8 +89,8 @@ ERROR Relation "name" Does Not Exis
Description
- DROP TABLE removes tables and views from the database.
- Only its owner may destroy a table or view. A table
+ DROP TABLE removes tables from the database.
+ Only its owner may destroy a table. A table
may be emptied of rows, but not destroyed, by using DELETE.
diff --git a/doc/src/sgml/ref/drop_view.sgml b/doc/src/sgml/ref/drop_view.sgml
index 7d08cbf485..636d18151d 100644
--- a/doc/src/sgml/ref/drop_view.sgml
+++ b/doc/src/sgml/ref/drop_view.sgml
@@ -1,5 +1,5 @@
@@ -23,7 +23,7 @@ Postgres documentation
1999-07-20
-DROP VIEW name
+DROP VIEW name [, ...]
@@ -70,7 +70,7 @@ DROP
-ERROR: RewriteGetRuleEventRel: rule "_RETname" not found
+ERROR: view name is nonexistent
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index e768d0bd79..3d740533ff 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.125 2000/10/07 00:58:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.126 2000/10/18 16:16:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1949,8 +1949,8 @@ _copyDropStmt(DropStmt *from)
{
DropStmt *newnode = makeNode(DropStmt);
- Node_Copy(from, newnode, relNames);
- newnode->sequence = from->sequence;
+ Node_Copy(from, newnode, names);
+ newnode->removeType = from->removeType;
return newnode;
}
@@ -2071,17 +2071,6 @@ _copyRemoveOperStmt(RemoveOperStmt *from)
return newnode;
}
-static RemoveStmt *
-_copyRemoveStmt(RemoveStmt *from)
-{
- RemoveStmt *newnode = makeNode(RemoveStmt);
-
- newnode->removeType = from->removeType;
- newnode->name = pstrdup(from->name);
-
- return newnode;
-}
-
static RenameStmt *
_copyRenameStmt(RenameStmt *from)
{
@@ -2782,9 +2771,6 @@ copyObject(void *from)
case T_RemoveOperStmt:
retval = _copyRemoveOperStmt(from);
break;
- case T_RemoveStmt:
- retval = _copyRemoveStmt(from);
- break;
case T_RenameStmt:
retval = _copyRenameStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index d5b2ff4607..372f22499d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.76 2000/10/07 00:58:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.77 2000/10/18 16:16:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -850,9 +850,9 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
static bool
_equalDropStmt(DropStmt *a, DropStmt *b)
{
- if (!equal(a->relNames, b->relNames))
+ if (!equal(a->names, b->names))
return false;
- if (a->sequence != b->sequence)
+ if (a->removeType != b->removeType)
return false;
return true;
@@ -989,16 +989,6 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
return true;
}
-static bool
-_equalRemoveStmt(RemoveStmt *a, RemoveStmt *b)
-{
- if (a->removeType != b->removeType)
- return false;
- if (!equalstr(a->name, b->name))
- return false;
-
- return true;
-}
static bool
_equalRenameStmt(RenameStmt *a, RenameStmt *b)
@@ -1959,9 +1949,6 @@ equal(void *a, void *b)
case T_RemoveOperStmt:
retval = _equalRemoveOperStmt(a, b);
break;
- case T_RemoveStmt:
- retval = _equalRemoveStmt(a, b);
- break;
case T_RenameStmt:
retval = _equalRenameStmt(a, b);
break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a596bd6aba..fbda275803 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.195 2000/10/07 00:58:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.196 2000/10/18 16:16:05 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -1942,15 +1942,22 @@ def_arg: func_return { $$ = (Node *)$1; }
DropStmt: DROP TABLE relation_name_list
{
DropStmt *n = makeNode(DropStmt);
- n->relNames = $3;
- n->sequence = FALSE;
+ n->names = $3;
+ n->removeType = DROP_TABLE;
$$ = (Node *)n;
}
| DROP SEQUENCE relation_name_list
{
DropStmt *n = makeNode(DropStmt);
- n->relNames = $3;
- n->sequence = TRUE;
+ n->names = $3;
+ n->removeType = DROP_SEQUENCE;
+ $$ = (Node *)n;
+ }
+ | DROP VIEW relation_name_list
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->names = $3;
+ n->removeType = DROP_VIEW;
$$ = (Node *)n;
}
;
@@ -2558,17 +2565,16 @@ func_return: Typename
RemoveStmt: DROP remove_type name
{
- RemoveStmt *n = makeNode(RemoveStmt);
+ DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
- n->name = $3;
+ n->names = makeList1(makeString($3));
$$ = (Node *)n;
}
;
-remove_type: TYPE_P { $$ = TYPE_P; }
- | INDEX { $$ = INDEX; }
- | RULE { $$ = RULE; }
- | VIEW { $$ = VIEW; }
+remove_type: TYPE_P { $$ = DROP_TYPE_P; }
+ | INDEX { $$ = DROP_INDEX; }
+ | RULE { $$ = DROP_RULE; }
;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 6c0b2be5ea..d63a5c6b7e 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.96 2000/10/16 17:08:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.97 2000/10/18 16:16:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -46,6 +46,71 @@
#include "utils/syscache.h"
+/*
+ *
+ */
+
+struct kindstrings {
+ char kind;
+ char *name;
+ char *command;
+};
+
+static struct kindstrings kindstringarray[] = {
+ { RELKIND_RELATION, "table", "TABLE" },
+ { RELKIND_SEQUENCE, "sequence", "SEQUENCE" },
+ { RELKIND_VIEW, "view", "VIEW" },
+ { RELKIND_INDEX, "index", "INDEX" },
+ { '\0', "", "" }
+};
+
+
+static void
+DropErrorMsg(char* relname, char wrongkind, char rightkind)
+{
+ struct kindstrings *rentry;
+ struct kindstrings *wentry;
+
+ for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
+ if (rentry->kind == rightkind)
+ break;
+ Assert(rentry->kind != '\0');
+
+ for (wentry = kindstringarray; wentry->kind != '\0'; wentry++)
+ if (wentry->kind == wrongkind)
+ break;
+ Assert(wentry->kind != '\0');
+
+ elog(ERROR, "%s is not a %s. Use 'DROP %s' to remove a %s",
+ relname, rentry->name, wentry->command, wentry->name);
+}
+
+static void
+CheckClassKind(char *name, char rightkind)
+{
+ HeapTuple tuple;
+ struct kindstrings *rentry;
+ Form_pg_class classform;
+
+ tuple = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(name),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tuple))
+ {
+ for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
+ if (rentry->kind == rightkind)
+ break;
+ Assert(rentry->kind != '\0');
+ elog(ERROR, "%s \"%s\" is nonexistent", rentry->name, name);
+ }
+
+ classform = (Form_pg_class) GETSTRUCT(tuple);
+
+ if (classform->relkind != rightkind)
+ DropErrorMsg(name, classform->relkind, rightkind);
+}
+
/* ----------------
* general utility function invoker
* ----------------
@@ -149,41 +214,76 @@ ProcessUtility(Node *parsetree,
case T_DropStmt:
{
DropStmt *stmt = (DropStmt *) parsetree;
- List *args = stmt->relNames;
+ List *args = stmt->names;
List *arg;
- set_ps_display(commandTag = "DROP");
-
- /* check as much as we can before we start dropping ... */
- foreach(arg, args)
- {
- Relation rel;
+ foreach(arg, args) {
relname = strVal(lfirst(arg));
if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "class \"%s\" is a system catalog",
relname);
- rel = heap_openr(relname, AccessExclusiveLock);
- if (stmt->sequence &&
- rel->rd_rel->relkind != RELKIND_SEQUENCE)
- elog(ERROR, "Use DROP TABLE to drop table '%s'",
- relname);
- if (!(stmt->sequence) &&
- rel->rd_rel->relkind == RELKIND_SEQUENCE)
- elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
- relname);
- /* close rel, but keep lock until end of xact */
- heap_close(rel, NoLock);
- if (!pg_ownercheck(GetUserId(), relname, RELNAME))
- elog(ERROR, "you do not own class \"%s\"",
- relname);
- }
- /* OK, terminate 'em all */
- foreach(arg, args)
- {
- relname = strVal(lfirst(arg));
- RemoveRelation(relname);
+
+ set_ps_display(commandTag = "DROP");
+
+ switch(stmt->removeType)
+ {
+ case DROP_TABLE:
+ CheckClassKind(relname, RELKIND_RELATION);
+ if (!pg_ownercheck(GetUserId(), relname, RELNAME))
+ elog(ERROR, "you do not own table \"%s\"",
+ relname);
+ RemoveRelation(relname);
+
+ break;
+
+ case DROP_SEQUENCE:
+ CheckClassKind(relname, RELKIND_SEQUENCE);
+ if (!pg_ownercheck(GetUserId(), relname, RELNAME))
+ elog(ERROR, "you do not own sequence \"%s\"",
+ relname);
+ RemoveRelation(relname);
+
+ break;
+
+ case DROP_VIEW:
+ CheckClassKind(relname, RELKIND_VIEW);
+ if (!pg_ownercheck(GetUserId(), relname, RELNAME))
+ elog(ERROR, "you do not own view \"%s\"",
+ relname);
+ RemoveView(relname);
+
+ break;
+
+ case DROP_INDEX:
+ CheckClassKind(relname, RELKIND_INDEX);
+ if (!pg_ownercheck(GetUserId(), relname, RELNAME))
+ elog(ERROR, "%s: %s", relname,
+ aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+ RemoveIndex(relname);
+
+ break;
+
+ case DROP_RULE:
+ {
+ char *rulename = relname;
+ int aclcheck_result;
+
+ relationName = RewriteGetRuleEventRel(rulename);
+ aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RU);
+ if (aclcheck_result != ACLCHECK_OK)
+ elog(ERROR, "%s: %s", relationName,
+ aclcheck_error_strings[aclcheck_result]);
+ RemoveRewriteRule(rulename);
+ }
+ break;
+
+ case DROP_TYPE_P:
+ RemoveType(relname);
+ break;
+ }
}
+
}
break;
@@ -452,57 +552,6 @@ ProcessUtility(Node *parsetree,
}
break;
- case T_RemoveStmt:
- {
- RemoveStmt *stmt = (RemoveStmt *) parsetree;
-
- set_ps_display(commandTag = "DROP");
-
- switch (stmt->removeType)
- {
- case INDEX:
- relname = stmt->name;
- if (!allowSystemTableMods && IsSystemRelationName(relname))
- elog(ERROR, "class \"%s\" is a system catalog index",
- relname);
- if (!pg_ownercheck(GetUserId(), relname, RELNAME))
- elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
- RemoveIndex(relname);
- break;
- case RULE:
- {
- char *rulename = stmt->name;
- int aclcheck_result;
-
- relationName = RewriteGetRuleEventRel(rulename);
- aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RU);
- if (aclcheck_result != ACLCHECK_OK)
- elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
- RemoveRewriteRule(rulename);
- }
- break;
- case TYPE_P:
- /* XXX moved to remove.c */
- RemoveType(stmt->name);
- break;
- case VIEW:
- {
- char *viewName = stmt->name;
- char *ruleName;
-
- ruleName = MakeRetrieveViewRuleName(viewName);
- relationName = RewriteGetRuleEventRel(ruleName);
- if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
- elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
- pfree(ruleName);
- RemoveView(viewName);
- }
- break;
- }
- break;
- }
- break;
-
case T_RemoveAggrStmt:
{
RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index b50990fe29..3913d88ce9 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.116 2000/10/07 00:58:21 tgl Exp $
+ * $Id: parsenodes.h,v 1.117 2000/10/18 16:16:10 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -389,15 +389,24 @@ typedef struct DefineStmt
List *definition; /* a list of DefElem */
} DefineStmt;
+
/* ----------------------
- * Drop Table Statement
+ * Drop Table|Sequence|View|Index|Rule|Type Statement
* ----------------------
*/
+
+#define DROP_TABLE 1
+#define DROP_SEQUENCE 2
+#define DROP_VIEW 3
+#define DROP_INDEX 4
+#define DROP_RULE 5
+#define DROP_TYPE_P 6
+
typedef struct DropStmt
{
NodeTag type;
- List *relNames; /* relations to be dropped */
- bool sequence;
+ List *names;
+ int removeType;
} DropStmt;
/* ----------------------
@@ -527,17 +536,6 @@ typedef struct RemoveOperStmt
List *args; /* types of the arguments */
} RemoveOperStmt;
-/* ----------------------
- * Drop {Type|Index|Rule|View} Statement
- * ----------------------
- */
-typedef struct RemoveStmt
-{
- NodeTag type;
- int removeType; /* P_TYPE|INDEX|RULE|VIEW */
- char *name; /* name to drop */
-} RemoveStmt;
-
/* ----------------------
* Alter Table Statement
* ----------------------
diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile
index 43d29cd8f9..a721b0ac6d 100644
--- a/src/test/regress/GNUmakefile
+++ b/src/test/regress/GNUmakefile
@@ -7,7 +7,7 @@
#
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/test/regress/GNUmakefile,v 1.26 2000/10/07 20:23:03 petere Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/GNUmakefile,v 1.27 2000/10/18 16:16:14 momjian Exp $
#
#-------------------------------------------------------------------------
@@ -130,9 +130,11 @@ endif
runcheck: all
ifneq ($(PORTNAME), win)
MULTIBYTE=$(MULTIBYTE);export MULTIBYTE; \
+ MAKE=$(MAKE);export MAKE; \
$(SHELL) ./run_check.sh $(host_tuple)
else
MULTIBYTE=$(MULTIBYTE);export MULTIBYTE; \
+ MAKE=$(MAKE);export MAKE; \
./run_check.sh $(host_tuple)
endif
@echo "ACTUAL RESULTS OF REGRESSION TEST ARE NOW IN FILES run_check.out"
@@ -148,9 +150,11 @@ endif
bigcheck: all
ifneq ($(PORTNAME), win)
MULTIBYTE=$(MULTIBYTE);export MULTIBYTE; \
+ MAKE=$(MAKE);export MAKE; \
$(SHELL) ./run_check.sh $(host_tuple) $(EXTRA_TESTS)
else
MULTIBYTE=$(MULTIBYTE);export MULTIBYTE; \
+ MAKE=$(MAKE);export MAKE; \
./run_check.sh $(host_tuple) $(EXTRA_TESTS)
endif
@echo "ACTUAL RESULTS OF REGRESSION TEST ARE NOW IN FILES run_check.out"
diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out
index ca030be4a2..81b905bbae 100644
--- a/src/test/regress/expected/errors.out
+++ b/src/test/regress/expected/errors.out
@@ -52,7 +52,7 @@ drop table;
ERROR: parser: parse error at or near ";"
-- no such relation
drop table nonesuch;
-ERROR: Relation 'nonesuch' does not exist
+ERROR: table "nonesuch" is nonexistent
--
-- RENAME
@@ -122,7 +122,7 @@ drop index 314159;
ERROR: parser: parse error at or near "314159"
-- no such index
drop index nonesuch;
-ERROR: index "nonesuch" nonexistent
+ERROR: index "nonesuch" is nonexistent
--
-- REMOVE AGGREGATE
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 105d07adfd..42ac65a3fe 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -699,7 +699,7 @@ CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1)
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: UNIQUE constraint matching given keys for referenced table "pktable" not found
DROP TABLE FKTABLE_FAIL1;
-ERROR: Relation 'fktable_fail1' does not exist
+ERROR: table "fktable_fail1" is nonexistent
DROP TABLE FKTABLE_FAIL2;
-ERROR: Relation 'fktable_fail2' does not exist
+ERROR: table "fktable_fail2" is nonexistent
DROP TABLE PKTABLE;
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index 6822ae3895..4a91fcc96f 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -3,7 +3,7 @@
--
-- prepare the table...
DROP TABLE INET_TBL;
-ERROR: Relation 'inet_tbl' does not exist
+ERROR: table "inet_tbl" is nonexistent
CREATE TABLE INET_TBL (c cidr, i inet);
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.226/24');
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');