Commit e1e60694 authored by Tom Lane's avatar Tom Lane

Make CREATE AGGREGATE complain if the initcond is invalid for the datatype.

The initial transition value is stored as a text string and not fed to the
transition type's input function until runtime (so that values such as
"now" don't get frozen at creation time).  Previously, CREATE AGGREGATE
didn't do anything with it but that, which meant that even erroneous values
would be accepted and not complained of until the aggregate is used.  This
seems unhelpful, and it's confused at least one user, as in Rhys Stewart's
recent report.  It seems worth taking a few more cycles to invoke the input
function and verify that the value is acceptable.  We can't do this if the
transition type is polymorphic, but in normal aggregates we know the actual
transition type so we can call the right input function.
parent 70726354
...@@ -61,6 +61,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -61,6 +61,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
Oid *aggArgTypes; Oid *aggArgTypes;
int numArgs; int numArgs;
Oid transTypeId; Oid transTypeId;
char transTypeType;
ListCell *pl; ListCell *pl;
/* Convert list of names to a name and namespace */ /* Convert list of names to a name and namespace */
...@@ -181,7 +182,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -181,7 +182,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
* aggregate. * aggregate.
*/ */
transTypeId = typenameTypeId(NULL, transType); transTypeId = typenameTypeId(NULL, transType);
if (get_typtype(transTypeId) == TYPTYPE_PSEUDO && transTypeType = get_typtype(transTypeId);
if (transTypeType == TYPTYPE_PSEUDO &&
!IsPolymorphicType(transTypeId)) !IsPolymorphicType(transTypeId))
{ {
if (transTypeId == INTERNALOID && superuser()) if (transTypeId == INTERNALOID && superuser())
...@@ -193,6 +195,24 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -193,6 +195,24 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
format_type_be(transTypeId)))); format_type_be(transTypeId))));
} }
/*
* If we have an initval, and it's not for a pseudotype (particularly a
* polymorphic type), make sure it's acceptable to the type's input
* function. We will store the initval as text, because the input
* function isn't necessarily immutable (consider "now" for timestamp),
* and we want to use the runtime not creation-time interpretation of the
* value. However, if it's an incorrect value it seems much more
* user-friendly to complain at CREATE AGGREGATE time.
*/
if (initval && transTypeType != TYPTYPE_PSEUDO)
{
Oid typinput,
typioparam;
getTypeInputInfo(transTypeId, &typinput, &typioparam);
(void) OidInputFunctionCall(typinput, initval, typioparam, -1);
}
/* /*
* Most of the argument-checking is done inside of AggregateCreate * Most of the argument-checking is done inside of AggregateCreate
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment