From 3651a3e6fb41121f2262577774382e84bf9a3177 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 15 Apr 2006 17:45:46 +0000 Subject: [PATCH] Support the syntax CREATE AGGREGATE aggname (input_type) (parameter_list) along with the old syntax where the input type was named in the parameter list. This fits more naturally with the way that the aggregate is identified in DROP AGGREGATE and other utility commands; furthermore it has a natural extension to handle multiple-input aggregates, where the basetype-parameter method would get ugly. In fact, this commit fixes the grammar and all the utility commands to support multiple-input aggregates; but DefineAggregate rejects it because the executor isn't fixed yet. I didn't do anything about treating agg(*) as a zero-input aggregate instead of artificially making it a one-input aggregate, but that should be considered in combination with supporting multi-input aggregates. --- doc/src/sgml/ref/create_aggregate.sgml | 37 +++++- doc/src/sgml/xaggr.sgml | 31 ++--- src/backend/commands/aggregatecmds.c | 158 ++++++++++++------------ src/backend/commands/alter.c | 17 +-- src/backend/commands/comment.c | 21 +--- src/backend/commands/functioncmds.c | 16 ++- src/backend/commands/operatorcmds.c | 7 +- src/backend/nodes/copyfuncs.c | 37 +----- src/backend/nodes/equalfuncs.c | 33 +---- src/backend/parser/gram.y | 109 +++++++++++------ src/backend/parser/parse_func.c | 159 +++++++++++++++---------- src/backend/tcop/utility.c | 61 ++++++---- src/include/commands/defrem.h | 15 +-- src/include/nodes/nodes.h | 4 +- src/include/nodes/parsenodes.h | 33 +---- src/include/parser/parse_func.h | 6 +- src/test/regress/expected/errors.out | 2 +- 17 files changed, 395 insertions(+), 351 deletions(-) diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml index 70362f6503..5eb0741c9c 100644 --- a/doc/src/sgml/ref/create_aggregate.sgml +++ b/doc/src/sgml/ref/create_aggregate.sgml @@ -1,5 +1,5 @@ @@ -20,8 +20,18 @@ PostgreSQL documentation +CREATE AGGREGATE name ( input_data_type ) ( + SFUNC = sfunc, + STYPE = state_data_type + [ , FINALFUNC = ffunc ] + [ , INITCOND = initial_condition ] + [ , SORTOP = sort_operator ] +) + +or the old syntax + CREATE AGGREGATE name ( - BASETYPE = input_data_type, + BASETYPE = base_type, SFUNC = sfunc, STYPE = state_data_type [ , FINALFUNC = ffunc ] @@ -87,7 +97,7 @@ CREATE AGGREGATE name ( An aggregate function may provide an initial condition, that is, an initial value for the internal state value. - This is specified and stored in the database as a column of type + This is specified and stored in the database as a value of type text, but it must be a valid external representation of a constant of the state value data type. If it is not supplied then the state value starts out null. @@ -146,8 +156,9 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; Ordinarily, a data type's < operator is the proper sort operator for MIN, and > is the proper sort operator for MAX. Note that the optimization will never - actually take effect unless the specified operator is the less than or - greater than strategy member of a B-tree index operator class. + actually take effect unless the specified operator is the less + than or greater than strategy member of a B-tree + index operator class. @@ -170,13 +181,27 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; The input data type on which this aggregate function operates. - This can be specified as "ANY" for an aggregate that + This can be specified as * for an aggregate that does not examine its input values (an example is count(*)). + + base_type + + + In the old syntax for CREATE AGGREGATE, the input data type + is specified by a basetype parameter rather than being + written next to the aggregate name. Note that this syntax allows + only one input parameter. To define an aggregate that does not examine + its input values, specify the basetype as + "ANY" (not *). + + + + sfunc diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml index bbb4055b91..db6c077cbf 100644 --- a/doc/src/sgml/xaggr.sgml +++ b/doc/src/sgml/xaggr.sgml @@ -1,4 +1,4 @@ - + User-Defined Aggregates @@ -43,23 +43,24 @@ The aggregate definition would be: -CREATE AGGREGATE complex_sum ( +CREATE AGGREGATE sum (complex) +( sfunc = complex_add, - basetype = complex, stype = complex, initcond = '(0,0)' ); -SELECT complex_sum(a) FROM test_complex; +SELECT sum(a) FROM test_complex; - complex_sum -------------- + sum +----------- (34,53.9) - (In practice, we'd just name the aggregate sum and rely on - PostgreSQL to figure out which kind - of sum to apply to a column of type complex.) + (Notice that we are relying on function overloading: there is more than + one aggregate named sum, but + PostgreSQL can figure out which kind + of sum applies to a column of type complex.) @@ -99,9 +100,9 @@ SELECT complex_sum(a) FROM test_complex; looks like: -CREATE AGGREGATE avg ( +CREATE AGGREGATE avg (float8) +( sfunc = float8_accum, - basetype = float8, stype = float8[], finalfunc = float8_avg, initcond = '{0,0}' @@ -116,14 +117,14 @@ CREATE AGGREGATE avg ( See for an explanation of polymorphic functions. Going a step further, the aggregate function itself may be specified - with a polymorphic base type and state type, allowing a single + with a polymorphic input type and state type, allowing a single aggregate definition to serve for multiple input data types. Here is an example of a polymorphic aggregate: -CREATE AGGREGATE array_accum ( +CREATE AGGREGATE array_accum (anyelement) +( sfunc = array_append, - basetype = anyelement, stype = anyarray, initcond = '{}' ); @@ -167,7 +168,7 @@ SELECT attrelid::regclass, array_accum(atttypid) if (fcinfo->context && IsA(fcinfo->context, AggState)) - One reason for checking this is that when it is true, the left input + One reason for checking this is that when it is true, the first input must be a temporary transition value and can therefore safely be modified in-place rather than allocating a new copy. (This is the only case where it is safe for a function to modify a pass-by-reference input.) diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 3c0855238e..7b954edd38 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.33 2006/03/14 22:48:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.34 2006/04/15 17:45:33 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -41,9 +41,13 @@ /* * DefineAggregate + * + * "oldstyle" signals the old (pre-8.2) style where the aggregate input type + * is specified by a BASETYPE element in the parameters. Otherwise, + * "args" defines the input type(s). */ void -DefineAggregate(List *names, List *parameters) +DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) { char *aggName; Oid aggNamespace; @@ -59,7 +63,7 @@ DefineAggregate(List *names, List *parameters) ListCell *pl; /* Convert list of names to a name and namespace */ - aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName); + aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName); /* Check we have creation rights in target namespace */ aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE); @@ -103,10 +107,6 @@ DefineAggregate(List *names, List *parameters) /* * make sure we have our required definitions */ - if (baseType == NULL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate basetype must be specified"))); if (transType == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), @@ -117,20 +117,63 @@ DefineAggregate(List *names, List *parameters) errmsg("aggregate sfunc must be specified"))); /* - * look up the aggregate's base type (input datatype) and transtype. + * look up the aggregate's input datatype. + */ + if (oldstyle) + { + /* + * Old style: use basetype parameter. This supports only one input. + * + * Historically we allowed the command to look like basetype = 'ANY' + * so we must do a case-insensitive comparison for the name ANY. Ugh. + */ + if (baseType == NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("aggregate input type must be specified"))); + + if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0) + baseTypeId = ANYOID; + else + baseTypeId = typenameTypeId(NULL, baseType); + } + else + { + /* + * New style: args is a list of TypeNames. For the moment, though, + * we allow at most one. + */ + if (baseType != NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("basetype is redundant with aggregate input type specification"))); + + if (args == NIL) + { + /* special case for agg(*) */ + baseTypeId = ANYOID; + } + else if (list_length(args) != 1) + { + /* temporarily reject > 1 arg */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("aggregates can have only one input"))); + baseTypeId = InvalidOid; /* keep compiler quiet */ + } + else + { + baseTypeId = typenameTypeId(NULL, (TypeName *) linitial(args)); + } + } + + /* + * look up the aggregate's transtype. * - * We have historically allowed the command to look like basetype = 'ANY' - * so we must do a case-insensitive comparison for the name ANY. Ugh. - * - * basetype can be a pseudo-type, but transtype can't, since we need to be + * transtype can't be a pseudo-type, since we need to be * able to store values of the transtype. However, we can allow * polymorphic transtype in some cases (AggregateCreate will check). */ - if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0) - baseTypeId = ANYOID; - else - baseTypeId = typenameTypeId(NULL, baseType); - transTypeId = typenameTypeId(NULL, transType); if (get_typtype(transTypeId) == 'p' && transTypeId != ANYARRAYOID && @@ -159,28 +202,16 @@ DefineAggregate(List *names, List *parameters) * Deletes an aggregate. */ void -RemoveAggregate(RemoveAggrStmt *stmt) +RemoveAggregate(RemoveFuncStmt *stmt) { - List *aggName = stmt->aggname; - TypeName *aggType = stmt->aggtype; - Oid basetypeID; + List *aggName = stmt->name; + List *aggArgs = stmt->args; Oid procOid; HeapTuple tup; ObjectAddress object; - /* - * if a basetype is passed in, then attempt to find an aggregate for that - * specific type. - * - * else attempt to find an aggregate with a basetype of ANYOID. This means - * that the aggregate is to apply to all basetypes (eg, COUNT). - */ - if (aggType) - basetypeID = typenameTypeId(NULL, aggType); - else - basetypeID = ANYOID; - - procOid = find_aggregate_func(aggName, basetypeID, false); + /* Look up function and make sure it's an aggregate */ + procOid = LookupAggNameTypeNames(aggName, aggArgs, false); /* * Find the function tuple, do permissions and validity checks @@ -198,8 +229,6 @@ RemoveAggregate(RemoveAggrStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(aggName)); - /* find_aggregate_func already checked it is an aggregate */ - ReleaseSysCache(tup); /* @@ -214,9 +243,8 @@ RemoveAggregate(RemoveAggrStmt *stmt) void -RenameAggregate(List *name, TypeName *basetype, const char *newname) +RenameAggregate(List *name, List *args, const char *newname) { - Oid basetypeOid; Oid procOid; Oid namespaceOid; HeapTuple tup; @@ -224,20 +252,10 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname) Relation rel; AclResult aclresult; - /* - * if a basetype is passed in, then attempt to find an aggregate for that - * specific type; else attempt to find an aggregate with a basetype of - * ANYOID. This means that the aggregate applies to all basetypes (eg, - * COUNT). - */ - if (basetype) - basetypeOid = typenameTypeId(NULL, basetype); - else - basetypeOid = ANYOID; - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - procOid = find_aggregate_func(name, basetypeOid, false); + /* Look up function and make sure it's an aggregate */ + procOid = LookupAggNameTypeNames(name, args, false); tup = SearchSysCacheCopy(PROCOID, ObjectIdGetDatum(procOid), @@ -254,22 +272,13 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname) PointerGetDatum(&procForm->proargtypes), ObjectIdGetDatum(namespaceOid), 0)) - { - if (basetypeOid == ANYOID) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function %s(*) already exists in schema \"%s\"", - newname, - get_namespace_name(namespaceOid)))); - else - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function %s already exists in schema \"%s\"", - funcname_signature_string(newname, - procForm->pronargs, - procForm->proargtypes.values), - get_namespace_name(namespaceOid)))); - } + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_FUNCTION), + errmsg("function %s already exists in schema \"%s\"", + funcname_signature_string(newname, + procForm->pronargs, + procForm->proargtypes.values), + get_namespace_name(namespaceOid)))); /* must be owner */ if (!pg_proc_ownercheck(procOid, GetUserId())) @@ -295,29 +304,18 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname) * Change aggregate owner */ void -AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId) +AlterAggregateOwner(List *name, List *args, Oid newOwnerId) { - Oid basetypeOid; Oid procOid; HeapTuple tup; Form_pg_proc procForm; Relation rel; AclResult aclresult; - /* - * if a basetype is passed in, then attempt to find an aggregate for that - * specific type; else attempt to find an aggregate with a basetype of - * ANYOID. This means that the aggregate applies to all basetypes (eg, - * COUNT). - */ - if (basetype) - basetypeOid = typenameTypeId(NULL, basetype); - else - basetypeOid = ANYOID; - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - procOid = find_aggregate_func(name, basetypeOid, false); + /* Look up function and make sure it's an aggregate */ + procOid = LookupAggNameTypeNames(name, args, false); tup = SearchSysCacheCopy(PROCOID, ObjectIdGetDatum(procOid), diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 3c99fd9e03..2b7c9250b3 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.18 2006/03/05 15:58:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.19 2006/04/15 17:45:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,9 +47,7 @@ ExecRenameStmt(RenameStmt *stmt) switch (stmt->renameType) { case OBJECT_AGGREGATE: - RenameAggregate(stmt->object, - (TypeName *) linitial(stmt->objarg), - stmt->newname); + RenameAggregate(stmt->object, stmt->objarg, stmt->newname); break; case OBJECT_CONVERSION: @@ -152,8 +150,12 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) switch (stmt->objectType) { case OBJECT_AGGREGATE: + AlterFunctionNamespace(stmt->object, stmt->objarg, true, + stmt->newschema); + break; + case OBJECT_FUNCTION: - AlterFunctionNamespace(stmt->object, stmt->objarg, + AlterFunctionNamespace(stmt->object, stmt->objarg, false, stmt->newschema); break; @@ -186,9 +188,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) switch (stmt->objectType) { case OBJECT_AGGREGATE: - AlterAggregateOwner(stmt->object, - (TypeName *) linitial(stmt->objarg), - newowner); + AlterAggregateOwner(stmt->object, stmt->objarg, newowner); break; case OBJECT_CONVERSION: @@ -204,6 +204,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) break; case OBJECT_OPERATOR: + Assert(list_length(stmt->objarg) == 2); AlterOperatorOwner(stmt->object, (TypeName *) linitial(stmt->objarg), (TypeName *) lsecond(stmt->objarg), diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 07d8278525..ec4762750f 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2006, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.88 2006/03/14 22:48:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.89 2006/04/15 17:45:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -868,28 +868,17 @@ CommentType(List *typename, char *comment) * * This routine is used to allow a user to provide comments on an * aggregate function. The aggregate function is determined by both - * its name and its argument type, which, with the comments are - * the three parameters handed to this routine. + * its name and its argument type(s). */ static void CommentAggregate(List *aggregate, List *arguments, char *comment) { - TypeName *aggtype = (TypeName *) linitial(arguments); - Oid baseoid, - oid; + Oid oid; - /* First, attempt to determine the base aggregate oid */ - if (aggtype) - baseoid = typenameTypeId(NULL, aggtype); - else - baseoid = ANYOID; - - /* Now, attempt to find the actual tuple in pg_proc */ - - oid = find_aggregate_func(aggregate, baseoid, false); + /* Look up function and make sure it's an aggregate */ + oid = LookupAggNameTypeNames(aggregate, arguments, false); /* Next, validate the user's attempt to comment */ - if (!pg_proc_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(aggregate)); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 1da1cf66cb..96929a0d6c 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.73 2006/03/14 22:48:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.74 2006/04/15 17:45:34 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -678,7 +678,7 @@ CreateFunction(CreateFunctionStmt *stmt) void RemoveFunction(RemoveFuncStmt *stmt) { - List *functionName = stmt->funcname; + List *functionName = stmt->name; List *argTypes = stmt->args; /* list of TypeName nodes */ Oid funcOid; HeapTuple tup; @@ -1440,10 +1440,13 @@ DropCastById(Oid castOid) } /* - * Execute ALTER FUNCTION SET SCHEMA + * Execute ALTER FUNCTION/AGGREGATE SET SCHEMA + * + * These commands are identical except for the lookup procedure, so share code. */ void -AlterFunctionNamespace(List *name, List *argtypes, const char *newschema) +AlterFunctionNamespace(List *name, List *argtypes, bool isagg, + const char *newschema) { Oid procOid; Oid oldNspOid; @@ -1455,7 +1458,10 @@ AlterFunctionNamespace(List *name, List *argtypes, const char *newschema) procRel = heap_open(ProcedureRelationId, RowExclusiveLock); /* get function OID */ - procOid = LookupFuncNameTypeNames(name, argtypes, false); + if (isagg) + procOid = LookupAggNameTypeNames(name, argtypes, false); + else + procOid = LookupFuncNameTypeNames(name, argtypes, false); /* check permissions on function */ if (!pg_proc_ownercheck(procOid, GetUserId())) diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index c40dbf9d82..54f50a8477 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.29 2006/03/14 22:48:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.30 2006/04/15 17:45:34 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -201,15 +201,16 @@ DefineOperator(List *names, List *parameters) * Deletes an operator. */ void -RemoveOperator(RemoveOperStmt *stmt) +RemoveOperator(RemoveFuncStmt *stmt) { - List *operatorName = stmt->opname; + List *operatorName = stmt->name; TypeName *typeName1 = (TypeName *) linitial(stmt->args); TypeName *typeName2 = (TypeName *) lsecond(stmt->args); Oid operOid; HeapTuple tup; ObjectAddress object; + Assert(list_length(stmt->args) == 2); operOid = LookupOperNameTypeNames(NULL, operatorName, typeName1, typeName2, false, -1); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index c7e2a7fff8..cd8ebe1f5d 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 - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.332 2006/03/23 00:19:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.333 2006/04/15 17:45:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1942,7 +1942,9 @@ _copyDefineStmt(DefineStmt *from) DefineStmt *newnode = makeNode(DefineStmt); COPY_SCALAR_FIELD(kind); + COPY_SCALAR_FIELD(oldstyle); COPY_NODE_FIELD(defnames); + COPY_NODE_FIELD(args); COPY_NODE_FIELD(definition); return newnode; @@ -2055,36 +2057,13 @@ _copyAlterFunctionStmt(AlterFunctionStmt *from) return newnode; } -static RemoveAggrStmt * -_copyRemoveAggrStmt(RemoveAggrStmt *from) -{ - RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt); - - COPY_NODE_FIELD(aggname); - COPY_NODE_FIELD(aggtype); - COPY_SCALAR_FIELD(behavior); - - return newnode; -} - static RemoveFuncStmt * _copyRemoveFuncStmt(RemoveFuncStmt *from) { RemoveFuncStmt *newnode = makeNode(RemoveFuncStmt); - COPY_NODE_FIELD(funcname); - COPY_NODE_FIELD(args); - COPY_SCALAR_FIELD(behavior); - - return newnode; -} - -static RemoveOperStmt * -_copyRemoveOperStmt(RemoveOperStmt *from) -{ - RemoveOperStmt *newnode = makeNode(RemoveOperStmt); - - COPY_NODE_FIELD(opname); + COPY_SCALAR_FIELD(kind); + COPY_NODE_FIELD(name); COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(behavior); @@ -3092,15 +3071,9 @@ copyObject(void *from) case T_AlterFunctionStmt: retval = _copyAlterFunctionStmt(from); break; - case T_RemoveAggrStmt: - retval = _copyRemoveAggrStmt(from); - break; case T_RemoveFuncStmt: retval = _copyRemoveFuncStmt(from); break; - case T_RemoveOperStmt: - retval = _copyRemoveOperStmt(from); - break; case T_RemoveOpClassStmt: retval = _copyRemoveOpClassStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 8d413b87c5..9aa0b399b7 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.268 2006/03/23 00:19:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.269 2006/04/15 17:45:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -909,7 +909,9 @@ static bool _equalDefineStmt(DefineStmt *a, DefineStmt *b) { COMPARE_SCALAR_FIELD(kind); + COMPARE_SCALAR_FIELD(oldstyle); COMPARE_NODE_FIELD(defnames); + COMPARE_NODE_FIELD(args); COMPARE_NODE_FIELD(definition); return true; @@ -1006,30 +1008,11 @@ _equalAlterFunctionStmt(AlterFunctionStmt *a, AlterFunctionStmt *b) return true; } -static bool -_equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b) -{ - COMPARE_NODE_FIELD(aggname); - COMPARE_NODE_FIELD(aggtype); - COMPARE_SCALAR_FIELD(behavior); - - return true; -} - static bool _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b) { - COMPARE_NODE_FIELD(funcname); - COMPARE_NODE_FIELD(args); - COMPARE_SCALAR_FIELD(behavior); - - return true; -} - -static bool -_equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b) -{ - COMPARE_NODE_FIELD(opname); + COMPARE_SCALAR_FIELD(kind); + COMPARE_NODE_FIELD(name); COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(behavior); @@ -2112,15 +2095,9 @@ equal(void *a, void *b) case T_AlterFunctionStmt: retval = _equalAlterFunctionStmt(a, b); break; - case T_RemoveAggrStmt: - retval = _equalRemoveAggrStmt(a, b); - break; case T_RemoveFuncStmt: retval = _equalRemoveFuncStmt(a, b); break; - case T_RemoveOperStmt: - retval = _equalRemoveOperStmt(a, b); - break; case T_RemoveOpClassStmt: retval = _equalRemoveOpClassStmt(a, b); break; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 43277e4587..1c1c07bd1b 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.537 2006/03/23 00:19:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.538 2006/04/15 17:45:34 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -224,8 +224,9 @@ static void doNegateFloat(Value *v); %type stmtblock stmtmulti OptTableElementList TableElementList OptInherit definition - opt_distinct opt_definition func_args - func_args_list func_as createfunc_opt_list alterfunc_opt_list + opt_distinct opt_definition func_args func_args_list + func_as createfunc_opt_list alterfunc_opt_list + aggr_args aggr_args_list old_aggr_definition old_aggr_list oper_argtypes RuleActionList RuleActionMulti opt_column_list columnList opt_name_list sort_clause opt_sort_clause sortby_list index_params @@ -246,7 +247,7 @@ static void doNegateFloat(Value *v); %type createfunc_opt_item common_func_opt_item %type func_arg %type arg_class -%type func_return func_type aggr_argtype +%type func_return func_type %type TriggerForType OptTemp %type OnCommitOption @@ -285,7 +286,7 @@ static void doNegateFloat(Value *v); %type TableElement ConstraintElem TableFuncElement %type columnDef -%type def_elem +%type def_elem old_aggr_elem %type def_arg columnElem where_clause a_expr b_expr c_expr func_expr AexprConst indirection_el columnref in_expr having_clause func_table array_expr @@ -2671,11 +2672,24 @@ DropAssertStmt: *****************************************************************************/ DefineStmt: - CREATE AGGREGATE func_name definition + CREATE AGGREGATE func_name aggr_args definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_AGGREGATE; + n->oldstyle = false; n->defnames = $3; + n->args = $4; + n->definition = $5; + $$ = (Node *)n; + } + | CREATE AGGREGATE func_name old_aggr_definition + { + /* old-style (pre-8.2) syntax for CREATE AGGREGATE */ + DefineStmt *n = makeNode(DefineStmt); + n->kind = OBJECT_AGGREGATE; + n->oldstyle = true; + n->defnames = $3; + n->args = NIL; n->definition = $4; $$ = (Node *)n; } @@ -2683,7 +2697,9 @@ DefineStmt: { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_OPERATOR; + n->oldstyle = false; n->defnames = $3; + n->args = NIL; n->definition = $4; $$ = (Node *)n; } @@ -2691,7 +2707,9 @@ DefineStmt: { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TYPE; + n->oldstyle = false; n->defnames = $3; + n->args = NIL; n->definition = $4; $$ = (Node *)n; } @@ -2700,7 +2718,9 @@ DefineStmt: /* Shell type (identified by lack of definition) */ DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TYPE; + n->oldstyle = false; n->defnames = $3; + n->args = NIL; n->definition = NIL; $$ = (Node *)n; } @@ -2764,6 +2784,28 @@ def_arg: func_type { $$ = (Node *)$1; } | Sconst { $$ = (Node *)makeString($1); } ; +aggr_args: '(' aggr_args_list ')' { $$ = $2; } + | '(' '*' ')' { $$ = NIL; } + ; + +aggr_args_list: + Typename { $$ = list_make1($1); } + | aggr_args_list ',' Typename { $$ = lappend($1, $3); } + ; + +old_aggr_definition: '(' old_aggr_list ')' { $$ = $2; } + ; + +old_aggr_list: old_aggr_elem { $$ = list_make1($1); } + | old_aggr_list ',' old_aggr_elem { $$ = lappend($1, $3); } + ; + +old_aggr_elem: IDENT '=' def_arg + { + $$ = makeDefElem($1, (Node *)$3); + } + ; + /***************************************************************************** * @@ -2960,7 +3002,7 @@ TruncateStmt: * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW | * CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT | * CAST | COLUMN | SCHEMA | TABLESPACE | ROLE ] | - * AGGREGATE () | + * AGGREGATE (arg1, ...) | * FUNCTION (arg1, arg2, ...) | * OPERATOR (leftoperand_typ, rightoperand_typ) | * TRIGGER ON | @@ -2980,14 +3022,13 @@ CommentStmt: n->comment = $6; $$ = (Node *) n; } - | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' - IS comment_text + | COMMENT ON AGGREGATE func_name aggr_args IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_AGGREGATE; n->objname = $4; - n->objargs = list_make1($6); - n->comment = $9; + n->objargs = $5; + n->comment = $7; $$ = (Node *) n; } | COMMENT ON FUNCTION func_name func_args IS comment_text @@ -3844,7 +3885,7 @@ opt_restrict: * QUERY: * * DROP FUNCTION funcname (arg1, arg2, ...) [ RESTRICT | CASCADE ] - * DROP AGGREGATE aggname (aggtype) [ RESTRICT | CASCADE ] + * DROP AGGREGATE aggname (arg1, ...) [ RESTRICT | CASCADE ] * DROP OPERATOR opname (leftoperand_typ, rightoperand_typ) [ RESTRICT | CASCADE ] * *****************************************************************************/ @@ -3853,7 +3894,8 @@ RemoveFuncStmt: DROP FUNCTION func_name func_args opt_drop_behavior { RemoveFuncStmt *n = makeNode(RemoveFuncStmt); - n->funcname = $3; + n->kind = OBJECT_FUNCTION; + n->name = $3; n->args = extractArgTypes($4); n->behavior = $5; $$ = (Node *)n; @@ -3861,26 +3903,23 @@ RemoveFuncStmt: ; RemoveAggrStmt: - DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior + DROP AGGREGATE func_name aggr_args opt_drop_behavior { - RemoveAggrStmt *n = makeNode(RemoveAggrStmt); - n->aggname = $3; - n->aggtype = $5; - n->behavior = $7; - $$ = (Node *)n; + RemoveFuncStmt *n = makeNode(RemoveFuncStmt); + n->kind = OBJECT_AGGREGATE; + n->name = $3; + n->args = $4; + n->behavior = $5; + $$ = (Node *)n; } ; -aggr_argtype: - Typename { $$ = $1; } - | '*' { $$ = NULL; } - ; - RemoveOperStmt: DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior { - RemoveOperStmt *n = makeNode(RemoveOperStmt); - n->opname = $3; + RemoveFuncStmt *n = makeNode(RemoveFuncStmt); + n->kind = OBJECT_OPERATOR; + n->name = $3; n->args = $5; n->behavior = $7; $$ = (Node *)n; @@ -4013,13 +4052,13 @@ opt_force: FORCE { $$ = TRUE; } * *****************************************************************************/ -RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name +RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = list_make1($5); - n->newname = $9; + n->objarg = $4; + n->newname = $7; $$ = (Node *)n; } | ALTER CONVERSION_P any_name RENAME TO name @@ -4153,13 +4192,13 @@ opt_column: COLUMN { $$ = COLUMN; } *****************************************************************************/ AlterObjectSchemaStmt: - ALTER AGGREGATE func_name '(' aggr_argtype ')' SET SCHEMA name + ALTER AGGREGATE func_name aggr_args SET SCHEMA name { AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); n->objectType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = list_make1($5); - n->newschema = $9; + n->objarg = $4; + n->newschema = $7; $$ = (Node *)n; } | ALTER DOMAIN_P any_name SET SCHEMA name @@ -4211,13 +4250,13 @@ AlterObjectSchemaStmt: * *****************************************************************************/ -AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO RoleId +AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = list_make1($5); - n->newowner = $9; + n->objarg = $4; + n->newowner = $7; $$ = (Node *)n; } | ALTER CONVERSION_P any_name OWNER TO RoleId diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 35e826881f..d7c04620b2 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.185 2006/03/14 22:48:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.186 2006/04/15 17:45:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1115,65 +1115,6 @@ func_signature_string(List *funcname, int nargs, const Oid *argtypes) nargs, argtypes); } -/* - * find_aggregate_func - * Convenience routine to check that a function exists and is an - * aggregate. - * - * Note: basetype is ANYOID if we are looking for an aggregate on - * all types. - */ -Oid -find_aggregate_func(List *aggname, Oid basetype, bool noError) -{ - Oid oid; - HeapTuple ftup; - Form_pg_proc pform; - - oid = LookupFuncName(aggname, 1, &basetype, true); - - if (!OidIsValid(oid)) - { - if (noError) - return InvalidOid; - if (basetype == ANYOID) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("aggregate %s(*) does not exist", - NameListToString(aggname)))); - else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("aggregate %s(%s) does not exist", - NameListToString(aggname), - format_type_be(basetype)))); - } - - /* Make sure it's an aggregate */ - ftup = SearchSysCache(PROCOID, - ObjectIdGetDatum(oid), - 0, 0, 0); - if (!HeapTupleIsValid(ftup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", oid); - pform = (Form_pg_proc) GETSTRUCT(ftup); - - if (!pform->proisagg) - { - ReleaseSysCache(ftup); - if (noError) - return InvalidOid; - /* we do not use the (*) notation for functions... */ - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function %s(%s) is not an aggregate", - NameListToString(aggname), format_type_be(basetype)))); - } - - ReleaseSysCache(ftup); - - return oid; -} - /* * LookupFuncName * Given a possibly-qualified function name and a set of argument types, @@ -1246,3 +1187,101 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) return LookupFuncName(funcname, argcount, argoids, noError); } + +/* + * LookupAggNameTypeNames + * Find an aggregate function given a name and list of TypeName nodes. + * + * This is almost like LookupFuncNameTypeNames, but the error messages refer + * to aggregates rather than plain functions, and we verify that the found + * function really is an aggregate, and we recognize the convention used by + * the grammar that agg(*) translates to a NIL list, which we have to treat + * as one ANY argument. (XXX this ought to be changed) + */ +Oid +LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) +{ + Oid argoids[FUNC_MAX_ARGS]; + int argcount; + int i; + ListCell *args_item; + Oid oid; + HeapTuple ftup; + Form_pg_proc pform; + + argcount = list_length(argtypes); + if (argcount > FUNC_MAX_ARGS) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("functions cannot have more than %d arguments", + FUNC_MAX_ARGS))); + + if (argcount == 0) + { + /* special case for agg(*) */ + argoids[0] = ANYOID; + argcount = 1; + } + else + { + args_item = list_head(argtypes); + for (i = 0; i < argcount; i++) + { + TypeName *t = (TypeName *) lfirst(args_item); + + argoids[i] = LookupTypeName(NULL, t); + + if (!OidIsValid(argoids[i])) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type \"%s\" does not exist", + TypeNameToString(t)))); + + args_item = lnext(args_item); + } + } + + oid = LookupFuncName(aggname, argcount, argoids, true); + + if (!OidIsValid(oid)) + { + if (noError) + return InvalidOid; + if (argcount == 1 && argoids[0] == ANYOID) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("aggregate %s(*) does not exist", + NameListToString(aggname)))); + else + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("aggregate %s does not exist", + func_signature_string(aggname, + argcount, argoids)))); + } + + /* Make sure it's an aggregate */ + ftup = SearchSysCache(PROCOID, + ObjectIdGetDatum(oid), + 0, 0, 0); + if (!HeapTupleIsValid(ftup)) /* should not happen */ + elog(ERROR, "cache lookup failed for function %u", oid); + pform = (Form_pg_proc) GETSTRUCT(ftup); + + if (!pform->proisagg) + { + ReleaseSysCache(ftup); + if (noError) + return InvalidOid; + /* we do not use the (*) notation for functions... */ + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function %s is not an aggregate", + func_signature_string(aggname, + argcount, argoids)))); + } + + ReleaseSysCache(ftup); + + return oid; +} diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 2a75ed24bb..b54d50702b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.255 2006/03/05 15:58:40 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.256 2006/04/15 17:45:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -333,7 +333,6 @@ check_xact_readonly(Node *parsetree) case T_CreateTrigStmt: case T_CompositeTypeStmt: case T_ViewStmt: - case T_RemoveAggrStmt: case T_DropCastStmt: case T_DropStmt: case T_DropdbStmt: @@ -341,7 +340,6 @@ check_xact_readonly(Node *parsetree) case T_RemoveFuncStmt: case T_DropRoleStmt: case T_DropPLangStmt: - case T_RemoveOperStmt: case T_RemoveOpClassStmt: case T_DropPropertyStmt: case T_GrantStmt: @@ -730,7 +728,7 @@ ProcessUtility(Node *parsetree, break; /* - * **************** object creation / destruction ****************** + * **************** object creation / destruction ***************** */ case T_DefineStmt: { @@ -739,12 +737,15 @@ ProcessUtility(Node *parsetree, switch (stmt->kind) { case OBJECT_AGGREGATE: - DefineAggregate(stmt->defnames, stmt->definition); + DefineAggregate(stmt->defnames, stmt->args, + stmt->oldstyle, stmt->definition); break; case OBJECT_OPERATOR: + Assert(stmt->args == NIL); DefineOperator(stmt->defnames, stmt->definition); break; case OBJECT_TYPE: + Assert(stmt->args == NIL); DefineType(stmt->defnames, stmt->definition); break; default: @@ -815,16 +816,27 @@ ProcessUtility(Node *parsetree, AlterSequence((AlterSeqStmt *) parsetree); break; - case T_RemoveAggrStmt: - RemoveAggregate((RemoveAggrStmt *) parsetree); - break; - case T_RemoveFuncStmt: - RemoveFunction((RemoveFuncStmt *) parsetree); - break; + { + RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree; - case T_RemoveOperStmt: - RemoveOperator((RemoveOperStmt *) parsetree); + switch (stmt->kind) + { + case OBJECT_FUNCTION: + RemoveFunction(stmt); + break; + case OBJECT_AGGREGATE: + RemoveAggregate(stmt); + break; + case OBJECT_OPERATOR: + RemoveOperator(stmt); + break; + default: + elog(ERROR, "unrecognized object type: %d", + (int) stmt->kind); + break; + } + } break; case T_CreatedbStmt: @@ -1576,16 +1588,21 @@ CreateCommandTag(Node *parsetree) tag = "ALTER SEQUENCE"; break; - case T_RemoveAggrStmt: - tag = "DROP AGGREGATE"; - break; - case T_RemoveFuncStmt: - tag = "DROP FUNCTION"; - break; - - case T_RemoveOperStmt: - tag = "DROP OPERATOR"; + switch (((RemoveFuncStmt *) parsetree)->kind) + { + case OBJECT_FUNCTION: + tag = "DROP FUNCTION"; + break; + case OBJECT_AGGREGATE: + tag = "DROP AGGREGATE"; + break; + case OBJECT_OPERATOR: + tag = "DROP OPERATOR"; + break; + default: + tag = "???"; + } break; case T_CreatedbStmt: diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 99e061d2de..f6ed06f3db 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.71 2006/03/05 15:58:55 momjian Exp $ + * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.72 2006/04/15 17:45:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,22 +57,23 @@ extern void AlterFunction(AlterFunctionStmt *stmt); extern void CreateCast(CreateCastStmt *stmt); extern void DropCast(DropCastStmt *stmt); extern void DropCastById(Oid castOid); -extern void AlterFunctionNamespace(List *name, List *argtypes, +extern void AlterFunctionNamespace(List *name, List *argtypes, bool isagg, const char *newschema); /* commands/operatorcmds.c */ extern void DefineOperator(List *names, List *parameters); -extern void RemoveOperator(RemoveOperStmt *stmt); +extern void RemoveOperator(RemoveFuncStmt *stmt); extern void RemoveOperatorById(Oid operOid); extern void AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typename2, Oid newOwnerId); extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId); /* commands/aggregatecmds.c */ -extern void DefineAggregate(List *names, List *parameters); -extern void RemoveAggregate(RemoveAggrStmt *stmt); -extern void RenameAggregate(List *name, TypeName *basetype, const char *newname); -extern void AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId); +extern void DefineAggregate(List *name, List *args, bool oldstyle, + List *parameters); +extern void RemoveAggregate(RemoveFuncStmt *stmt); +extern void RenameAggregate(List *name, List *args, const char *newname); +extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId); /* commands/opclasscmds.c */ extern void DefineOpClass(CreateOpClassStmt *stmt); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index b8415378d9..fe5ab018f5 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.184 2006/03/07 01:00:18 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.185 2006/04/15 17:45:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -241,9 +241,7 @@ typedef enum NodeTag T_IndexStmt, T_CreateFunctionStmt, T_AlterFunctionStmt, - T_RemoveAggrStmt, T_RemoveFuncStmt, - T_RemoveOperStmt, T_RenameStmt, T_RuleStmt, T_NotifyStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d6f7c4a95a..e4eb385df8 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.306 2006/03/23 00:19:30 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.307 2006/04/15 17:45:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1242,7 +1242,9 @@ typedef struct DefineStmt { NodeTag type; ObjectType kind; /* aggregate, operator, type */ + bool oldstyle; /* hack to signal old CREATE AGG syntax */ List *defnames; /* qualified name (list of Value strings) */ + List *args; /* a list of TypeName (if needed) */ List *definition; /* a list of DefElem */ } DefineStmt; @@ -1456,41 +1458,18 @@ typedef struct AlterFunctionStmt } AlterFunctionStmt; /* ---------------------- - * Drop Aggregate Statement - * ---------------------- - */ -typedef struct RemoveAggrStmt -{ - NodeTag type; - List *aggname; /* aggregate to drop */ - TypeName *aggtype; /* TypeName for input datatype, or NULL */ - DropBehavior behavior; /* RESTRICT or CASCADE behavior */ -} RemoveAggrStmt; - -/* ---------------------- - * Drop Function Statement + * Drop {Function|Aggregate|Operator} Statement * ---------------------- */ typedef struct RemoveFuncStmt { NodeTag type; - List *funcname; /* function to drop */ + ObjectType kind; /* function, aggregate, operator */ + List *name; /* qualified name of object to drop */ List *args; /* types of the arguments */ DropBehavior behavior; /* RESTRICT or CASCADE behavior */ } RemoveFuncStmt; -/* ---------------------- - * Drop Operator Statement - * ---------------------- - */ -typedef struct RemoveOperStmt -{ - NodeTag type; - List *opname; /* operator to drop */ - List *args; /* types of the arguments */ - DropBehavior behavior; /* RESTRICT or CASCADE behavior */ -} RemoveOperStmt; - /* ---------------------- * Drop Operator Class Statement * ---------------------- diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index 13aa706a04..486e5ea44d 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.55 2006/03/14 22:48:22 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.56 2006/04/15 17:45:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -72,11 +72,11 @@ extern const char *funcname_signature_string(const char *funcname, extern const char *func_signature_string(List *funcname, int nargs, const Oid *argtypes); -extern Oid find_aggregate_func(List *aggname, Oid basetype, bool noError); - extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError); extern Oid LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError); +extern Oid LookupAggNameTypeNames(List *aggname, List *argtypes, + bool noError); #endif /* PARSE_FUNC_H */ diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out index 8c97e4106b..ba5ecedc0a 100644 --- a/src/test/regress/expected/errors.out +++ b/src/test/regress/expected/errors.out @@ -133,7 +133,7 @@ ERROR: function int2um(integer) does not exist create aggregate newcnt1 (sfunc = int4inc, stype = int4, initcond = '0'); -ERROR: aggregate basetype must be specified +ERROR: aggregate input type must be specified -- -- DROP INDEX