mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	From: Darren King <aixssd!darrenk@abs.net>
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.
This commit is contained in:
		@@ -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];
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    key[0].sk_argument = PointerGetDatum(aggName);
 | 
			
		||||
    /*
 | 
			
		||||
     * 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));
 | 
			
		||||
    
 | 
			
		||||
    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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <str>	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 <str>	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 <list>	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 <funcname>
 | 
			
		||||
 *		(REMOVE FUNCTION "funcname" (arg1, arg2, ...))
 | 
			
		||||
 *	remove aggregate <aggname>
 | 
			
		||||
 *		(REMOVE AGGREGATE "aggname" "aggtype")
 | 
			
		||||
 *	remove operator <opname>
 | 
			
		||||
 *		(REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
 | 
			
		||||
 *	remove type <typename>
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user