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');