drop if exists remnainder (reprise) - Mailing list pgsql-patches

From Andrew Dunstan
Subject drop if exists remnainder (reprise)
Date
Msg-id 448AD42F.9040702@dunslane.net
Whole thread Raw
Responses Re: drop if exists remnainder (reprise)  (Andrew Dunstan <andrew@dunslane.net>)
List pgsql-patches
Here is an updated patch for the remaining cases of DROP objtype IF
EXISTS ... as recently discussed on -hackers.

The cases are:

  language, tablespace, trigger, rule, opclass, function, aggregate.
operator, and cast.

Regression tests and docs still to come.

I wasn't quite sure how to format the message in the case of aggregate -
the change in calls there seems to have made it somewhat harder, so some
advice would be appreciated.

cheers

andrew




Index: src/backend/commands/aggregatecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v
retrieving revision 1.34
diff -c -r1.34 aggregatecmds.c
*** src/backend/commands/aggregatecmds.c    15 Apr 2006 17:45:33 -0000    1.34
--- src/backend/commands/aggregatecmds.c    10 Jun 2006 14:04:54 -0000
***************
*** 211,217 ****
      ObjectAddress object;

      /* Look up function and make sure it's an aggregate */
!     procOid = LookupAggNameTypeNames(aggName, aggArgs, false);

      /*
       * Find the function tuple, do permissions and validity checks
--- 211,231 ----
      ObjectAddress object;

      /* Look up function and make sure it's an aggregate */
!     procOid = LookupAggNameTypeNames(aggName, aggArgs, stmt->missing_ok);
!
!     if (!OidIsValid(procOid))
!     {
!         /* we only get here if stmt->missing_ok is true */
!
!         /* XXX might need better message here */
!
!         ereport(NOTICE,
!                 (errmsg("aggregate %s does not exist ... skipping",
!                        stmt->name)));
!
!
!         return;
!     }

      /*
       * Find the function tuple, do permissions and validity checks
Index: src/backend/commands/functioncmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v
retrieving revision 1.74
diff -c -r1.74 functioncmds.c
*** src/backend/commands/functioncmds.c    15 Apr 2006 17:45:34 -0000    1.74
--- src/backend/commands/functioncmds.c    10 Jun 2006 14:04:56 -0000
***************
*** 687,693 ****
      /*
       * Find the function, do permissions and validity checks
       */
!     funcOid = LookupFuncNameTypeNames(functionName, argTypes, false);

      tup = SearchSysCache(PROCOID,
                           ObjectIdGetDatum(funcOid),
--- 687,702 ----
      /*
       * Find the function, do permissions and validity checks
       */
!     funcOid = LookupFuncNameTypeNames(functionName, argTypes, stmt->missing_ok);
!     if (stmt->missing_ok &&!OidIsValid(funcOid))
!     {
!         ereport(NOTICE,
!                 (errmsg("function %s(%s) does not exist ... skipping",
!                         NameListToString(functionName),
!                         NameListToString(argTypes))));
!         return;
!     }
!

      tup = SearchSysCache(PROCOID,
                           ObjectIdGetDatum(funcOid),
***************
*** 1377,1382 ****
--- 1386,1392 ----
      HeapTuple    tuple;
      ObjectAddress object;

+     /* when dropping a cast, the types must exist even if you use IF EXISTS */
      sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
      targettypeid = typenameTypeId(NULL, stmt->targettype);

***************
*** 1385,1395 ****
                             ObjectIdGetDatum(targettypeid),
                             0, 0);
      if (!HeapTupleIsValid(tuple))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("cast from type %s to type %s does not exist",
!                         TypeNameToString(stmt->sourcetype),
!                         TypeNameToString(stmt->targettype))));

      /* Permission check */
      if (!pg_type_ownercheck(sourcetypeid, GetUserId())
--- 1395,1417 ----
                             ObjectIdGetDatum(targettypeid),
                             0, 0);
      if (!HeapTupleIsValid(tuple))
!     {
!         if (! stmt->missing_ok)
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("cast from type %s to type %s does not exist",
!                             TypeNameToString(stmt->sourcetype),
!                             TypeNameToString(stmt->targettype))));
!         else
!             ereport(NOTICE,
!                      (errmsg("cast from type %s to type %s does not exist ... skipping",
!                             TypeNameToString(stmt->sourcetype),
!                             TypeNameToString(stmt->targettype))));
!
!         return;
!     }
!
!

      /* Permission check */
      if (!pg_type_ownercheck(sourcetypeid, GetUserId())
Index: src/backend/commands/opclasscmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v
retrieving revision 1.45
diff -c -r1.45 opclasscmds.c
*** src/backend/commands/opclasscmds.c    2 May 2006 22:25:10 -0000    1.45
--- src/backend/commands/opclasscmds.c    10 Jun 2006 14:04:56 -0000
***************
*** 700,720 ****
          /* Unqualified opclass name, so search the search path */
          opcID = OpclassnameGetOpcid(amID, opcname);
          if (!OidIsValid(opcID))
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                             opcname, stmt->amname)));
          tuple = SearchSysCache(CLAOID,
                                 ObjectIdGetDatum(opcID),
                                 0, 0, 0);
      }

      if (!HeapTupleIsValid(tuple))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                         NameListToString(stmt->opclassname), stmt->amname)));
!
      opcID = HeapTupleGetOid(tuple);

      /* Permission check: must own opclass or its namespace */
--- 700,739 ----
          /* Unqualified opclass name, so search the search path */
          opcID = OpclassnameGetOpcid(amID, opcname);
          if (!OidIsValid(opcID))
!         {
!             if (! stmt -> missing_ok )
!                 ereport(ERROR,
!                         (errcode(ERRCODE_UNDEFINED_OBJECT),
!                          errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                                 opcname, stmt->amname)));
!             else
!                 ereport(NOTICE,
!                         (errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                                 opcname, stmt->amname)));
!
!             return;
!         }
!
          tuple = SearchSysCache(CLAOID,
                                 ObjectIdGetDatum(opcID),
                                 0, 0, 0);
      }

      if (!HeapTupleIsValid(tuple))
!     {
!
!         if (! stmt->missing_ok )
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                             NameListToString(stmt->opclassname), stmt->amname)));
!         else
!             ereport(NOTICE,
!                     (errmsg("operator class \"%s\" does not exist for access method \"%s\"",
!                             NameListToString(stmt->opclassname), stmt->amname)));
!         return;
!     }
!
      opcID = HeapTupleGetOid(tuple);

      /* Permission check: must own opclass or its namespace */
Index: src/backend/commands/operatorcmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v
retrieving revision 1.30
diff -c -r1.30 operatorcmds.c
*** src/backend/commands/operatorcmds.c    15 Apr 2006 17:45:34 -0000    1.30
--- src/backend/commands/operatorcmds.c    10 Jun 2006 14:04:56 -0000
***************
*** 213,219 ****
      Assert(list_length(stmt->args) == 2);
      operOid = LookupOperNameTypeNames(NULL, operatorName,
                                        typeName1, typeName2,
!                                       false, -1);

      tup = SearchSysCache(OPEROID,
                           ObjectIdGetDatum(operOid),
--- 213,227 ----
      Assert(list_length(stmt->args) == 2);
      operOid = LookupOperNameTypeNames(NULL, operatorName,
                                        typeName1, typeName2,
!                                       stmt->missing_ok, -1);
!
!    if (stmt->missing_ok &&!OidIsValid(operOid) )
!    {
!        ereport(NOTICE,
!                (errmsg("operator %s does not exist ... skipping",
!                        NameListToString(operatorName))));
!        return;
!    }

      tup = SearchSysCache(OPEROID,
                           ObjectIdGetDatum(operOid),
Index: src/backend/commands/proclang.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/proclang.c,v
retrieving revision 1.64
diff -c -r1.64 proclang.c
*** src/backend/commands/proclang.c    5 Mar 2006 15:58:24 -0000    1.64
--- src/backend/commands/proclang.c    10 Jun 2006 14:04:56 -0000
***************
*** 396,404 ****
                               CStringGetDatum(languageName),
                               0, 0, 0);
      if (!HeapTupleIsValid(langTup))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("language \"%s\" does not exist", languageName)));

      object.classId = LanguageRelationId;
      object.objectId = HeapTupleGetOid(langTup);
--- 396,413 ----
                               CStringGetDatum(languageName),
                               0, 0, 0);
      if (!HeapTupleIsValid(langTup))
!     {
!         if (! stmt->missing_ok)
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("language \"%s\" does not exist", languageName)));
!         else
!             ereport(NOTICE,
!                     (errmsg("language \"%s\" does not exist ... skipping",
!                             languageName)));
!
!         return;
!     }

      object.classId = LanguageRelationId;
      object.objectId = HeapTupleGetOid(langTup);
Index: src/backend/commands/tablespace.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablespace.c,v
retrieving revision 1.34
diff -c -r1.34 tablespace.c
*** src/backend/commands/tablespace.c    29 Mar 2006 21:17:38 -0000    1.34
--- src/backend/commands/tablespace.c    10 Jun 2006 14:04:57 -0000
***************
*** 403,412 ****
      tuple = heap_getnext(scandesc, ForwardScanDirection);

      if (!HeapTupleIsValid(tuple))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("tablespace \"%s\" does not exist",
!                         tablespacename)));

      tablespaceoid = HeapTupleGetOid(tuple);

--- 403,427 ----
      tuple = heap_getnext(scandesc, ForwardScanDirection);

      if (!HeapTupleIsValid(tuple))
!     {
!         if ( ! stmt->missing_ok )
!         {
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("tablespace \"%s\" does not exist",
!                             tablespacename)));
!         }
!         else
!         {
!             ereport(NOTICE,
!                     (errmsg("tablespace \"%s\" does not exist ... skipping",
!                             tablespacename)));
!             /* XXX I assume I need one or both of these next two calls */
!             heap_endscan(scandesc);
!             heap_close(rel, NoLock);
!         }
!         return;
!     }

      tablespaceoid = HeapTupleGetOid(tuple);

Index: src/backend/commands/trigger.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/trigger.c,v
retrieving revision 1.202
diff -c -r1.202 trigger.c
*** src/backend/commands/trigger.c    30 May 2006 14:01:57 -0000    1.202
--- src/backend/commands/trigger.c    10 Jun 2006 14:05:01 -0000
***************
*** 452,458 ****
   * DropTrigger - drop an individual trigger by name
   */
  void
! DropTrigger(Oid relid, const char *trigname, DropBehavior behavior)
  {
      Relation    tgrel;
      ScanKeyData skey[2];
--- 452,459 ----
   * DropTrigger - drop an individual trigger by name
   */
  void
! DropTrigger(Oid relid, const char *trigname, DropBehavior behavior,
!             bool missing_ok)
  {
      Relation    tgrel;
      ScanKeyData skey[2];
***************
*** 481,490 ****
      tup = systable_getnext(tgscan);

      if (!HeapTupleIsValid(tup))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("trigger \"%s\" for table \"%s\" does not exist",
!                         trigname, get_rel_name(relid))));

      if (!pg_class_ownercheck(relid, GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
--- 482,502 ----
      tup = systable_getnext(tgscan);

      if (!HeapTupleIsValid(tup))
!     {
!         if (! missing_ok)
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("trigger \"%s\" for table \"%s\" does not exist",
!                             trigname, get_rel_name(relid))));
!         else
!             ereport(NOTICE,
!                     (errmsg("trigger \"%s\" for table \"%s\" does not exist ...skipping",
!                             trigname, get_rel_name(relid))));
!         /* cleanup */
!         systable_endscan(tgscan);
!         heap_close(tgrel, AccessShareLock);
!         return;
!     }

      if (!pg_class_ownercheck(relid, GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.335
diff -c -r1.335 copyfuncs.c
*** src/backend/nodes/copyfuncs.c    30 Apr 2006 18:30:38 -0000    1.335
--- src/backend/nodes/copyfuncs.c    10 Jun 2006 14:05:02 -0000
***************
*** 2075,2080 ****
--- 2075,2081 ----
      COPY_NODE_FIELD(name);
      COPY_NODE_FIELD(args);
      COPY_SCALAR_FIELD(behavior);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
***************
*** 2087,2092 ****
--- 2088,2094 ----
      COPY_NODE_FIELD(opclassname);
      COPY_STRING_FIELD(amname);
      COPY_SCALAR_FIELD(behavior);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
***************
*** 2414,2419 ****
--- 2416,2422 ----
      DropTableSpaceStmt *newnode = makeNode(DropTableSpaceStmt);

      COPY_STRING_FIELD(tablespacename);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
***************
*** 2447,2452 ****
--- 2450,2456 ----
      COPY_STRING_FIELD(property);
      COPY_SCALAR_FIELD(removeType);
      COPY_SCALAR_FIELD(behavior);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
***************
*** 2471,2476 ****
--- 2475,2481 ----

      COPY_STRING_FIELD(plname);
      COPY_SCALAR_FIELD(behavior);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
***************
*** 2606,2611 ****
--- 2611,2617 ----
      COPY_NODE_FIELD(sourcetype);
      COPY_NODE_FIELD(targettype);
      COPY_SCALAR_FIELD(behavior);
+     COPY_SCALAR_FIELD(missing_ok);

      return newnode;
  }
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.271
diff -c -r1.271 equalfuncs.c
*** src/backend/nodes/equalfuncs.c    30 Apr 2006 18:30:38 -0000    1.271
--- src/backend/nodes/equalfuncs.c    10 Jun 2006 14:05:04 -0000
***************
*** 999,1004 ****
--- 999,1005 ----
      COMPARE_NODE_FIELD(name);
      COMPARE_NODE_FIELD(args);
      COMPARE_SCALAR_FIELD(behavior);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
***************
*** 1009,1014 ****
--- 1010,1016 ----
      COMPARE_NODE_FIELD(opclassname);
      COMPARE_STRING_FIELD(amname);
      COMPARE_SCALAR_FIELD(behavior);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
***************
*** 1282,1287 ****
--- 1284,1290 ----
  _equalDropTableSpaceStmt(DropTableSpaceStmt *a, DropTableSpaceStmt *b)
  {
      COMPARE_STRING_FIELD(tablespacename);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
***************
*** 1312,1317 ****
--- 1315,1321 ----
      COMPARE_STRING_FIELD(property);
      COMPARE_SCALAR_FIELD(removeType);
      COMPARE_SCALAR_FIELD(behavior);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
***************
*** 1332,1337 ****
--- 1336,1342 ----
  {
      COMPARE_STRING_FIELD(plname);
      COMPARE_SCALAR_FIELD(behavior);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
***************
*** 1445,1450 ****
--- 1450,1456 ----
      COMPARE_NODE_FIELD(sourcetype);
      COMPARE_NODE_FIELD(targettype);
      COMPARE_SCALAR_FIELD(behavior);
+     COMPARE_SCALAR_FIELD(missing_ok);

      return true;
  }
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.545
diff -c -r2.545 gram.y
*** src/backend/parser/gram.y    27 May 2006 17:38:45 -0000    2.545
--- src/backend/parser/gram.y    10 Jun 2006 14:05:13 -0000
***************
*** 191,197 ****
  %type <ival>    opt_lock lock_type cast_context
  %type <boolean>    opt_force opt_or_replace
                  opt_grant_grant_option opt_grant_admin_option
!                 opt_nowait

  %type <boolean>    like_including_defaults

--- 191,197 ----
  %type <ival>    opt_lock lock_type cast_context
  %type <boolean>    opt_force opt_or_replace
                  opt_grant_grant_option opt_grant_admin_option
!                 opt_nowait opt_if_exists

  %type <boolean>    like_including_defaults

***************
*** 2401,2406 ****
--- 2401,2415 ----
                      DropPLangStmt *n = makeNode(DropPLangStmt);
                      n->plname = $4;
                      n->behavior = $5;
+                     n->missing_ok = false;
+                     $$ = (Node *)n;
+                 }
+             | DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior
+                 {
+                     DropPLangStmt *n = makeNode(DropPLangStmt);
+                     n->plname = $6;
+                     n->behavior = $7;
+                     n->missing_ok = true;
                      $$ = (Node *)n;
                  }
          ;
***************
*** 2445,2450 ****
--- 2454,2467 ----
                  {
                      DropTableSpaceStmt *n = makeNode(DropTableSpaceStmt);
                      n->tablespacename = $3;
+                     n->missing_ok = false;
+                     $$ = (Node *) n;
+                 }
+                 |  DROP TABLESPACE IF_P EXISTS name
+                 {
+                     DropTableSpaceStmt *n = makeNode(DropTableSpaceStmt);
+                     n->tablespacename = $5;
+                     n->missing_ok = true;
                      $$ = (Node *) n;
                  }
          ;
***************
*** 2630,2635 ****
--- 2647,2663 ----
                      n->property = $3;
                      n->behavior = $6;
                      n->removeType = OBJECT_TRIGGER;
+                     n->missing_ok = false;
+                     $$ = (Node *) n;
+                 }
+             | DROP TRIGGER IF_P EXISTS name ON qualified_name opt_drop_behavior
+                 {
+                     DropPropertyStmt *n = makeNode(DropPropertyStmt);
+                     n->relation = $7;
+                     n->property = $5;
+                     n->behavior = $8;
+                     n->removeType = OBJECT_TRIGGER;
+                     n->missing_ok = true;
                      $$ = (Node *) n;
                  }
          ;
***************
*** 2903,2908 ****
--- 2931,2946 ----
                      n->opclassname = $4;
                      n->amname = $6;
                      n->behavior = $7;
+                     n->missing_ok = false;
+                     $$ = (Node *) n;
+                 }
+             | DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
+                 {
+                     RemoveOpClassStmt *n = makeNode(RemoveOpClassStmt);
+                     n->opclassname = $6;
+                     n->amname = $8;
+                     n->behavior = $9;
+                     n->missing_ok = true;
                      $$ = (Node *) n;
                  }
          ;
***************
*** 3912,3917 ****
--- 3950,3966 ----
                      n->name = $3;
                      n->args = extractArgTypes($4);
                      n->behavior = $5;
+                     n->missing_ok = false;
+                     $$ = (Node *)n;
+                 }
+             | DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
+                 {
+                     RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
+                     n->kind = OBJECT_FUNCTION;
+                     n->name = $5;
+                     n->args = extractArgTypes($6);
+                     n->behavior = $7;
+                     n->missing_ok = true;
                      $$ = (Node *)n;
                  }
          ;
***************
*** 3924,3929 ****
--- 3973,3989 ----
                      n->name = $3;
                      n->args = $4;
                      n->behavior = $5;
+                     n->missing_ok = false;
+                     $$ = (Node *)n;
+                 }
+             | DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
+                 {
+                     RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
+                     n->kind = OBJECT_AGGREGATE;
+                     n->name = $5;
+                     n->args = $6;
+                     n->behavior = $7;
+                     n->missing_ok = true;
                      $$ = (Node *)n;
                  }
          ;
***************
*** 3936,3941 ****
--- 3996,4012 ----
                      n->name = $3;
                      n->args = $5;
                      n->behavior = $7;
+                     n->missing_ok = false;
+                     $$ = (Node *)n;
+                 }
+             | DROP OPERATOR IF_P EXISTS any_operator '(' oper_argtypes ')' opt_drop_behavior
+                 {
+                     RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
+                     n->kind = OBJECT_OPERATOR;
+                     n->name = $5;
+                     n->args = $7;
+                     n->behavior = $9;
+                     n->missing_ok = true;
                      $$ = (Node *)n;
                  }
          ;
***************
*** 3998,4013 ****
          ;


! DropCastStmt: DROP CAST '(' Typename AS Typename ')' opt_drop_behavior
                  {
                      DropCastStmt *n = makeNode(DropCastStmt);
!                     n->sourcetype = $4;
!                     n->targettype = $6;
!                     n->behavior = $8;
                      $$ = (Node *)n;
                  }
          ;



  /*****************************************************************************
--- 4069,4089 ----
          ;


! DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_behavior
                  {
                      DropCastStmt *n = makeNode(DropCastStmt);
!                     n->sourcetype = $5;
!                     n->targettype = $7;
!                     n->behavior = $9;
!                     n->missing_ok =
                      $$ = (Node *)n;
                  }
          ;

+ opt_if_exists: IF_P EXISTS { $$ = true; }
+                | /* empty */ { $$ = false; }
+         ;
+


  /*****************************************************************************
***************
*** 4432,4437 ****
--- 4508,4524 ----
                      n->property = $3;
                      n->behavior = $6;
                      n->removeType = OBJECT_RULE;
+                     n->missing_ok = false;
+                     $$ = (Node *) n;
+                 }
+             | DROP RULE IF_P EXISTS name ON qualified_name opt_drop_behavior
+                 {
+                     DropPropertyStmt *n = makeNode(DropPropertyStmt);
+                     n->relation = $7;
+                     n->property = $5;
+                     n->behavior = $8;
+                     n->removeType = OBJECT_RULE;
+                     n->missing_ok = true;
                      $$ = (Node *) n;
                  }
          ;
Index: src/backend/rewrite/rewriteRemove.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v
retrieving revision 1.64
diff -c -r1.64 rewriteRemove.c
*** src/backend/rewrite/rewriteRemove.c    5 Mar 2006 15:58:36 -0000    1.64
--- src/backend/rewrite/rewriteRemove.c    10 Jun 2006 14:05:13 -0000
***************
*** 34,40 ****
   * Delete a rule given its name.
   */
  void
! RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior)
  {
      HeapTuple    tuple;
      Oid            eventRelationOid;
--- 34,41 ----
   * Delete a rule given its name.
   */
  void
! RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior,
!                   bool missing_ok)
  {
      HeapTuple    tuple;
      Oid            eventRelationOid;
***************
*** 53,62 ****
       * complain if no rule with such name exists
       */
      if (!HeapTupleIsValid(tuple))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("rule \"%s\" for relation \"%s\" does not exist",
!                         ruleName, get_rel_name(owningRel))));

      /*
       * Verify user has appropriate permissions.
--- 54,71 ----
       * complain if no rule with such name exists
       */
      if (!HeapTupleIsValid(tuple))
!     {
!         if (! missing_ok)
!             ereport(ERROR,
!                     (errcode(ERRCODE_UNDEFINED_OBJECT),
!                      errmsg("rule \"%s\" for relation \"%s\" does not exist",
!                             ruleName, get_rel_name(owningRel))));
!         else
!             ereport(NOTICE,
!                     (errmsg("rule \"%s\" for relation \"%s\" does not exist ... skipping",
!                             ruleName, get_rel_name(owningRel))));
!         return;
!     }

      /*
       * Verify user has appropriate permissions.
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.257
diff -c -r1.257 utility.c
*** src/backend/tcop/utility.c    30 Apr 2006 18:30:40 -0000    1.257
--- src/backend/tcop/utility.c    10 Jun 2006 14:05:14 -0000
***************
*** 986,997 ****
                      case OBJECT_RULE:
                          /* RemoveRewriteRule checks permissions */
                          RemoveRewriteRule(relId, stmt->property,
!                                           stmt->behavior);
                          break;
                      case OBJECT_TRIGGER:
                          /* DropTrigger checks permissions */
                          DropTrigger(relId, stmt->property,
!                                     stmt->behavior);
                          break;
                      default:
                          elog(ERROR, "unrecognized object type: %d",
--- 986,997 ----
                      case OBJECT_RULE:
                          /* RemoveRewriteRule checks permissions */
                          RemoveRewriteRule(relId, stmt->property,
!                                           stmt->behavior, stmt->missing_ok);
                          break;
                      case OBJECT_TRIGGER:
                          /* DropTrigger checks permissions */
                          DropTrigger(relId, stmt->property,
!                                     stmt->behavior, stmt->missing_ok);
                          break;
                      default:
                          elog(ERROR, "unrecognized object type: %d",
Index: src/include/commands/trigger.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/trigger.h,v
retrieving revision 1.57
diff -c -r1.57 trigger.h
*** src/include/commands/trigger.h    5 Mar 2006 15:58:55 -0000    1.57
--- src/include/commands/trigger.h    10 Jun 2006 14:05:16 -0000
***************
*** 108,114 ****
  extern Oid    CreateTrigger(CreateTrigStmt *stmt, bool forConstraint);

  extern void DropTrigger(Oid relid, const char *trigname,
!             DropBehavior behavior);
  extern void RemoveTriggerById(Oid trigOid);

  extern void renametrig(Oid relid, const char *oldname, const char *newname);
--- 108,114 ----
  extern Oid    CreateTrigger(CreateTrigStmt *stmt, bool forConstraint);

  extern void DropTrigger(Oid relid, const char *trigname,
!             DropBehavior behavior, bool missing_ok);
  extern void RemoveTriggerById(Oid trigOid);

  extern void renametrig(Oid relid, const char *oldname, const char *newname);
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.310
diff -c -r1.310 parsenodes.h
*** src/include/nodes/parsenodes.h    30 Apr 2006 18:30:40 -0000    1.310
--- src/include/nodes/parsenodes.h    10 Jun 2006 14:05:17 -0000
***************
*** 1131,1136 ****
--- 1131,1137 ----
  {
      NodeTag        type;
      char       *tablespacename;
+     bool        missing_ok;        /* skip error if a missing? */
  } DropTableSpaceStmt;

  /* ----------------------
***************
*** 1175,1180 ****
--- 1176,1182 ----
      NodeTag        type;
      char       *plname;            /* PL name */
      DropBehavior behavior;        /* RESTRICT or CASCADE behavior */
+     bool        missing_ok;        /* skip error if missing? */
  } DropPLangStmt;

  /* ----------------------
***************
*** 1329,1334 ****
--- 1331,1337 ----
      char       *property;        /* name of rule, trigger, etc */
      ObjectType    removeType;        /* OBJECT_RULE or OBJECT_TRIGGER */
      DropBehavior behavior;        /* RESTRICT or CASCADE behavior */
+     bool        missing_ok;        /* skip error if a missing? */
  } DropPropertyStmt;

  /* ----------------------
***************
*** 1477,1482 ****
--- 1480,1486 ----
      List       *name;            /* qualified name of object to drop */
      List       *args;            /* types of the arguments */
      DropBehavior behavior;        /* RESTRICT or CASCADE behavior */
+     bool        missing_ok;        /* skip error if a missing? */
  } RemoveFuncStmt;

  /* ----------------------
***************
*** 1489,1494 ****
--- 1493,1499 ----
      List       *opclassname;    /* qualified name (list of Value strings) */
      char       *amname;            /* name of index AM opclass is for */
      DropBehavior behavior;        /* RESTRICT or CASCADE behavior */
+     bool        missing_ok;        /* skip error if a missing? */
  } RemoveOpClassStmt;

  /* ----------------------
***************
*** 1846,1851 ****
--- 1851,1857 ----
      TypeName   *sourcetype;
      TypeName   *targettype;
      DropBehavior behavior;
+     bool        missing_ok;        /* skip error if a missing? */
  } DropCastStmt;


Index: src/include/rewrite/rewriteRemove.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/rewrite/rewriteRemove.h,v
retrieving revision 1.21
diff -c -r1.21 rewriteRemove.h
*** src/include/rewrite/rewriteRemove.h    5 Mar 2006 15:58:58 -0000    1.21
--- src/include/rewrite/rewriteRemove.h    10 Jun 2006 14:05:18 -0000
***************
*** 18,24 ****


  extern void RemoveRewriteRule(Oid owningRel, const char *ruleName,
!                   DropBehavior behavior);
  extern void RemoveRewriteRuleById(Oid ruleOid);

  #endif   /* REWRITEREMOVE_H */
--- 18,24 ----


  extern void RemoveRewriteRule(Oid owningRel, const char *ruleName,
!                   DropBehavior behavior, bool missing_ok);
  extern void RemoveRewriteRuleById(Oid ruleOid);

  #endif   /* REWRITEREMOVE_H */

pgsql-patches by date:

Previous
From: Greg Stark
Date:
Subject: ADD/DROP INHERITS
Next
From: Tom Lane
Date:
Subject: Re: ADD/DROP INHERITS