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.
This commit is contained in:
Tom Lane 2006-04-15 17:45:46 +00:00
parent ebd5257d49
commit 3651a3e6fb
17 changed files with 395 additions and 351 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.33 2005/11/04 23:14:02 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.34 2006/04/15 17:45:18 tgl Exp $
PostgreSQL documentation
-->
@ -20,8 +20,18 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">input_data_type</replaceable> ) (
SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
[ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
)
or the old syntax
CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
BASETYPE = <replaceable class="PARAMETER">input_data_type</replaceable>,
BASETYPE = <replaceable class="PARAMETER">base_type</replaceable>,
SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
@ -87,7 +97,7 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
<para>
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
<type>text</type>, 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 <literal>&lt;</> operator is the proper sort
operator for <function>MIN</>, and <literal>&gt;</> is the proper sort
operator for <function>MAX</>. Note that the optimization will never
actually take effect unless the specified operator is the <quote>less than</quote> or
<quote>greater than</quote> strategy member of a B-tree index operator class.
actually take effect unless the specified operator is the <quote>less
than</quote> or <quote>greater than</quote> strategy member of a B-tree
index operator class.
</para>
</refsect1>
@ -170,13 +181,27 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
<listitem>
<para>
The input data type on which this aggregate function operates.
This can be specified as <literal>"ANY"</> for an aggregate that
This can be specified as <literal>*</> for an aggregate that
does not examine its input values (an example is
<function>count(*)</function>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">base_type</replaceable></term>
<listitem>
<para>
In the old syntax for <command>CREATE AGGREGATE</>, the input data type
is specified by a <literal>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 <literal>basetype</> as
<literal>"ANY"</> (not <literal>*</>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">sfunc</replaceable></term>
<listitem>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/xaggr.sgml,v 1.30 2006/03/10 19:10:49 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/xaggr.sgml,v 1.31 2006/04/15 17:45:33 tgl Exp $ -->
<sect1 id="xaggr">
<title>User-Defined Aggregates</title>
@ -43,23 +43,24 @@
The aggregate definition would be:
<screen>
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)
</screen>
(In practice, we'd just name the aggregate <function>sum</function> and rely on
<productname>PostgreSQL</productname> to figure out which kind
of sum to apply to a column of type <type>complex</type>.)
(Notice that we are relying on function overloading: there is more than
one aggregate named <function>sum</>, but
<productname>PostgreSQL</productname> can figure out which kind
of sum applies to a column of type <type>complex</type>.)
</para>
<para>
@ -99,9 +100,9 @@ SELECT complex_sum(a) FROM test_complex;
looks like:
<programlisting>
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 <xref linkend="extend-types-polymorphic">
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:
<programlisting>
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)
<programlisting>
if (fcinfo->context &amp;&amp; IsA(fcinfo->context, AggState))
</programlisting>
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 <emphasis>only</>
case where it is safe for a function to modify a pass-by-reference input.)

View File

@ -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),

View File

@ -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),

View File

@ -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));

View File

@ -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()))

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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 <list> 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 <defelt> createfunc_opt_item common_func_opt_item
%type <fun_param> func_arg
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type aggr_argtype
%type <typnam> func_return func_type
%type <boolean> TriggerForType OptTemp
%type <oncommit> OnCommitOption
@ -285,7 +286,7 @@ static void doNegateFloat(Value *v);
%type <node> TableElement ConstraintElem TableFuncElement
%type <node> columnDef
%type <defelt> def_elem
%type <defelt> def_elem old_aggr_elem
%type <node> 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 ] <objname> |
* AGGREGATE <aggname> (<aggtype>) |
* AGGREGATE <aggname> (arg1, ...) |
* FUNCTION <funcname> (arg1, arg2, ...) |
* OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
* TRIGGER <triggername> ON <relname> |
@ -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

View File

@ -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;
}

View File

@ -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:

View File

@ -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);

View File

@ -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,

View File

@ -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
* ----------------------

View File

@ -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 */

View File

@ -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