The following patch was sent to the patches list:
authorBruce Momjian <bruce@momjian.us>
Wed, 18 Oct 2000 16:16:18 +0000 (16:16 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 18 Oct 2000 16:16:18 +0000 (16:16 +0000)
This patch forces the use of 'DROP VIEW' to destroy views.

It also changes the syntax of DROP VIEW to
DROP VIEW v1, v2, ...
to match the syntax of DROP TABLE.

Some error messages were changed so this patch also includes changes to the
appropriate expected/*.out files.

Doc changes for 'DROP TABLE" and 'DROP VIEW' are included.

--
Mark Hollomon

doc/src/sgml/ref/drop_table.sgml
doc/src/sgml/ref/drop_view.sgml
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/nodes/parsenodes.h
src/test/regress/GNUmakefile
src/test/regress/expected/errors.out
src/test/regress/expected/foreign_key.out
src/test/regress/expected/inet.out

index adcd30d3116bf5133bdf53417267f72b7c54b69b..3c905cca3536b7a6d921de505c6712180e536803 100644 (file)
@@ -39,7 +39,7 @@ DROP TABLE <replaceable class="PARAMETER">name</replaceable> [, ...]
       <term><replaceable class="PARAMETER">name</replaceable></term>
       <listitem>
        <para>
-       The name of an existing table or view to drop.
+       The name of an existing table to drop.
        </para>
       </listitem>
      </varlistentry>
@@ -68,11 +68,11 @@ DROP
      </varlistentry>
      <varlistentry>
       <term><computeroutput>
-ERROR Relation "<replaceable class="parameter">name</replaceable>" Does Not Exist!
+ERROR: table "<replaceable class="parameter">name</replaceable>" is nonexistent
        </computeroutput></term>
       <listitem>
        <para>
-       If the specified table or view does not exist in the database.
+       If the specified table does not exist in the database.
        </para>
       </listitem>
      </varlistentry>
@@ -89,8 +89,8 @@ ERROR Relation "<replaceable class="parameter">name</replaceable>" Does Not Exis
    Description
   </title>
   <para>
-   <command>DROP TABLE</command> removes tables and views from the database.
-   Only its owner may destroy a table or view. A table
+   <command>DROP TABLE</command> removes tables from the database.
+   Only its owner may destroy a table. A table
    may be emptied of rows, but not destroyed, by using <command>DELETE</command>.
   </para>
   <para>
index c42e2421cb0eb396d95b496426420d5d286a9f99..03fd1c5d624f2890605b0dc4f068115408d51f7c 100644 (file)
@@ -23,7 +23,7 @@ Postgres documentation
    <date>1999-07-20</date>
   </refsynopsisdivinfo>
   <synopsis>
-DROP VIEW <replaceable class="PARAMETER">name</replaceable>
+DROP VIEW <replaceable class="PARAMETER">name</replaceable> [, ...]
   </synopsis>
   
   <refsect2 id="R2-SQL-DROPVIEW-1">
@@ -70,7 +70,7 @@ DROP
      </varlistentry>
      <varlistentry>
       <term><computeroutput>
-ERROR: RewriteGetRuleEventRel: rule "_RET<replaceable class="PARAMETER">name</replaceable>" not found
+ERROR: view <replaceable class="parameter">name</replaceable> is nonexistent
        </computeroutput></term>
       <listitem>
        <para>
index dd19059dccea9dc4b802a4b8e86c8a879416e6ca..c643027fe46201b4072e7601932a96cf442e5203 100644 (file)
@@ -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;
index ed6be75a4bc7951f7607c262d2224d662d7484fe..5552055bf85cfe5b0c1d43fb2c5cc261d59d21ea 100644 (file)
@@ -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;
index a57d138e8a6cd6ad7aac1f9a42537b85b644246f..ede95ca0b9b646b633a0dd9e71fad19e2f11b13e 100644 (file)
@@ -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; }
                ;
 
 
index b65554702e7149b889995f7f704cc2ccf8933030..2e7a26fbad302ac022d6102b9907d89eedec0271 100644 (file)
 #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;
index fd82a8e7c4c53c00a6d3869b58ca3708e8f8ef0d..3320edde9dd9312492a67c08c710ae24e54e962b 100644 (file)
@@ -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
  * ----------------------
index f8590309371d98ed9e2fcaa12e5c9350dff7e8c1..50f25d1ca91d346781ab98f0a9975c5c6884cdd7 100644 (file)
@@ -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"
index ca030be4a2b61dd5f76d93ccc149155bb7402d8d..81b905bbae53cb6c2e1f1aee245e618361533edd 100644 (file)
@@ -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
  
index 105d07adfd8fe76c68b7f4fcdd99966ff92c27df..42ac65a3fe4eb1c4f85d81cab6f4dd9fed25c2e1 100644 (file)
@@ -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;
index 6822ae3895451518a54eaede78bef8a59b500365..4a91fcc96fde341bfc311f5c8b1e87b0557d1b34 100644 (file)
@@ -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');