From: Darren King
authorMarc G. Fournier
Thu, 22 May 1997 00:17:24 +0000 (00:17 +0000)
committerMarc G. Fournier
Thu, 22 May 1997 00:17:24 +0000 (00:17 +0000)
Subject: [PATCHES] DROP AGGREGATE patch/fix.

Here's a patch that fixes the DROP AGGREGATE command to delete
the desired aggregate for a specific type.

13 files changed:
src/backend/commands/remove.c
src/backend/parser/catalog_utils.c
src/backend/parser/gram.y
src/backend/tcop/aclchk.c
src/backend/tcop/utility.c
src/include/commands/defrem.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/parser/catalog_utils.h
src/include/utils/acl.h
src/man/drop_aggregate.l
src/test/regress/sql/destroy.sql
src/test/regress/sql/errors.sql

index 3f57ea79bc06f681b9db509670674a54f8d3c88f..e3c8bdc469269190cc2ff2cf085f0ce470ba8b19 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.7 1996/11/30 18:06:10 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.8 1997/05/22 00:14:32 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -403,27 +403,78 @@ RemoveFunction(char *functionName, /* function name to be removed */
 }
 
 void
-RemoveAggregate(char *aggName)
+RemoveAggregate(char *aggName, char *aggType)
 {
-    Relation   relation;
-    HeapScanDesc   scan;
-    HeapTuple  tup;
-    ItemPointerData      itemPointerData;
-    static ScanKeyData key[3] = {
-   { 0, Anum_pg_aggregate_aggname, NameEqualRegProcedure }
-    };
+    Relation            relation;
+    HeapScanDesc        scan;
+    HeapTuple           tup;
+    ItemPointerData     itemPointerData;
+    char                *userName;
+    char                *typename;
+    Oid                 basetypeID = InvalidOid;
+    bool                defined;
+    ScanKeyData         aggregateKey[3];
+
+    
+    /*
+     * if a basetype is passed in, then attempt to find an aggregate for that
+     *   specific type.
+     *
+     * else if the basetype is blank, then attempt to find an aggregate with a
+     *   basetype of zero.  This is valid. It means that the aggregate is to apply
+     *   to all basetypes.  ie, a counter of some sort.  
+     *
+     */
+
+    if (aggType) {
+        basetypeID = TypeGet(aggType, &defined);
+        if (!OidIsValid(basetypeID)) {
+            elog(WARN, "RemoveAggregate: type '%s' does not exist", aggType);
+        }
+    } else {
+        basetypeID = 0;
+    }
+
+/*
+#ifndef NO_SECURITY
+*/
+    userName = GetPgUserName();
+    if (!pg_aggr_ownercheck(userName, aggName, basetypeID)) {
+        if (aggType) {
+            elog(WARN, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
+                 aggName, aggType);
+        } else {
+            elog(WARN, "RemoveAggregate: aggregate '%s': permission denied",
+                 aggName);
+        }
+    }
+/*
+#endif
+*/
+
+    ScanKeyEntryInitialize(&aggregateKey[0], 0x0,
+              Anum_pg_aggregate_aggname,
+              NameEqualRegProcedure,
+              PointerGetDatum(aggName));
     
-    key[0].sk_argument = PointerGetDatum(aggName);
+    ScanKeyEntryInitialize(&aggregateKey[1], 0x0,
+              Anum_pg_aggregate_aggbasetype,
+              ObjectIdEqualRegProcedure,
+              ObjectIdGetDatum(basetypeID));
     
-    fmgr_info(key[0].sk_procedure, &key[0].sk_func, &key[0].sk_nargs);
     relation = heap_openr(AggregateRelationName);
-    scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
+    scan = heap_beginscan(relation, 0, NowTimeQual, 2, aggregateKey);
     tup = heap_getnext(scan, 0, (Buffer *) 0);
     if (!HeapTupleIsValid(tup)) {
-   heap_endscan(scan);
-   heap_close(relation);
-   elog(WARN, "RemoveAggregate: aggregate '%s' does not exist",
-        aggName);
+        heap_endscan(scan);
+        heap_close(relation);
+        if (aggType) {
+            elog(WARN, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
+                 aggName, aggType);
+        } else {
+            elog(WARN, "RemoveAggregate: aggregate '%s' for all types does not exist",
+                 aggName);
+        }
     }
     ItemPointerCopy(&tup->t_ctid, &itemPointerData);
     heap_delete(relation, &itemPointerData);
index 60a4323949a534489351357e747aa471fb5664db..e848b75e5922d5a3cdc5018d6a24e01d86df03b2 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.17 1997/03/02 01:03:00 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.18 1997/05/22 00:14:41 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1499,3 +1499,19 @@ func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
     elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
 }
 
+/*
+ * Error message when aggregate lookup fails that gives details of the
+ * basetype
+ */
+void
+agg_error(char *caller, char *aggname, Oid basetypeID)
+{
+    /* basetypeID that is Invalid (zero) means aggregate over all types. (count) */
+
+    if (basetypeID == InvalidOid) {
+        elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
+    } else {
+        elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
+            tname(get_id_type(basetypeID)));
+    }
+}
index af655059462dbaa4b8a671208c8c37e6687dbb59..db2932a77d065c19939a22c25cee4231cf7fbdfd 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.32 1997/04/23 06:04:42 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.33 1997/05/22 00:14:52 scrappy Exp $
  *
  * HISTORY
  *    AUTHOR       DATE        MAJOR EVENT
@@ -104,8 +104,8 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
    ExtendStmt, FetchStmt,  GrantStmt,
    IndexStmt, MoveStmt, ListenStmt, OptimizableStmt, 
         ProcedureStmt, PurgeStmt,
-   RecipeStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt, RenameStmt,
-        RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
+   RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
+   RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
    CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
    ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
    ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
@@ -113,7 +113,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
 %type     relation_name, copy_file_name, copy_delimiter, def_name,
    database_name, access_method_clause, access_method, attr_name,
    class, index_name, name, file_name, recipe_name,
-   var_name
+   var_name, aggr_argtype
 
 %type     opt_id, opt_portal_name,
    before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
@@ -126,7 +126,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
 %type    stmtblock, stmtmulti,
    relation_name_list, OptTableElementList,
    tableElementList, OptInherit, definition,
-   opt_with, def_args, def_name_list, func_argtypes
+   opt_with, def_args, def_name_list, func_argtypes
    oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
    opt_column_list, columnList, opt_va_list, va_list,
    sort_clause, sortby_list, index_params, index_list,
@@ -262,6 +262,7 @@ stmt :    AddAttrStmt
    | ProcedureStmt
    | PurgeStmt         
    | RecipeStmt
+   | RemoveAggrStmt
    | RemoveOperStmt
    | RemoveFuncStmt
    | RemoveStmt
@@ -921,6 +922,8 @@ after_clause:   AFTER date      { $$ = $2; }
  *
  * remove function 
  *     (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
+ * remove aggregate 
+ *     (REMOVE AGGREGATE "aggname" "aggtype")
  * remove operator 
  *     (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
  * remove type 
@@ -939,13 +942,25 @@ RemoveStmt:  DROP remove_type name
        }
    ;
 
-remove_type:  AGGREGATE        {  $$ = AGGREGATE; }
-   |  Type             {  $$ = P_TYPE; }
-   |  INDEX            {  $$ = INDEX; }
-   |  RULE             {  $$ = RULE; }
-   |  VIEW             {  $$ = VIEW; }
+remove_type:  Type                 {  $$ = P_TYPE; }
+   |  INDEX                {  $$ = INDEX; }
+   |  RULE                 {  $$ = RULE; }
+   |  VIEW                 {  $$ = VIEW; }
    ;
 
+RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
+       {
+           RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
+           n->aggname = $3;
+           n->aggtype = $4;
+           $$ = (Node *)n;
+       }
+   ;
+
+aggr_argtype:  name                { $$ = $1; }
+   |  '*'                  { $$ = NULL; }
+   ;
+
 RemoveFuncStmt:  DROP FUNCTION name '(' func_argtypes ')'
                 {
            RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
index a60794af085d50e491b9448712ae1be7e02483fa..a94d35791507ef1f01d51cedcb41efcc363be505 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.9 1997/04/03 21:31:47 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.10 1997/05/22 00:15:21 scrappy Exp $
  *
  * NOTES
  *    See acl.h.
@@ -29,6 +29,7 @@
 #include "catalog/catname.h"
 #include "catalog/pg_group.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_aggregate.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_user.h"
 #include "utils/syscache.h"
@@ -561,3 +562,43 @@ pg_func_ownercheck(char *usename,
    
     return(user_id == owner_id);
 }
+
+int32
+pg_aggr_ownercheck(char *usename, 
+          char *aggname,
+          Oid basetypeID)
+{
+    HeapTuple htp;
+    AclId user_id, owner_id;
+
+    htp = SearchSysCacheTuple(USENAME, PointerGetDatum(usename), 
+                 0,0,0);
+    if (!HeapTupleIsValid(htp))
+   elog(WARN, "pg_aggr_ownercheck: user \"%-.*s\" not found",
+        NAMEDATALEN, usename);
+    user_id = (AclId) ((Form_pg_user) GETSTRUCT(htp))->usesysid;
+
+    /*
+     * Superusers bypass all permission-checking.
+     */
+    if (((Form_pg_user) GETSTRUCT(htp))->usesuper) {
+#ifdef ACLDEBUG_TRACE
+   elog(DEBUG, "pg_aggr_ownercheck: user \"%-.*s\" is superuser",
+        NAMEDATALEN, usename);
+#endif
+   return(1);
+    }
+
+    htp = SearchSysCacheTuple(AGGNAME,
+                 PointerGetDatum(aggname),
+                 PointerGetDatum(basetypeID),
+                 0,
+                 0);
+
+    if (!HeapTupleIsValid(htp))
+   agg_error("pg_aggr_ownercheck", aggname, basetypeID);
+
+    owner_id = ((Form_pg_aggregate) GETSTRUCT(htp))->aggowner;
+   
+    return(user_id == owner_id);
+}
index ee89e5b3916028ac78bf45d3272a0fffc8427029..fc5b09b4a1e4ee4a0b15fd6723ce8031bb69fe54 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.16 1997/04/23 06:09:33 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.17 1997/05/22 00:15:36 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -440,9 +440,6 @@ ProcessUtility(Node *parsetree,
        CHECK_IF_ABORTED();
    
        switch(stmt->removeType) {
-       case AGGREGATE:
-       RemoveAggregate(stmt->name);
-       break;
        case INDEX:
        relname = stmt->name;
        if (IsSystemRelationName(relname))
@@ -496,6 +493,16 @@ ProcessUtility(Node *parsetree,
        break;
    }
    break;
+
+    case T_RemoveAggrStmt:
+   {
+       RemoveAggrStmt *stmt = (RemoveAggrStmt *)parsetree;
+       commandTag = "DROP";
+       CHECK_IF_ABORTED();
+       RemoveAggregate(stmt->aggname, stmt->aggtype);
+   }
+   break;
+      
     case T_RemoveFuncStmt:
    {
        RemoveFuncStmt *stmt = (RemoveFuncStmt *)parsetree;
index 4d582910015500552d0fcbe6cfefd1701a86e9aa..f47e7a343eab38fafaaa3cb73ff0ae5ddd5bd35c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: defrem.h,v 1.6 1996/11/13 20:51:18 scrappy Exp $
+ * $Id: defrem.h,v 1.7 1997/05/22 00:15:47 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,6 @@ extern void RemoveFunction(char *functionName, int nargs, List *argNameList);
 extern void RemoveOperator(char *operatorName, 
               char *typeName1, char *typeName2);
 extern void RemoveType(char *typeName);
-extern void RemoveAggregate(char *aggName);
+extern void RemoveAggregate(char *aggName, char *aggType);
 
 #endif /* DEFREM_H */
index e63e56f251d19314706c11f0c55f2d550475023c..16d50d3b701eb2bf690ddeef7da7f4482f4f7747 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.8 1997/04/23 03:17:29 scrappy Exp $
+ * $Id: nodes.h,v 1.9 1997/05/22 00:15:58 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -164,6 +164,7 @@ typedef enum NodeTag {
     T_ProcedureStmt,
     T_PurgeStmt,
     T_RecipeStmt,
+    T_RemoveAggrStmt,
     T_RemoveFuncStmt,
     T_RemoveOperStmt,
     T_RemoveStmt,
index d29e66bcf53935597a925753a3cc9a8028c1ac95..288434c785b8b2fde7d33abb2b50559c796b32d1 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.15 1997/04/29 04:28:59 vadim Exp $
+ * $Id: parsenodes.h,v 1.16 1997/05/22 00:16:13 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -271,6 +271,16 @@ typedef struct PurgeStmt {
     char       *afterDate; /* purge after this date */
 } PurgeStmt;
 
+/* ----------------------
+ * Drop Aggregate Statement
+ * ----------------------
+ */
+typedef struct RemoveAggrStmt {
+    NodeTag        type;
+    char       *aggname;   /* aggregate to drop */
+    char       *aggtype;   /* for this type */
+} RemoveAggrStmt;
+
 /* ----------------------
  * Drop Function Statement
  * ----------------------
@@ -292,12 +302,12 @@ typedef struct RemoveOperStmt {
 } RemoveOperStmt;
 
 /* ----------------------
- * Drop {Aggregate|Type|Index|Rule|View} Statement
+ * Drop {Type|Index|Rule|View} Statement
  * ----------------------
  */
 typedef struct RemoveStmt {
     NodeTag        type;
-    int        removeType; /* AGGREGATE|P_TYPE|INDEX|RULE|VIEW */
+    int        removeType; /* P_TYPE|INDEX|RULE|VIEW */
     char       *name;      /* name to drop */
 } RemoveStmt;
 
index 98b03fe41aa064fd3da6904be6e0d564d68487ee..4be3c7edec925158693a63b2b108adced491ba2e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catalog_utils.h,v 1.8 1997/02/07 16:24:12 momjian Exp $
+ * $Id: catalog_utils.h,v 1.9 1997/05/22 00:16:28 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,5 +53,6 @@ extern Oid get_typelem(Oid type_id);
 extern char FindDelimiter(char *typename);
 extern void op_error(char *op, Oid arg1, Oid arg2);
 extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
+extern void agg_error(char *caller, char *aggname, Oid basetypeID);
 
 #endif /* CATALOG_UTILS_H */
index bc4473d37d7dce500aa0b92364bf363b673c5e06..6aa5b72b7f0c0283fef4db7ae6152dd88544f12f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: acl.h,v 1.5 1997/03/12 20:48:48 scrappy Exp $
+ * $Id: acl.h,v 1.6 1997/05/22 00:16:41 scrappy Exp $
  *
  * NOTES
  *    For backward-compatability purposes we have to allow there
@@ -161,6 +161,8 @@ extern int32 pg_aclcheck(char *relname, char *usename, AclMode mode);
 extern int32 pg_ownercheck(char *usename, char *value, int cacheid);
 extern int32 pg_func_ownercheck(char *usename, char *funcname,
             int nargs, Oid *arglist);
+extern int32 pg_aggr_ownercheck(char *usename, char *aggname,
+            Oid basetypeID);
 
 #endif /* ACL_H */
 
index 7837dcb328ade3ca3e6e69695e8f46bb5d575a21..740d081c7ab249b9289bb4dc6a49cfc165a06668 100644 (file)
@@ -1,12 +1,12 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/drop_aggregate.l,v 1.2 1996/12/11 00:27:38 momjian Exp $
+.\" $Header: /cvsroot/pgsql/src/man/Attic/drop_aggregate.l,v 1.3 1997/05/22 00:16:56 scrappy Exp $
 .TH "DROP AGGREGATE" SQL 11/05/95 PostgreSQL PostgreSQL
 .SH NAME
 drop aggregate \(em remove the definition of an aggregate
 .SH SYNOPSIS
 .nf
-\fBdrop aggregate\fR aggname
+\fBdrop aggregate\fR aggname aggtype
 .fi
 .SH DESCRIPTION
 .BR "drop aggregate"
@@ -16,9 +16,9 @@ aggregate.
 .SH EXAMPLE
 .nf
 --
---Remove the average aggregate
+--Remove the average aggregate for type int4
 --
-drop aggregate avg
+drop aggregate avg int4
 .fi
 .SH "SEE ALSO"
 create aggregate(l).
index 345af37c36f989f51cb755b57d032c75ac0ac738..4d183f3de8706830a09b0d274a7b162fb6647c2b 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- destroy.source
 --
--- $Header: /cvsroot/pgsql/src/test/regress/sql/Attic/destroy.sql,v 1.2 1997/04/27 04:35:31 scrappy Exp $
+-- $Header: /cvsroot/pgsql/src/test/regress/sql/Attic/destroy.sql,v 1.3 1997/05/22 00:17:15 scrappy Exp $
 --
 
 --
@@ -74,11 +74,11 @@ DROP TYPE widget;
 --
 -- AGGREGATE REMOVAL
 --
-DROP AGGREGATE newavg;
+DROP AGGREGATE newavg int4;
 
-DROP AGGREGATE newsum;
+DROP AGGREGATE newsum int4;
 
-DROP AGGREGATE newcnt;
+DROP AGGREGATE newcnt int4;
 
 
 --
index e3a080e02a4d59c2f8381f03372241d9e4348dc3..225029e306c30330f6d11d4ccccd507ed285a53f 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- errors.source
 --
--- $Header: /cvsroot/pgsql/src/test/regress/sql/errors.sql,v 1.1 1997/04/27 03:56:21 scrappy Exp $
+-- $Header: /cvsroot/pgsql/src/test/regress/sql/errors.sql,v 1.2 1997/05/22 00:17:24 scrappy Exp $
  
 
 -- bad in postquel, but ok in postsql
@@ -182,6 +182,15 @@ drop aggregate 314159;
 -- no such aggregate 
 drop aggregate nonesuch;
 
+-- missing aggregate type
+drop aggregate newcnt1;
+
+-- bad aggregate type
+drop aggregate newcnt nonesuch;
+
+-- no such aggregate for type
+drop aggregate newcnt float4;
+
 
 --
 -- REMOVE FUNCTION