1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-27 22:56:53 +03:00

Fix type-safety problem with parallel aggregate serial/deserialization.

The original specification for this called for the deserialization function
to have signature "deserialize(serialtype) returns transtype", which is a
security violation if transtype is INTERNAL (which it always would be in
practice) and serialtype is not (which ditto).  The patch blithely overrode
the opr_sanity check for that, which was sloppy-enough work in itself,
but the indisputable reason this cannot be allowed to stand is that CREATE
FUNCTION will reject such a signature and thus it'd be impossible for
extensions to create parallelizable aggregates.

The minimum fix to make the signature type-safe is to add a second, dummy
argument of type INTERNAL.  But to lock it down a bit more and make misuse
of INTERNAL-accepting functions less likely, let's get rid of the ability
to specify a "serialtype" for an aggregate and just say that the only
useful serialtype is BYTEA --- which, in practice, is the only interesting
value anyway, due to the usefulness of the send/recv infrastructure for
this purpose.  That means we only have to allow "serialize(internal)
returns bytea" and "deserialize(bytea, internal) returns internal" as
the signatures for these support functions.

In passing fix bogus signature of int4_avg_combine, which I found thanks
to adding an opr_sanity check on combinefunc signatures.

catversion bump due to removing pg_aggregate.aggserialtype and adjusting
signatures of assorted built-in functions.

David Rowley and Tom Lane

Discussion: <27247.1466185504@sss.pgh.pa.us>
This commit is contained in:
Tom Lane 2016-06-22 16:52:41 -04:00
parent e45e990e4b
commit f8ace5477e
18 changed files with 506 additions and 715 deletions

View File

@ -463,12 +463,6 @@
<entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
<entry>Data type of the aggregate function's internal transition (state) data</entry> <entry>Data type of the aggregate function's internal transition (state) data</entry>
</row> </row>
<row>
<entry><structfield>aggserialtype</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
<entry>Return data type of the aggregate function's serialization function (zero if none)</entry>
</row>
<row> <row>
<entry><structfield>aggtransspace</structfield></entry> <entry><structfield>aggtransspace</structfield></entry>
<entry><type>int4</type></entry> <entry><type>int4</type></entry>

View File

@ -30,7 +30,6 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
[ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ] [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
[ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ] [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
[ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
[ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
[ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
@ -50,10 +49,6 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
[ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ] [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , FINALFUNC_EXTRA ] [ , FINALFUNC_EXTRA ]
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
[ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
[ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
[ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
[ , HYPOTHETICAL ] [ , HYPOTHETICAL ]
[ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
@ -72,7 +67,6 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
[ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ] [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
[ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ] [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
[ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
[ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
[ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
@ -255,7 +249,7 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
To be able to create an aggregate function, you must To be able to create an aggregate function, you must
have <literal>USAGE</literal> privilege on the argument types, the state have <literal>USAGE</literal> privilege on the argument types, the state
type(s), and the return type, as well as <literal>EXECUTE</literal> type(s), and the return type, as well as <literal>EXECUTE</literal>
privilege on the transition and final functions. privilege on the supporting functions.
</para> </para>
</refsect1> </refsect1>
@ -412,38 +406,51 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
<term><replaceable class="PARAMETER">combinefunc</replaceable></term> <term><replaceable class="PARAMETER">combinefunc</replaceable></term>
<listitem> <listitem>
<para> <para>
The <replaceable class="PARAMETER">combinefunc</replaceable> may The <replaceable class="PARAMETER">combinefunc</replaceable> function
optionally be specified in order to allow the aggregate function to may optionally be specified to allow the aggregate function to support
support partial aggregation. This is a prerequisite to allow the partial aggregation. This is a prerequisite to allow the aggregate to
aggregate to participate in certain optimizations such as parallel participate in certain optimizations such as parallel aggregation.
aggregation.
</para> </para>
<para> <para>
This function can be thought of as an <replaceable class="PARAMETER"> If provided,
sfunc</replaceable>, where instead of acting upon individual input rows the <replaceable class="PARAMETER">combinefunc</replaceable> must
and adding these to the aggregate state, it adds other aggregate states combine two <replaceable class="PARAMETER">state_data_type</replaceable>
to the aggregate state. values, each containing the result of aggregation over some subset of
the input values, to produce a
new <replaceable class="PARAMETER">state_data_type</replaceable> that
represents the result of aggregating over both sets of inputs. This
function can be thought of as
an <replaceable class="PARAMETER">sfunc</replaceable>, where instead of
acting upon individual input rows and adding these to the aggregate
state, it adds another aggregate state to the aggregate state.
Typically, it is not possible to define
a <replaceable class="PARAMETER">combinefunc</replaceable> for aggregate
functions that are sensitive to the order of the input values, since the
relative ordering of the inputs that went into the subset states is
indeterminate.
</para> </para>
<para> <para>
The <replaceable class="PARAMETER">combinefunc</replaceable> must accept The <replaceable class="PARAMETER">combinefunc</replaceable> must accept
two arguments of <replaceable class="PARAMETER">state_data_type two arguments of
</replaceable> and return <replaceable class="PARAMETER">state_data_type the <replaceable class="PARAMETER">state_data_type</replaceable> and
</replaceable>. Optionally this function may be <quote>strict</quote>. In return a value of
this case the function will not be called when either of the input states the <replaceable class="PARAMETER">state_data_type</replaceable>.
are null. Optionally this function may be <quote>strict</quote>. In this case the
function will not be called when either of the input states are null;
the other state will be taken as the correct result.
</para> </para>
<para> <para>
For aggregate functions with an <literal>INTERNAL</literal> For aggregate functions
<replaceable class="PARAMETER">state_data_type</replaceable> the whose <replaceable class="PARAMETER">state_data_type</replaceable>
<replaceable class="PARAMETER">combinefunc</replaceable> must not be is <type>internal</type>,
<quote>strict</quote>. In this scenario the the <replaceable class="PARAMETER">combinefunc</replaceable> must not be
<replaceable class="PARAMETER">combinefunc</replaceable> must take charge strict. In this scenario
and ensure that the null states are handled correctly and that the state the <replaceable class="PARAMETER">combinefunc</replaceable> must ensure
being returned is a pointer to memory which belongs in the aggregate that null states are handled correctly and that the state being returned
memory context. is properly stored in the aggregate memory context.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -452,14 +459,13 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
<term><replaceable class="PARAMETER">serialfunc</replaceable></term> <term><replaceable class="PARAMETER">serialfunc</replaceable></term>
<listitem> <listitem>
<para> <para>
In order to allow aggregate functions with an <literal>INTERNAL</> An aggregate function
<replaceable class="PARAMETER">state_data_type</replaceable> to whose <replaceable class="PARAMETER">state_data_type</replaceable>
participate in parallel aggregation, the aggregate must have a valid is <type>internal</> can participate in parallel aggregation only if it
<replaceable class="PARAMETER">serialfunc</replaceable>, which must has a <replaceable class="PARAMETER">serialfunc</replaceable> function,
serialize the aggregate state into <replaceable class="PARAMETER"> which must serialize the aggregate state into a <type>bytea</> value for
serialtype</replaceable>. This function must take a single argument of transmission to another process. This function must take a single
<replaceable class="PARAMETER">state_data_type</replaceable> and return argument of type <type>internal</> and return type <type>bytea</>. A
<replaceable class="PARAMETER">serialtype</replaceable>. A
corresponding <replaceable class="PARAMETER">deserialfunc</replaceable> corresponding <replaceable class="PARAMETER">deserialfunc</replaceable>
is also required. is also required.
</para> </para>
@ -470,21 +476,12 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
<term><replaceable class="PARAMETER">deserialfunc</replaceable></term> <term><replaceable class="PARAMETER">deserialfunc</replaceable></term>
<listitem> <listitem>
<para> <para>
Deserializes a previously serialized aggregate state back into Deserialize a previously serialized aggregate state back into
<replaceable class="PARAMETER">state_data_type</replaceable>. This <replaceable class="PARAMETER">state_data_type</replaceable>. This
function must take a single argument of <replaceable class="PARAMETER"> function must take two arguments of types <type>bytea</>
serialtype</replaceable> and return <replaceable class="PARAMETER"> and <type>internal</>, and produce a result of type <type>internal</>.
state_data_type</replaceable>. (Note: the second, <type>internal</> argument is unused, but is required
</para> for type safety reasons.)
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">serialtype</replaceable></term>
<listitem>
<para>
The data type to into which an <literal>INTERNAL</literal> aggregate
state should be serialized.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -67,7 +67,6 @@ AggregateCreate(const char *aggName,
bool mfinalfnExtraArgs, bool mfinalfnExtraArgs,
List *aggsortopName, List *aggsortopName,
Oid aggTransType, Oid aggTransType,
Oid aggSerialType,
int32 aggTransSpace, int32 aggTransSpace,
Oid aggmTransType, Oid aggmTransType,
int32 aggmTransSpace, int32 aggmTransSpace,
@ -440,44 +439,42 @@ AggregateCreate(const char *aggName,
} }
/* /*
* Validate the serialization function, if present. We must ensure that * Validate the serialization function, if present.
* the return type of this function is the same as the specified
* serialType.
*/ */
if (aggserialfnName) if (aggserialfnName)
{ {
fnArgs[0] = aggTransType; fnArgs[0] = INTERNALOID;
serialfn = lookup_agg_function(aggserialfnName, 1, serialfn = lookup_agg_function(aggserialfnName, 1,
fnArgs, variadicArgType, fnArgs, variadicArgType,
&rettype); &rettype);
if (rettype != aggSerialType) if (rettype != BYTEAOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of serialization function %s is not %s", errmsg("return type of serialization function %s is not %s",
NameListToString(aggserialfnName), NameListToString(aggserialfnName),
format_type_be(aggSerialType)))); format_type_be(BYTEAOID))));
} }
/* /*
* Validate the deserialization function, if present. We must ensure that * Validate the deserialization function, if present.
* the return type of this function is the same as the transType.
*/ */
if (aggdeserialfnName) if (aggdeserialfnName)
{ {
fnArgs[0] = aggSerialType; fnArgs[0] = BYTEAOID;
fnArgs[1] = INTERNALOID; /* dummy argument for type safety */
deserialfn = lookup_agg_function(aggdeserialfnName, 1, deserialfn = lookup_agg_function(aggdeserialfnName, 2,
fnArgs, variadicArgType, fnArgs, variadicArgType,
&rettype); &rettype);
if (rettype != aggTransType) if (rettype != INTERNALOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of deserialization function %s is not %s", errmsg("return type of deserialization function %s is not %s",
NameListToString(aggdeserialfnName), NameListToString(aggdeserialfnName),
format_type_be(aggTransType)))); format_type_be(INTERNALOID))));
} }
/* /*
@ -661,7 +658,6 @@ AggregateCreate(const char *aggName,
values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs); values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop); values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType); values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
values[Anum_pg_aggregate_aggserialtype - 1] = ObjectIdGetDatum(aggSerialType);
values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace); values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType); values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace); values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
@ -688,8 +684,7 @@ AggregateCreate(const char *aggName,
* Create dependencies for the aggregate (above and beyond those already * Create dependencies for the aggregate (above and beyond those already
* made by ProcedureCreate). Note: we don't need an explicit dependency * made by ProcedureCreate). Note: we don't need an explicit dependency
* on aggTransType since we depend on it indirectly through transfn. * on aggTransType since we depend on it indirectly through transfn.
* Likewise for aggmTransType using the mtransfunc, and also for * Likewise for aggmTransType using the mtransfunc, if it exists.
* aggSerialType using the serialfn, if they exist.
*/ */
/* Depends on transition function */ /* Depends on transition function */

View File

@ -72,7 +72,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
List *sortoperatorName = NIL; List *sortoperatorName = NIL;
TypeName *baseType = NULL; TypeName *baseType = NULL;
TypeName *transType = NULL; TypeName *transType = NULL;
TypeName *serialType = NULL;
TypeName *mtransType = NULL; TypeName *mtransType = NULL;
int32 transSpace = 0; int32 transSpace = 0;
int32 mtransSpace = 0; int32 mtransSpace = 0;
@ -88,7 +87,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
List *parameterDefaults; List *parameterDefaults;
Oid variadicArgType; Oid variadicArgType;
Oid transTypeId; Oid transTypeId;
Oid serialTypeId = InvalidOid;
Oid mtransTypeId = InvalidOid; Oid mtransTypeId = InvalidOid;
char transTypeType; char transTypeType;
char mtransTypeType = 0; char mtransTypeType = 0;
@ -164,8 +162,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
} }
else if (pg_strcasecmp(defel->defname, "stype") == 0) else if (pg_strcasecmp(defel->defname, "stype") == 0)
transType = defGetTypeName(defel); transType = defGetTypeName(defel);
else if (pg_strcasecmp(defel->defname, "serialtype") == 0)
serialType = defGetTypeName(defel);
else if (pg_strcasecmp(defel->defname, "stype1") == 0) else if (pg_strcasecmp(defel->defname, "stype1") == 0)
transType = defGetTypeName(defel); transType = defGetTypeName(defel);
else if (pg_strcasecmp(defel->defname, "sspace") == 0) else if (pg_strcasecmp(defel->defname, "sspace") == 0)
@ -333,73 +329,25 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
format_type_be(transTypeId)))); format_type_be(transTypeId))));
} }
if (serialType) if (serialfuncName && deserialfuncName)
{ {
/* /*
* There's little point in having a serialization/deserialization * Serialization is only needed/allowed for transtype INTERNAL.
* function on aggregates that don't have an internal state, so let's
* just disallow this as it may help clear up any confusion or
* needless authoring of these functions.
*/ */
if (transTypeId != INTERNALOID) if (transTypeId != INTERNALOID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("a serialization type must only be specified when the aggregate transition data type is %s", errmsg("serialization functions may be specified only when the aggregate transition data type is %s",
format_type_be(INTERNALOID)))); format_type_be(INTERNALOID))));
serialTypeId = typenameTypeId(NULL, serialType);
if (get_typtype(mtransTypeId) == TYPTYPE_PSEUDO &&
!IsPolymorphicType(serialTypeId))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregate serialization data type cannot be %s",
format_type_be(serialTypeId))));
/*
* We disallow INTERNAL serialType as the whole point of the
* serialized types is to allow the aggregate state to be output, and
* we cannot output INTERNAL. This check, combined with the one above
* ensures that the trans type and serialization type are not the
* same.
*/
if (serialTypeId == INTERNALOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregate serialization data type cannot be %s",
format_type_be(serialTypeId))));
/*
* If serialType is specified then serialfuncName and deserialfuncName
* must be present; if not, then none of the serialization options
* should have been specified.
*/
if (serialfuncName == NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregate serialization function must be specified when serialization type is specified")));
if (deserialfuncName == NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregate deserialization function must be specified when serialization type is specified")));
} }
else else if (serialfuncName || deserialfuncName)
{ {
/* /*
* If serialization type was not specified then there shouldn't be a * Cannot specify one function without the other.
* serialization function.
*/ */
if (serialfuncName != NIL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must specify serialization type when specifying serialization function"))); errmsg("must specify both or neither of serialization and deserialization functions")));
/* likewise for the deserialization function */
if (deserialfuncName != NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must specify serialization type when specifying deserialization function")));
} }
/* /*
@ -493,7 +441,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
mfinalfuncExtraArgs, mfinalfuncExtraArgs,
sortoperatorName, /* sort operator name */ sortoperatorName, /* sort operator name */
transTypeId, /* transition data type */ transTypeId, /* transition data type */
serialTypeId, /* serialization data type */
transSpace, /* transition space */ transSpace, /* transition space */
mtransTypeId, /* transition data type */ mtransTypeId, /* transition data type */
mtransSpace, /* transition space */ mtransSpace, /* transition space */

View File

@ -514,10 +514,9 @@ static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
static void build_pertrans_for_aggref(AggStatePerTrans pertrans, static void build_pertrans_for_aggref(AggStatePerTrans pertrans,
AggState *aggsate, EState *estate, AggState *aggsate, EState *estate,
Aggref *aggref, Oid aggtransfn, Oid aggtranstype, Aggref *aggref, Oid aggtransfn, Oid aggtranstype,
Oid aggserialtype, Oid aggserialfn, Oid aggserialfn, Oid aggdeserialfn,
Oid aggdeserialfn, Datum initValue, Datum initValue, bool initValueIsNull,
bool initValueIsNull, Oid *inputTypes, Oid *inputTypes, int numArguments);
int numArguments);
static int find_compatible_peragg(Aggref *newagg, AggState *aggstate, static int find_compatible_peragg(Aggref *newagg, AggState *aggstate,
int lastaggno, List **same_input_transnos); int lastaggno, List **same_input_transnos);
static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
@ -996,6 +995,9 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
dsinfo->arg[0] = slot->tts_values[0]; dsinfo->arg[0] = slot->tts_values[0];
dsinfo->argnull[0] = slot->tts_isnull[0]; dsinfo->argnull[0] = slot->tts_isnull[0];
/* Dummy second argument for type-safety reasons */
dsinfo->arg[1] = PointerGetDatum(NULL);
dsinfo->argnull[1] = false;
/* /*
* We run the deserialization functions in per-input-tuple * We run the deserialization functions in per-input-tuple
@ -2669,8 +2671,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
AclResult aclresult; AclResult aclresult;
Oid transfn_oid, Oid transfn_oid,
finalfn_oid; finalfn_oid;
Oid serialtype_oid, Oid serialfn_oid,
serialfn_oid,
deserialfn_oid; deserialfn_oid;
Expr *finalfnexpr; Expr *finalfnexpr;
Oid aggtranstype; Oid aggtranstype;
@ -2740,7 +2741,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
else else
peragg->finalfn_oid = finalfn_oid = InvalidOid; peragg->finalfn_oid = finalfn_oid = InvalidOid;
serialtype_oid = InvalidOid;
serialfn_oid = InvalidOid; serialfn_oid = InvalidOid;
deserialfn_oid = InvalidOid; deserialfn_oid = InvalidOid;
@ -2753,13 +2753,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
{ {
/* /*
* The planner should only have generated an agg node with * The planner should only have generated an agg node with
* serialStates if every aggregate with an INTERNAL state has a * serialStates if every aggregate with an INTERNAL state has
* serialization type, serialization function and deserialization * serialization/deserialization functions. Verify that.
* function. Let's ensure it didn't mess that up.
*/ */
if (!OidIsValid(aggform->aggserialtype))
elog(ERROR, "serialtype not set during serialStates aggregation step");
if (!OidIsValid(aggform->aggserialfn)) if (!OidIsValid(aggform->aggserialfn))
elog(ERROR, "serialfunc not set during serialStates aggregation step"); elog(ERROR, "serialfunc not set during serialStates aggregation step");
@ -2768,17 +2764,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
/* serialization func only required when not finalizing aggs */ /* serialization func only required when not finalizing aggs */
if (!aggstate->finalizeAggs) if (!aggstate->finalizeAggs)
{
serialfn_oid = aggform->aggserialfn; serialfn_oid = aggform->aggserialfn;
serialtype_oid = aggform->aggserialtype;
}
/* deserialization func only required when combining states */ /* deserialization func only required when combining states */
if (aggstate->combineStates) if (aggstate->combineStates)
{
deserialfn_oid = aggform->aggdeserialfn; deserialfn_oid = aggform->aggdeserialfn;
serialtype_oid = aggform->aggserialtype;
}
} }
/* Check that aggregate owner has permission to call component fns */ /* Check that aggregate owner has permission to call component fns */
@ -2906,10 +2896,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
pertrans = &pertransstates[++transno]; pertrans = &pertransstates[++transno];
build_pertrans_for_aggref(pertrans, aggstate, estate, build_pertrans_for_aggref(pertrans, aggstate, estate,
aggref, transfn_oid, aggtranstype, aggref, transfn_oid, aggtranstype,
serialtype_oid, serialfn_oid, serialfn_oid, deserialfn_oid,
deserialfn_oid, initValue, initValue, initValueIsNull,
initValueIsNull, inputTypes, inputTypes, numArguments);
numArguments);
peragg->transno = transno; peragg->transno = transno;
} }
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
@ -2937,7 +2926,7 @@ static void
build_pertrans_for_aggref(AggStatePerTrans pertrans, build_pertrans_for_aggref(AggStatePerTrans pertrans,
AggState *aggstate, EState *estate, AggState *aggstate, EState *estate,
Aggref *aggref, Aggref *aggref,
Oid aggtransfn, Oid aggtranstype, Oid aggserialtype, Oid aggtransfn, Oid aggtranstype,
Oid aggserialfn, Oid aggdeserialfn, Oid aggserialfn, Oid aggdeserialfn,
Datum initValue, bool initValueIsNull, Datum initValue, bool initValueIsNull,
Oid *inputTypes, int numArguments) Oid *inputTypes, int numArguments)
@ -3065,10 +3054,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
if (OidIsValid(aggserialfn)) if (OidIsValid(aggserialfn))
{ {
build_aggregate_serialfn_expr(aggtranstype, build_aggregate_serialfn_expr(aggserialfn,
aggserialtype,
aggref->inputcollid,
aggserialfn,
&serialfnexpr); &serialfnexpr);
fmgr_info(aggserialfn, &pertrans->serialfn); fmgr_info(aggserialfn, &pertrans->serialfn);
fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn); fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
@ -3076,24 +3062,21 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
InitFunctionCallInfoData(pertrans->serialfn_fcinfo, InitFunctionCallInfoData(pertrans->serialfn_fcinfo,
&pertrans->serialfn, &pertrans->serialfn,
1, 1,
pertrans->aggCollation, InvalidOid,
(void *) aggstate, NULL); (void *) aggstate, NULL);
} }
if (OidIsValid(aggdeserialfn)) if (OidIsValid(aggdeserialfn))
{ {
build_aggregate_serialfn_expr(aggserialtype, build_aggregate_deserialfn_expr(aggdeserialfn,
aggtranstype,
aggref->inputcollid,
aggdeserialfn,
&deserialfnexpr); &deserialfnexpr);
fmgr_info(aggdeserialfn, &pertrans->deserialfn); fmgr_info(aggdeserialfn, &pertrans->deserialfn);
fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn); fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
InitFunctionCallInfoData(pertrans->deserialfn_fcinfo, InitFunctionCallInfoData(pertrans->deserialfn_fcinfo,
&pertrans->deserialfn, &pertrans->deserialfn,
1, 2,
pertrans->aggCollation, InvalidOid,
(void *) aggstate, NULL); (void *) aggstate, NULL);
} }

View File

@ -465,13 +465,11 @@ aggregates_allow_partial_walker(Node *node, partial_agg_context *context)
/* /*
* If we find any aggs with an internal transtype then we must check * If we find any aggs with an internal transtype then we must check
* that these have a serialization type, serialization func and * whether these have serialization/deserialization functions;
* deserialization func; otherwise, we set the maximum allowed type to * otherwise, we set the maximum allowed type to PAT_INTERNAL_ONLY.
* PAT_INTERNAL_ONLY.
*/ */
if (aggform->aggtranstype == INTERNALOID && if (aggform->aggtranstype == INTERNALOID &&
(!OidIsValid(aggform->aggserialtype) || (!OidIsValid(aggform->aggserialfn) ||
!OidIsValid(aggform->aggserialfn) ||
!OidIsValid(aggform->aggdeserialfn))) !OidIsValid(aggform->aggdeserialfn)))
context->allowedtype = PAT_INTERNAL_ONLY; context->allowedtype = PAT_INTERNAL_ONLY;

View File

@ -15,7 +15,7 @@
#include "postgres.h" #include "postgres.h"
#include "access/htup_details.h" #include "access/htup_details.h"
#include "catalog/pg_aggregate.h" #include "catalog/pg_type.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
#include "optimizer/tlist.h" #include "optimizer/tlist.h"
@ -766,8 +766,8 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
/* /*
* apply_partialaggref_adjustment * apply_partialaggref_adjustment
* Convert PathTarget to be suitable for a partial aggregate node. We simply * Convert PathTarget to be suitable for a partial aggregate node. We simply
* adjust any Aggref nodes found in the target and set the aggoutputtype to * adjust any Aggref nodes found in the target and set the aggoutputtype
* the aggtranstype or aggserialtype. This allows exprType() to return the * appropriately. This allows exprType() to return the
* actual type that will be produced. * actual type that will be produced.
* *
* Note: We expect 'target' to be a flat target list and not have Aggrefs buried * Note: We expect 'target' to be a flat target list and not have Aggrefs buried
@ -784,40 +784,29 @@ apply_partialaggref_adjustment(PathTarget *target)
if (IsA(aggref, Aggref)) if (IsA(aggref, Aggref))
{ {
HeapTuple aggTuple;
Form_pg_aggregate aggform;
Aggref *newaggref; Aggref *newaggref;
aggTuple = SearchSysCache1(AGGFNOID,
ObjectIdGetDatum(aggref->aggfnoid));
if (!HeapTupleIsValid(aggTuple))
elog(ERROR, "cache lookup failed for aggregate %u",
aggref->aggfnoid);
aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
newaggref = (Aggref *) copyObject(aggref); newaggref = (Aggref *) copyObject(aggref);
/* /*
* Use the serialization type, if one exists. Note that we don't * Normally, a partial aggregate returns the aggregate's
* support it being a polymorphic type. (XXX really we ought to * transition type, but if that's INTERNAL, it returns BYTEA
* hardwire this as INTERNAL -> BYTEA, and avoid a catalog lookup * instead. (XXX this assumes we're doing parallel aggregate with
* here altogether?) * serialization; later we might need an argument to tell this
* function whether we're doing parallel or just local partial
* aggregation.)
*/ */
if (OidIsValid(aggform->aggserialtype))
newaggref->aggoutputtype = aggform->aggserialtype;
else
{
/* Otherwise, we return the aggregate's transition type */
Assert(OidIsValid(newaggref->aggtranstype)); Assert(OidIsValid(newaggref->aggtranstype));
if (newaggref->aggtranstype == INTERNALOID)
newaggref->aggoutputtype = BYTEAOID;
else
newaggref->aggoutputtype = newaggref->aggtranstype; newaggref->aggoutputtype = newaggref->aggtranstype;
}
/* flag it as partial */ /* flag it as partial */
newaggref->aggpartial = true; newaggref->aggpartial = true;
lfirst(lc) = newaggref; lfirst(lc) = newaggref;
ReleaseSysCache(aggTuple);
} }
} }
} }

View File

@ -71,6 +71,8 @@ static bool finalize_grouping_exprs_walker(Node *node,
check_ungrouped_columns_context *context); check_ungrouped_columns_context *context);
static void check_agglevels_and_constraints(ParseState *pstate, Node *expr); static void check_agglevels_and_constraints(ParseState *pstate, Node *expr);
static List *expand_groupingset_node(GroupingSet *gs); static List *expand_groupingset_node(GroupingSet *gs);
static Node *make_agg_arg(Oid argtype, Oid argcollation);
/* /*
* transformAggregateCall - * transformAggregateCall -
@ -1863,37 +1865,19 @@ build_aggregate_transfn_expr(Oid *agg_input_types,
Expr **transfnexpr, Expr **transfnexpr,
Expr **invtransfnexpr) Expr **invtransfnexpr)
{ {
Param *argp;
List *args; List *args;
FuncExpr *fexpr; FuncExpr *fexpr;
int i; int i;
/* /*
* Build arg list to use in the transfn FuncExpr node. We really only care * Build arg list to use in the transfn FuncExpr node.
* that transfn can discover the actual argument types at runtime using
* get_fn_expr_argtype(), so it's okay to use Param nodes that don't
* correspond to any real Param.
*/ */
argp = makeNode(Param); args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
argp->paramkind = PARAM_EXEC;
argp->paramid = -1;
argp->paramtype = agg_state_type;
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
args = list_make1(argp);
for (i = agg_num_direct_inputs; i < agg_num_inputs; i++) for (i = agg_num_direct_inputs; i < agg_num_inputs; i++)
{ {
argp = makeNode(Param); args = lappend(args,
argp->paramkind = PARAM_EXEC; make_agg_arg(agg_input_types[i], agg_input_collation));
argp->paramid = -1;
argp->paramtype = agg_input_types[i];
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
args = lappend(args, argp);
} }
fexpr = makeFuncExpr(transfn_oid, fexpr = makeFuncExpr(transfn_oid,
@ -1936,20 +1920,13 @@ build_aggregate_combinefn_expr(Oid agg_state_type,
Oid combinefn_oid, Oid combinefn_oid,
Expr **combinefnexpr) Expr **combinefnexpr)
{ {
Param *argp; Node *argp;
List *args; List *args;
FuncExpr *fexpr; FuncExpr *fexpr;
/* Build arg list to use in the combinefn FuncExpr node. */ /* combinefn takes two arguments of the aggregate state type */
argp = makeNode(Param); argp = make_agg_arg(agg_state_type, agg_input_collation);
argp->paramkind = PARAM_EXEC;
argp->paramid = -1;
argp->paramtype = agg_state_type;
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
/* transition state type is arg 1 and 2 */
args = list_make2(argp, argp); args = list_make2(argp, argp);
fexpr = makeFuncExpr(combinefn_oid, fexpr = makeFuncExpr(combinefn_oid,
@ -1958,49 +1935,57 @@ build_aggregate_combinefn_expr(Oid agg_state_type,
InvalidOid, InvalidOid,
agg_input_collation, agg_input_collation,
COERCE_EXPLICIT_CALL); COERCE_EXPLICIT_CALL);
fexpr->funcvariadic = false; /* combinefn is currently never treated as variadic */
*combinefnexpr = (Expr *) fexpr; *combinefnexpr = (Expr *) fexpr;
} }
/* /*
* Like build_aggregate_transfn_expr, but creates an expression tree for the * Like build_aggregate_transfn_expr, but creates an expression tree for the
* serialization or deserialization function of an aggregate, rather than the * serialization function of an aggregate.
* transition function. This may be used for either the serialization or
* deserialization function by swapping the first two parameters over.
*/ */
void void
build_aggregate_serialfn_expr(Oid agg_input_type, build_aggregate_serialfn_expr(Oid serialfn_oid,
Oid agg_output_type,
Oid agg_input_collation,
Oid serialfn_oid,
Expr **serialfnexpr) Expr **serialfnexpr)
{ {
Param *argp;
List *args; List *args;
FuncExpr *fexpr; FuncExpr *fexpr;
/* Build arg list to use in the FuncExpr node. */ /* serialfn always takes INTERNAL and returns BYTEA */
argp = makeNode(Param); args = list_make1(make_agg_arg(INTERNALOID, InvalidOid));
argp->paramkind = PARAM_EXEC;
argp->paramid = -1;
argp->paramtype = agg_input_type;
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
/* takes a single arg of the agg_input_type */
args = list_make1(argp);
fexpr = makeFuncExpr(serialfn_oid, fexpr = makeFuncExpr(serialfn_oid,
agg_output_type, BYTEAOID,
args, args,
InvalidOid, InvalidOid,
agg_input_collation, InvalidOid,
COERCE_EXPLICIT_CALL); COERCE_EXPLICIT_CALL);
fexpr->funcvariadic = false;
*serialfnexpr = (Expr *) fexpr; *serialfnexpr = (Expr *) fexpr;
} }
/*
* Like build_aggregate_transfn_expr, but creates an expression tree for the
* deserialization function of an aggregate.
*/
void
build_aggregate_deserialfn_expr(Oid deserialfn_oid,
Expr **deserialfnexpr)
{
List *args;
FuncExpr *fexpr;
/* deserialfn always takes BYTEA, INTERNAL and returns INTERNAL */
args = list_make2(make_agg_arg(BYTEAOID, InvalidOid),
make_agg_arg(INTERNALOID, InvalidOid));
fexpr = makeFuncExpr(deserialfn_oid,
INTERNALOID,
args,
InvalidOid,
InvalidOid,
COERCE_EXPLICIT_CALL);
*deserialfnexpr = (Expr *) fexpr;
}
/* /*
* Like build_aggregate_transfn_expr, but creates an expression tree for the * Like build_aggregate_transfn_expr, but creates an expression tree for the
* final function of an aggregate, rather than the transition function. * final function of an aggregate, rather than the transition function.
@ -2014,33 +1999,19 @@ build_aggregate_finalfn_expr(Oid *agg_input_types,
Oid finalfn_oid, Oid finalfn_oid,
Expr **finalfnexpr) Expr **finalfnexpr)
{ {
Param *argp;
List *args; List *args;
int i; int i;
/* /*
* Build expr tree for final function * Build expr tree for final function
*/ */
argp = makeNode(Param); args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
argp->paramkind = PARAM_EXEC;
argp->paramid = -1;
argp->paramtype = agg_state_type;
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
args = list_make1(argp);
/* finalfn may take additional args, which match agg's input types */ /* finalfn may take additional args, which match agg's input types */
for (i = 0; i < num_finalfn_inputs - 1; i++) for (i = 0; i < num_finalfn_inputs - 1; i++)
{ {
argp = makeNode(Param); args = lappend(args,
argp->paramkind = PARAM_EXEC; make_agg_arg(agg_input_types[i], agg_input_collation));
argp->paramid = -1;
argp->paramtype = agg_input_types[i];
argp->paramtypmod = -1;
argp->paramcollid = agg_input_collation;
argp->location = -1;
args = lappend(args, argp);
} }
*finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid, *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
@ -2051,3 +2022,24 @@ build_aggregate_finalfn_expr(Oid *agg_input_types,
COERCE_EXPLICIT_CALL); COERCE_EXPLICIT_CALL);
/* finalfn is currently never treated as variadic */ /* finalfn is currently never treated as variadic */
} }
/*
* Convenience function to build dummy argument expressions for aggregates.
*
* We really only care that an aggregate support function can discover its
* actual argument types at runtime using get_fn_expr_argtype(), so it's okay
* to use Param nodes that don't correspond to any real Param.
*/
static Node *
make_agg_arg(Oid argtype, Oid argcollation)
{
Param *argp = makeNode(Param);
argp->paramkind = PARAM_EXEC;
argp->paramid = -1;
argp->paramtype = argtype;
argp->paramtypmod = -1;
argp->paramcollid = argcollation;
argp->location = -1;
return (Node *) argp;
}

View File

@ -3510,10 +3510,7 @@ numeric_avg_combine(PG_FUNCTION_ARGS)
/* /*
* numeric_avg_serialize * numeric_avg_serialize
* Serialize NumericAggState for numeric aggregates that don't require * Serialize NumericAggState for numeric aggregates that don't require
* sumX2. Serializes NumericAggState into bytea using the standard pq API. * sumX2.
*
* numeric_avg_deserialize(numeric_avg_serialize(state)) must result in a state
* which matches the original input state.
*/ */
Datum Datum
numeric_avg_serialize(PG_FUNCTION_ARGS) numeric_avg_serialize(PG_FUNCTION_ARGS)
@ -3565,16 +3562,12 @@ numeric_avg_serialize(PG_FUNCTION_ARGS)
/* /*
* numeric_avg_deserialize * numeric_avg_deserialize
* Deserialize bytea into NumericAggState for numeric aggregates that * Deserialize bytea into NumericAggState for numeric aggregates that
* don't require sumX2. Deserializes bytea into NumericAggState using the * don't require sumX2.
* standard pq API.
*
* numeric_avg_serialize(numeric_avg_deserialize(bytea)) must result in a value
* which matches the original bytea value.
*/ */
Datum Datum
numeric_avg_deserialize(PG_FUNCTION_ARGS) numeric_avg_deserialize(PG_FUNCTION_ARGS)
{ {
bytea *sstate = PG_GETARG_BYTEA_P(0); bytea *sstate;
NumericAggState *result; NumericAggState *result;
Datum temp; Datum temp;
StringInfoData buf; StringInfoData buf;
@ -3582,6 +3575,8 @@ numeric_avg_deserialize(PG_FUNCTION_ARGS)
if (!AggCheckCallContext(fcinfo, NULL)) if (!AggCheckCallContext(fcinfo, NULL))
elog(ERROR, "aggregate function called in non-aggregate context"); elog(ERROR, "aggregate function called in non-aggregate context");
sstate = PG_GETARG_BYTEA_P(0);
/* /*
* Copy the bytea into a StringInfo so that we can "receive" it using the * Copy the bytea into a StringInfo so that we can "receive" it using the
* standard pq API. * standard pq API.
@ -3619,11 +3614,7 @@ numeric_avg_deserialize(PG_FUNCTION_ARGS)
/* /*
* numeric_serialize * numeric_serialize
* Serialization function for NumericAggState for numeric aggregates that * Serialization function for NumericAggState for numeric aggregates that
* require sumX2. Serializes NumericAggState into bytea using the standard * require sumX2.
* pq API.
*
* numeric_deserialize(numeric_serialize(state)) must result in a state which
* matches the original input state.
*/ */
Datum Datum
numeric_serialize(PG_FUNCTION_ARGS) numeric_serialize(PG_FUNCTION_ARGS)
@ -3683,16 +3674,12 @@ numeric_serialize(PG_FUNCTION_ARGS)
/* /*
* numeric_deserialize * numeric_deserialize
* Deserialization function for NumericAggState for numeric aggregates that * Deserialization function for NumericAggState for numeric aggregates that
* require sumX2. Deserializes bytea into into NumericAggState using the * require sumX2.
* standard pq API.
*
* numeric_serialize(numeric_deserialize(bytea)) must result in a value which
* matches the original bytea value.
*/ */
Datum Datum
numeric_deserialize(PG_FUNCTION_ARGS) numeric_deserialize(PG_FUNCTION_ARGS)
{ {
bytea *sstate = PG_GETARG_BYTEA_P(0); bytea *sstate;
NumericAggState *result; NumericAggState *result;
Datum temp; Datum temp;
StringInfoData buf; StringInfoData buf;
@ -3700,6 +3687,8 @@ numeric_deserialize(PG_FUNCTION_ARGS)
if (!AggCheckCallContext(fcinfo, NULL)) if (!AggCheckCallContext(fcinfo, NULL))
elog(ERROR, "aggregate function called in non-aggregate context"); elog(ERROR, "aggregate function called in non-aggregate context");
sstate = PG_GETARG_BYTEA_P(0);
/* /*
* Copy the bytea into a StringInfo so that we can "receive" it using the * Copy the bytea into a StringInfo so that we can "receive" it using the
* standard pq API. * standard pq API.
@ -3992,11 +3981,8 @@ numeric_poly_combine(PG_FUNCTION_ARGS)
/* /*
* numeric_poly_serialize * numeric_poly_serialize
* Serialize PolyNumAggState into bytea using the standard pq API for * Serialize PolyNumAggState into bytea for aggregate functions which
* aggregate functions which require sumX2. * require sumX2.
*
* numeric_poly_deserialize(numeric_poly_serialize(state)) must result in a
* state which matches the original input state.
*/ */
Datum Datum
numeric_poly_serialize(PG_FUNCTION_ARGS) numeric_poly_serialize(PG_FUNCTION_ARGS)
@ -4067,16 +4053,13 @@ numeric_poly_serialize(PG_FUNCTION_ARGS)
/* /*
* numeric_poly_deserialize * numeric_poly_deserialize
* Deserialize PolyNumAggState from bytea using the standard pq API for * Deserialize PolyNumAggState from bytea for aggregate functions which
* aggregate functions which require sumX2. * require sumX2.
*
* numeric_poly_serialize(numeric_poly_deserialize(bytea)) must result in a
* state which matches the original input state.
*/ */
Datum Datum
numeric_poly_deserialize(PG_FUNCTION_ARGS) numeric_poly_deserialize(PG_FUNCTION_ARGS)
{ {
bytea *sstate = PG_GETARG_BYTEA_P(0); bytea *sstate;
PolyNumAggState *result; PolyNumAggState *result;
Datum sumX; Datum sumX;
Datum sumX2; Datum sumX2;
@ -4085,6 +4068,8 @@ numeric_poly_deserialize(PG_FUNCTION_ARGS)
if (!AggCheckCallContext(fcinfo, NULL)) if (!AggCheckCallContext(fcinfo, NULL))
elog(ERROR, "aggregate function called in non-aggregate context"); elog(ERROR, "aggregate function called in non-aggregate context");
sstate = PG_GETARG_BYTEA_P(0);
/* /*
* Copy the bytea into a StringInfo so that we can "receive" it using the * Copy the bytea into a StringInfo so that we can "receive" it using the
* standard pq API. * standard pq API.
@ -4226,9 +4211,6 @@ int8_avg_combine(PG_FUNCTION_ARGS)
/* /*
* int8_avg_serialize * int8_avg_serialize
* Serialize PolyNumAggState into bytea using the standard pq API. * Serialize PolyNumAggState into bytea using the standard pq API.
*
* int8_avg_deserialize(int8_avg_serialize(state)) must result in a state which
* matches the original input state.
*/ */
Datum Datum
int8_avg_serialize(PG_FUNCTION_ARGS) int8_avg_serialize(PG_FUNCTION_ARGS)
@ -4286,14 +4268,11 @@ int8_avg_serialize(PG_FUNCTION_ARGS)
/* /*
* int8_avg_deserialize * int8_avg_deserialize
* Deserialize bytea back into PolyNumAggState. * Deserialize bytea back into PolyNumAggState.
*
* int8_avg_serialize(int8_avg_deserialize(bytea)) must result in a value which
* matches the original bytea value.
*/ */
Datum Datum
int8_avg_deserialize(PG_FUNCTION_ARGS) int8_avg_deserialize(PG_FUNCTION_ARGS)
{ {
bytea *sstate = PG_GETARG_BYTEA_P(0); bytea *sstate;
PolyNumAggState *result; PolyNumAggState *result;
StringInfoData buf; StringInfoData buf;
Datum temp; Datum temp;
@ -4301,6 +4280,8 @@ int8_avg_deserialize(PG_FUNCTION_ARGS)
if (!AggCheckCallContext(fcinfo, NULL)) if (!AggCheckCallContext(fcinfo, NULL))
elog(ERROR, "aggregate function called in non-aggregate context"); elog(ERROR, "aggregate function called in non-aggregate context");
sstate = PG_GETARG_BYTEA_P(0);
/* /*
* Copy the bytea into a StringInfo so that we can "receive" it using the * Copy the bytea into a StringInfo so that we can "receive" it using the
* standard pq API. * standard pq API.

View File

@ -13412,7 +13412,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
int i_aggsortop; int i_aggsortop;
int i_hypothetical; int i_hypothetical;
int i_aggtranstype; int i_aggtranstype;
int i_aggserialtype;
int i_aggtransspace; int i_aggtransspace;
int i_aggmtranstype; int i_aggmtranstype;
int i_aggmtransspace; int i_aggmtransspace;
@ -13434,7 +13433,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
char *aggsortconvop; char *aggsortconvop;
bool hypothetical; bool hypothetical;
const char *aggtranstype; const char *aggtranstype;
const char *aggserialtype;
const char *aggtransspace; const char *aggtransspace;
const char *aggmtranstype; const char *aggmtranstype;
const char *aggmtransspace; const char *aggmtransspace;
@ -13465,7 +13463,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
"aggfinalextra, aggmfinalextra, " "aggfinalextra, aggmfinalextra, "
"aggsortop::pg_catalog.regoperator, " "aggsortop::pg_catalog.regoperator, "
"aggserialtype::pg_catalog.regtype, "
"(aggkind = 'h') AS hypothetical, " "(aggkind = 'h') AS hypothetical, "
"aggtransspace, agginitval, " "aggtransspace, agginitval, "
"aggmtransspace, aggminitval, " "aggmtransspace, aggminitval, "
@ -13487,7 +13484,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
"aggfinalextra, aggmfinalextra, " "aggfinalextra, aggmfinalextra, "
"aggsortop::pg_catalog.regoperator, " "aggsortop::pg_catalog.regoperator, "
"0 AS aggserialtype, "
"(aggkind = 'h') AS hypothetical, " "(aggkind = 'h') AS hypothetical, "
"aggtransspace, agginitval, " "aggtransspace, agginitval, "
"aggmtransspace, aggminitval, " "aggmtransspace, aggminitval, "
@ -13509,7 +13505,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"0 AS aggmtranstype, false AS aggfinalextra, " "0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, " "false AS aggmfinalextra, "
"aggsortop::pg_catalog.regoperator, " "aggsortop::pg_catalog.regoperator, "
"0 AS aggserialtype, "
"false AS hypothetical, " "false AS hypothetical, "
"0 AS aggtransspace, agginitval, " "0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, " "0 AS aggmtransspace, NULL AS aggminitval, "
@ -13531,7 +13526,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"0 AS aggmtranstype, false AS aggfinalextra, " "0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, " "false AS aggmfinalextra, "
"aggsortop::pg_catalog.regoperator, " "aggsortop::pg_catalog.regoperator, "
"0 AS aggserialtype, "
"false AS hypothetical, " "false AS hypothetical, "
"0 AS aggtransspace, agginitval, " "0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, " "0 AS aggmtransspace, NULL AS aggminitval, "
@ -13550,7 +13544,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, " "0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, 0 AS aggsortop, " "false AS aggmfinalextra, 0 AS aggsortop, "
"0 AS aggserialtype, "
"false AS hypothetical, " "false AS hypothetical, "
"0 AS aggtransspace, agginitval, " "0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, " "0 AS aggmtransspace, NULL AS aggminitval, "
@ -13569,7 +13562,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, " "0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, 0 AS aggsortop, " "false AS aggmfinalextra, 0 AS aggsortop, "
"0 AS aggserialtype, "
"false AS hypothetical, " "false AS hypothetical, "
"0 AS aggtransspace, agginitval, " "0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, " "0 AS aggmtransspace, NULL AS aggminitval, "
@ -13588,7 +13580,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, " "0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, 0 AS aggsortop, " "false AS aggmfinalextra, 0 AS aggsortop, "
"0 AS aggserialtype, "
"false AS hypothetical, " "false AS hypothetical, "
"0 AS aggtransspace, agginitval1 AS agginitval, " "0 AS aggtransspace, agginitval1 AS agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, " "0 AS aggmtransspace, NULL AS aggminitval, "
@ -13611,7 +13602,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
i_aggfinalextra = PQfnumber(res, "aggfinalextra"); i_aggfinalextra = PQfnumber(res, "aggfinalextra");
i_aggmfinalextra = PQfnumber(res, "aggmfinalextra"); i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
i_aggsortop = PQfnumber(res, "aggsortop"); i_aggsortop = PQfnumber(res, "aggsortop");
i_aggserialtype = PQfnumber(res, "aggserialtype");
i_hypothetical = PQfnumber(res, "hypothetical"); i_hypothetical = PQfnumber(res, "hypothetical");
i_aggtranstype = PQfnumber(res, "aggtranstype"); i_aggtranstype = PQfnumber(res, "aggtranstype");
i_aggtransspace = PQfnumber(res, "aggtransspace"); i_aggtransspace = PQfnumber(res, "aggtransspace");
@ -13635,7 +13625,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
aggsortop = PQgetvalue(res, 0, i_aggsortop); aggsortop = PQgetvalue(res, 0, i_aggsortop);
hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't'); hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't');
aggtranstype = PQgetvalue(res, 0, i_aggtranstype); aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
aggserialtype = PQgetvalue(res, 0, i_aggserialtype);
aggtransspace = PQgetvalue(res, 0, i_aggtransspace); aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype); aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
aggmtransspace = PQgetvalue(res, 0, i_aggmtransspace); aggmtransspace = PQgetvalue(res, 0, i_aggmtransspace);
@ -13722,20 +13711,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
} }
if (strcmp(aggcombinefn, "-") != 0) if (strcmp(aggcombinefn, "-") != 0)
{
appendPQExpBuffer(details, ",\n COMBINEFUNC = %s", aggcombinefn); appendPQExpBuffer(details, ",\n COMBINEFUNC = %s", aggcombinefn);
}
/*
* CREATE AGGREGATE should ensure we either have all of these, or none of
* them.
*/
if (strcmp(aggserialfn, "-") != 0) if (strcmp(aggserialfn, "-") != 0)
{
appendPQExpBuffer(details, ",\n SERIALFUNC = %s", aggserialfn); appendPQExpBuffer(details, ",\n SERIALFUNC = %s", aggserialfn);
if (strcmp(aggdeserialfn, "-") != 0)
appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn); appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn);
appendPQExpBuffer(details, ",\n SERIALTYPE = %s", aggserialtype);
}
if (strcmp(aggmtransfn, "-") != 0) if (strcmp(aggmtransfn, "-") != 0)
{ {

View File

@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201606171 #define CATALOG_VERSION_NO 201606221
#endif #endif

View File

@ -34,8 +34,8 @@
* aggtransfn transition function * aggtransfn transition function
* aggfinalfn final function (0 if none) * aggfinalfn final function (0 if none)
* aggcombinefn combine function (0 if none) * aggcombinefn combine function (0 if none)
* aggserialfn function to convert transtype to serialtype (0 if none) * aggserialfn function to convert transtype to bytea (0 if none)
* aggdeserialfn function to convert serialtype to transtype (0 if none) * aggdeserialfn function to convert bytea to transtype (0 if none)
* aggmtransfn forward function for moving-aggregate mode (0 if none) * aggmtransfn forward function for moving-aggregate mode (0 if none)
* aggminvtransfn inverse function for moving-aggregate mode (0 if none) * aggminvtransfn inverse function for moving-aggregate mode (0 if none)
* aggmfinalfn final function for moving-aggregate mode (0 if none) * aggmfinalfn final function for moving-aggregate mode (0 if none)
@ -45,7 +45,6 @@
* aggtranstype type of aggregate's transition (state) data * aggtranstype type of aggregate's transition (state) data
* aggtransspace estimated size of state data (0 for default estimate) * aggtransspace estimated size of state data (0 for default estimate)
* aggmtranstype type of moving-aggregate state data (0 if none) * aggmtranstype type of moving-aggregate state data (0 if none)
* aggserialtype datatype to serialize state to. (0 if none)
* aggmtransspace estimated size of moving-agg state (0 for default est) * aggmtransspace estimated size of moving-agg state (0 for default est)
* agginitval initial value for transition state (can be NULL) * agginitval initial value for transition state (can be NULL)
* aggminitval initial value for moving-agg state (can be NULL) * aggminitval initial value for moving-agg state (can be NULL)
@ -70,7 +69,6 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
bool aggmfinalextra; bool aggmfinalextra;
Oid aggsortop; Oid aggsortop;
Oid aggtranstype; Oid aggtranstype;
Oid aggserialtype;
int32 aggtransspace; int32 aggtransspace;
Oid aggmtranstype; Oid aggmtranstype;
int32 aggmtransspace; int32 aggmtransspace;
@ -93,7 +91,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
* ---------------- * ----------------
*/ */
#define Natts_pg_aggregate 21 #define Natts_pg_aggregate 20
#define Anum_pg_aggregate_aggfnoid 1 #define Anum_pg_aggregate_aggfnoid 1
#define Anum_pg_aggregate_aggkind 2 #define Anum_pg_aggregate_aggkind 2
#define Anum_pg_aggregate_aggnumdirectargs 3 #define Anum_pg_aggregate_aggnumdirectargs 3
@ -109,12 +107,11 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
#define Anum_pg_aggregate_aggmfinalextra 13 #define Anum_pg_aggregate_aggmfinalextra 13
#define Anum_pg_aggregate_aggsortop 14 #define Anum_pg_aggregate_aggsortop 14
#define Anum_pg_aggregate_aggtranstype 15 #define Anum_pg_aggregate_aggtranstype 15
#define Anum_pg_aggregate_aggserialtype 16 #define Anum_pg_aggregate_aggtransspace 16
#define Anum_pg_aggregate_aggtransspace 17 #define Anum_pg_aggregate_aggmtranstype 17
#define Anum_pg_aggregate_aggmtranstype 18 #define Anum_pg_aggregate_aggmtransspace 18
#define Anum_pg_aggregate_aggmtransspace 19 #define Anum_pg_aggregate_agginitval 19
#define Anum_pg_aggregate_agginitval 20 #define Anum_pg_aggregate_aggminitval 20
#define Anum_pg_aggregate_aggminitval 21
/* /*
* Symbolic values for aggkind column. We distinguish normal aggregates * Symbolic values for aggkind column. We distinguish normal aggregates
@ -138,184 +135,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
*/ */
/* avg */ /* avg */
DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_combine - - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_combine - - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" ));
DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int4_avg_combine - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int4_avg_combine - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" ));
DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2104 n 0 float4_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2104 n 0 float4_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2105 n 0 float8_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2105 n 0 float8_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2106 n 0 interval_accum interval_avg interval_combine - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); DATA(insert ( 2106 n 0 interval_accum interval_avg interval_combine - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" ));
/* sum */ /* sum */
DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2108 n 0 int4_sum - int8pl - - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 0 1016 0 _null_ "{0,0}" )); DATA(insert ( 2108 n 0 int4_sum - int8pl - - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" ));
DATA(insert ( 2109 n 0 int2_sum - int8pl - - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 0 1016 0 _null_ "{0,0}" )); DATA(insert ( 2109 n 0 int2_sum - int8pl - - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" ));
DATA(insert ( 2110 n 0 float4pl - float4pl - - - - - f f 0 700 0 0 0 0 _null_ _null_ )); DATA(insert ( 2110 n 0 float4pl - float4pl - - - - - f f 0 700 0 0 0 _null_ _null_ ));
DATA(insert ( 2111 n 0 float8pl - float8pl - - - - - f f 0 701 0 0 0 0 _null_ _null_ )); DATA(insert ( 2111 n 0 float8pl - float8pl - - - - - f f 0 701 0 0 0 _null_ _null_ ));
DATA(insert ( 2112 n 0 cash_pl - cash_pl - - cash_pl cash_mi - f f 0 790 0 0 790 0 _null_ _null_ )); DATA(insert ( 2112 n 0 cash_pl - cash_pl - - cash_pl cash_mi - f f 0 790 0 790 0 _null_ _null_ ));
DATA(insert ( 2113 n 0 interval_pl - interval_pl - - interval_pl interval_mi - f f 0 1186 0 0 1186 0 _null_ _null_ )); DATA(insert ( 2113 n 0 interval_pl - interval_pl - - interval_pl interval_mi - f f 0 1186 0 1186 0 _null_ _null_ ));
DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ ));
/* max */ /* max */
DATA(insert ( 2115 n 0 int8larger - int8larger - - - - - f f 413 20 0 0 0 0 _null_ _null_ )); DATA(insert ( 2115 n 0 int8larger - int8larger - - - - - f f 413 20 0 0 0 _null_ _null_ ));
DATA(insert ( 2116 n 0 int4larger - int4larger - - - - - f f 521 23 0 0 0 0 _null_ _null_ )); DATA(insert ( 2116 n 0 int4larger - int4larger - - - - - f f 521 23 0 0 0 _null_ _null_ ));
DATA(insert ( 2117 n 0 int2larger - int2larger - - - - - f f 520 21 0 0 0 0 _null_ _null_ )); DATA(insert ( 2117 n 0 int2larger - int2larger - - - - - f f 520 21 0 0 0 _null_ _null_ ));
DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - - - f f 610 26 0 0 0 0 _null_ _null_ )); DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - - - f f 610 26 0 0 0 _null_ _null_ ));
DATA(insert ( 2119 n 0 float4larger - float4larger - - - - - f f 623 700 0 0 0 0 _null_ _null_ )); DATA(insert ( 2119 n 0 float4larger - float4larger - - - - - f f 623 700 0 0 0 _null_ _null_ ));
DATA(insert ( 2120 n 0 float8larger - float8larger - - - - - f f 674 701 0 0 0 0 _null_ _null_ )); DATA(insert ( 2120 n 0 float8larger - float8larger - - - - - f f 674 701 0 0 0 _null_ _null_ ));
DATA(insert ( 2121 n 0 int4larger - int4larger - - - - - f f 563 702 0 0 0 0 _null_ _null_ )); DATA(insert ( 2121 n 0 int4larger - int4larger - - - - - f f 563 702 0 0 0 _null_ _null_ ));
DATA(insert ( 2122 n 0 date_larger - date_larger - - - - - f f 1097 1082 0 0 0 0 _null_ _null_ )); DATA(insert ( 2122 n 0 date_larger - date_larger - - - - - f f 1097 1082 0 0 0 _null_ _null_ ));
DATA(insert ( 2123 n 0 time_larger - time_larger - - - - - f f 1112 1083 0 0 0 0 _null_ _null_ )); DATA(insert ( 2123 n 0 time_larger - time_larger - - - - - f f 1112 1083 0 0 0 _null_ _null_ ));
DATA(insert ( 2124 n 0 timetz_larger - timetz_larger - - - - - f f 1554 1266 0 0 0 0 _null_ _null_ )); DATA(insert ( 2124 n 0 timetz_larger - timetz_larger - - - - - f f 1554 1266 0 0 0 _null_ _null_ ));
DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - - - f f 903 790 0 0 0 0 _null_ _null_ )); DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - - - f f 903 790 0 0 0 _null_ _null_ ));
DATA(insert ( 2126 n 0 timestamp_larger - timestamp_larger - - - - - f f 2064 1114 0 0 0 0 _null_ _null_ )); DATA(insert ( 2126 n 0 timestamp_larger - timestamp_larger - - - - - f f 2064 1114 0 0 0 _null_ _null_ ));
DATA(insert ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - - - f f 1324 1184 0 0 0 0 _null_ _null_ )); DATA(insert ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - - - f f 1324 1184 0 0 0 _null_ _null_ ));
DATA(insert ( 2128 n 0 interval_larger - interval_larger - - - - - f f 1334 1186 0 0 0 0 _null_ _null_ )); DATA(insert ( 2128 n 0 interval_larger - interval_larger - - - - - f f 1334 1186 0 0 0 _null_ _null_ ));
DATA(insert ( 2129 n 0 text_larger - text_larger - - - - - f f 666 25 0 0 0 0 _null_ _null_ )); DATA(insert ( 2129 n 0 text_larger - text_larger - - - - - f f 666 25 0 0 0 _null_ _null_ ));
DATA(insert ( 2130 n 0 numeric_larger - numeric_larger - - - - - f f 1756 1700 0 0 0 0 _null_ _null_ )); DATA(insert ( 2130 n 0 numeric_larger - numeric_larger - - - - - f f 1756 1700 0 0 0 _null_ _null_ ));
DATA(insert ( 2050 n 0 array_larger - array_larger - - - - - f f 1073 2277 0 0 0 0 _null_ _null_ )); DATA(insert ( 2050 n 0 array_larger - array_larger - - - - - f f 1073 2277 0 0 0 _null_ _null_ ));
DATA(insert ( 2244 n 0 bpchar_larger - bpchar_larger - - - - - f f 1060 1042 0 0 0 0 _null_ _null_ )); DATA(insert ( 2244 n 0 bpchar_larger - bpchar_larger - - - - - f f 1060 1042 0 0 0 _null_ _null_ ));
DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - - - f f 2800 27 0 0 0 0 _null_ _null_ )); DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - - - f f 2800 27 0 0 0 _null_ _null_ ));
DATA(insert ( 3526 n 0 enum_larger - enum_larger - - - - - f f 3519 3500 0 0 0 0 _null_ _null_ )); DATA(insert ( 3526 n 0 enum_larger - enum_larger - - - - - f f 3519 3500 0 0 0 _null_ _null_ ));
DATA(insert ( 3564 n 0 network_larger - network_larger - - - - - f f 1205 869 0 0 0 0 _null_ _null_ )); DATA(insert ( 3564 n 0 network_larger - network_larger - - - - - f f 1205 869 0 0 0 _null_ _null_ ));
/* min */ /* min */
DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - - - f f 412 20 0 0 0 0 _null_ _null_ )); DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - - - f f 412 20 0 0 0 _null_ _null_ ));
DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - - - f f 97 23 0 0 0 0 _null_ _null_ )); DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - - - f f 97 23 0 0 0 _null_ _null_ ));
DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - - - f f 95 21 0 0 0 0 _null_ _null_ )); DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - - - f f 95 21 0 0 0 _null_ _null_ ));
DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - - - f f 609 26 0 0 0 0 _null_ _null_ )); DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - - - f f 609 26 0 0 0 _null_ _null_ ));
DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - - - f f 622 700 0 0 0 0 _null_ _null_ )); DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - - - f f 622 700 0 0 0 _null_ _null_ ));
DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - - - f f 672 701 0 0 0 0 _null_ _null_ )); DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - - - f f 672 701 0 0 0 _null_ _null_ ));
DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - - - f f 562 702 0 0 0 0 _null_ _null_ )); DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - - - f f 562 702 0 0 0 _null_ _null_ ));
DATA(insert ( 2138 n 0 date_smaller - date_smaller - - - - - f f 1095 1082 0 0 0 0 _null_ _null_ )); DATA(insert ( 2138 n 0 date_smaller - date_smaller - - - - - f f 1095 1082 0 0 0 _null_ _null_ ));
DATA(insert ( 2139 n 0 time_smaller - time_smaller - - - - - f f 1110 1083 0 0 0 0 _null_ _null_ )); DATA(insert ( 2139 n 0 time_smaller - time_smaller - - - - - f f 1110 1083 0 0 0 _null_ _null_ ));
DATA(insert ( 2140 n 0 timetz_smaller - timetz_smaller - - - - - f f 1552 1266 0 0 0 0 _null_ _null_ )); DATA(insert ( 2140 n 0 timetz_smaller - timetz_smaller - - - - - f f 1552 1266 0 0 0 _null_ _null_ ));
DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - - - f f 902 790 0 0 0 0 _null_ _null_ )); DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - - - f f 902 790 0 0 0 _null_ _null_ ));
DATA(insert ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - - - f f 2062 1114 0 0 0 0 _null_ _null_ )); DATA(insert ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - - - f f 2062 1114 0 0 0 _null_ _null_ ));
DATA(insert ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - - - f f 1322 1184 0 0 0 0 _null_ _null_ )); DATA(insert ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - - - f f 1322 1184 0 0 0 _null_ _null_ ));
DATA(insert ( 2144 n 0 interval_smaller - interval_smaller - - - - - f f 1332 1186 0 0 0 0 _null_ _null_ )); DATA(insert ( 2144 n 0 interval_smaller - interval_smaller - - - - - f f 1332 1186 0 0 0 _null_ _null_ ));
DATA(insert ( 2145 n 0 text_smaller - text_smaller - - - - - f f 664 25 0 0 0 0 _null_ _null_ )); DATA(insert ( 2145 n 0 text_smaller - text_smaller - - - - - f f 664 25 0 0 0 _null_ _null_ ));
DATA(insert ( 2146 n 0 numeric_smaller - numeric_smaller - - - - - f f 1754 1700 0 0 0 0 _null_ _null_ )); DATA(insert ( 2146 n 0 numeric_smaller - numeric_smaller - - - - - f f 1754 1700 0 0 0 _null_ _null_ ));
DATA(insert ( 2051 n 0 array_smaller - array_smaller - - - - - f f 1072 2277 0 0 0 0 _null_ _null_ )); DATA(insert ( 2051 n 0 array_smaller - array_smaller - - - - - f f 1072 2277 0 0 0 _null_ _null_ ));
DATA(insert ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - - - f f 1058 1042 0 0 0 0 _null_ _null_ )); DATA(insert ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - - - f f 1058 1042 0 0 0 _null_ _null_ ));
DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - - - f f 2799 27 0 0 0 0 _null_ _null_ )); DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - - - f f 2799 27 0 0 0 _null_ _null_ ));
DATA(insert ( 3527 n 0 enum_smaller - enum_smaller - - - - - f f 3518 3500 0 0 0 0 _null_ _null_ )); DATA(insert ( 3527 n 0 enum_smaller - enum_smaller - - - - - f f 3518 3500 0 0 0 _null_ _null_ ));
DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - - - f f 1203 869 0 0 0 0 _null_ _null_ )); DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - - - f f 1203 869 0 0 0 _null_ _null_ ));
/* count */ /* count */
DATA(insert ( 2147 n 0 int8inc_any - int8pl - - int8inc_any int8dec_any - f f 0 20 0 0 20 0 "0" "0" )); DATA(insert ( 2147 n 0 int8inc_any - int8pl - - int8inc_any int8dec_any - f f 0 20 0 20 0 "0" "0" ));
DATA(insert ( 2803 n 0 int8inc - int8pl - - int8inc int8dec - f f 0 20 0 0 20 0 "0" "0" )); DATA(insert ( 2803 n 0 int8inc - int8pl - - int8inc int8dec - f f 0 20 0 20 0 "0" "0" ));
/* var_pop */ /* var_pop */
DATA(insert ( 2718 n 0 int8_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2718 n 0 int8_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2721 n 0 float4_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2721 n 0 float4_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2722 n 0 float8_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2722 n 0 float8_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ ));
/* var_samp */ /* var_samp */
DATA(insert ( 2641 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2641 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2644 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2644 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2645 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2645 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ ));
/* variance: historical Postgres syntax for var_samp */ /* variance: historical Postgres syntax for var_samp */
DATA(insert ( 2148 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2148 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2151 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2151 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2152 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2152 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ ));
/* stddev_pop */ /* stddev_pop */
DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ ));
/* stddev_samp */ /* stddev_samp */
DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ ));
/* stddev: historical Postgres syntax for stddev_samp */ /* stddev: historical Postgres syntax for stddev_samp */
DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ ));
DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ ));
DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ ));
/* SQL2003 binary regression aggregates */ /* SQL2003 binary regression aggregates */
DATA(insert ( 2818 n 0 int8inc_float8_float8 - int8pl - - - - - f f 0 20 0 0 0 0 "0" _null_ )); DATA(insert ( 2818 n 0 int8inc_float8_float8 - int8pl - - - - - f f 0 20 0 0 0 "0" _null_ ));
DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
DATA(insert ( 2829 n 0 float8_regr_accum float8_corr float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2829 n 0 float8_regr_accum float8_corr float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ ));
/* boolean-and and boolean-or */ /* boolean-and and boolean-or */
DATA(insert ( 2517 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ )); DATA(insert ( 2517 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ ));
DATA(insert ( 2518 n 0 boolor_statefunc - boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 0 2281 16 _null_ _null_ )); DATA(insert ( 2518 n 0 boolor_statefunc - boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 2281 16 _null_ _null_ ));
DATA(insert ( 2519 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ )); DATA(insert ( 2519 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ ));
/* bitwise integer */ /* bitwise integer */
DATA(insert ( 2236 n 0 int2and - int2and - - - - - f f 0 21 0 0 0 0 _null_ _null_ )); DATA(insert ( 2236 n 0 int2and - int2and - - - - - f f 0 21 0 0 0 _null_ _null_ ));
DATA(insert ( 2237 n 0 int2or - int2or - - - - - f f 0 21 0 0 0 0 _null_ _null_ )); DATA(insert ( 2237 n 0 int2or - int2or - - - - - f f 0 21 0 0 0 _null_ _null_ ));
DATA(insert ( 2238 n 0 int4and - int4and - - - - - f f 0 23 0 0 0 0 _null_ _null_ )); DATA(insert ( 2238 n 0 int4and - int4and - - - - - f f 0 23 0 0 0 _null_ _null_ ));
DATA(insert ( 2239 n 0 int4or - int4or - - - - - f f 0 23 0 0 0 0 _null_ _null_ )); DATA(insert ( 2239 n 0 int4or - int4or - - - - - f f 0 23 0 0 0 _null_ _null_ ));
DATA(insert ( 2240 n 0 int8and - int8and - - - - - f f 0 20 0 0 0 0 _null_ _null_ )); DATA(insert ( 2240 n 0 int8and - int8and - - - - - f f 0 20 0 0 0 _null_ _null_ ));
DATA(insert ( 2241 n 0 int8or - int8or - - - - - f f 0 20 0 0 0 0 _null_ _null_ )); DATA(insert ( 2241 n 0 int8or - int8or - - - - - f f 0 20 0 0 0 _null_ _null_ ));
DATA(insert ( 2242 n 0 bitand - bitand - - - - - f f 0 1560 0 0 0 0 _null_ _null_ )); DATA(insert ( 2242 n 0 bitand - bitand - - - - - f f 0 1560 0 0 0 _null_ _null_ ));
DATA(insert ( 2243 n 0 bitor - bitor - - - - - f f 0 1560 0 0 0 0 _null_ _null_ )); DATA(insert ( 2243 n 0 bitor - bitor - - - - - f f 0 1560 0 0 0 _null_ _null_ ));
/* xml */ /* xml */
DATA(insert ( 2901 n 0 xmlconcat2 - - - - - - - f f 0 142 0 0 0 0 _null_ _null_ )); DATA(insert ( 2901 n 0 xmlconcat2 - - - - - - - f f 0 142 0 0 0 _null_ _null_ ));
/* array */ /* array */
DATA(insert ( 2335 n 0 array_agg_transfn array_agg_finalfn - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 2335 n 0 array_agg_transfn array_agg_finalfn - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
/* text */ /* text */
DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
/* bytea */ /* bytea */
DATA(insert ( 3545 n 0 bytea_string_agg_transfn bytea_string_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3545 n 0 bytea_string_agg_transfn bytea_string_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
/* json */ /* json */
DATA(insert ( 3175 n 0 json_agg_transfn json_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3175 n 0 json_agg_transfn json_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
/* jsonb */ /* jsonb */
DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
/* ordered-set and hypothetical-set aggregates */ /* ordered-set and hypothetical-set aggregates */
DATA(insert ( 3972 o 1 ordered_set_transition percentile_disc_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3972 o 1 ordered_set_transition percentile_disc_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3974 o 1 ordered_set_transition percentile_cont_float8_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3974 o 1 ordered_set_transition percentile_cont_float8_final - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3976 o 1 ordered_set_transition percentile_cont_interval_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3976 o 1 ordered_set_transition percentile_cont_interval_final - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3978 o 1 ordered_set_transition percentile_disc_multi_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3978 o 1 ordered_set_transition percentile_disc_multi_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3980 o 1 ordered_set_transition percentile_cont_float8_multi_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3980 o 1 ordered_set_transition percentile_cont_float8_multi_final - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3982 o 1 ordered_set_transition percentile_cont_interval_multi_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3982 o 1 ordered_set_transition percentile_cont_interval_multi_final - - - - - - f f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3984 o 0 ordered_set_transition mode_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3984 o 0 ordered_set_transition mode_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3986 h 1 ordered_set_transition_multi rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3986 h 1 ordered_set_transition_multi rank_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3988 h 1 ordered_set_transition_multi percent_rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3988 h 1 ordered_set_transition_multi percent_rank_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3990 h 1 ordered_set_transition_multi cume_dist_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3990 h 1 ordered_set_transition_multi cume_dist_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
DATA(insert ( 3992 h 1 ordered_set_transition_multi dense_rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); DATA(insert ( 3992 h 1 ordered_set_transition_multi dense_rank_final - - - - - - t f 0 2281 0 0 0 _null_ _null_ ));
/* /*
@ -344,7 +341,6 @@ extern ObjectAddress AggregateCreate(const char *aggName,
bool mfinalfnExtraArgs, bool mfinalfnExtraArgs,
List *aggsortopName, List *aggsortopName,
Oid aggTransType, Oid aggTransType,
Oid aggSerialType,
int32 aggTransSpace, int32 aggTransSpace,
Oid aggmTransType, Oid aggmTransType,
int32 aggmTransSpace, int32 aggmTransSpace,

View File

@ -2451,11 +2451,11 @@ DATA(insert OID = 3337 ( numeric_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f
DESCR("aggregate combine function"); DESCR("aggregate combine function");
DATA(insert OID = 2740 ( numeric_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_serialize _null_ _null_ _null_ )); DATA(insert OID = 2740 ( numeric_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_serialize _null_ _null_ _null_ ));
DESCR("aggregate serial function"); DESCR("aggregate serial function");
DATA(insert OID = 2741 ( numeric_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ )); DATA(insert OID = 2741 ( numeric_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ ));
DESCR("aggregate deserial function"); DESCR("aggregate deserial function");
DATA(insert OID = 3335 ( numeric_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_serialize _null_ _null_ _null_ )); DATA(insert OID = 3335 ( numeric_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_serialize _null_ _null_ _null_ ));
DESCR("aggregate serial function"); DESCR("aggregate serial function");
DATA(insert OID = 3336 ( numeric_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ )); DATA(insert OID = 3336 ( numeric_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ ));
DESCR("aggregate deserial function"); DESCR("aggregate deserial function");
DATA(insert OID = 3548 ( numeric_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum_inv _null_ _null_ _null_ )); DATA(insert OID = 3548 ( numeric_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum_inv _null_ _null_ _null_ ));
DESCR("aggregate transition function"); DESCR("aggregate transition function");
@ -2469,7 +2469,7 @@ DATA(insert OID = 3338 ( numeric_poly_combine PGNSP PGUID 12 1 0 0 0 f f f f
DESCR("aggregate combine function"); DESCR("aggregate combine function");
DATA(insert OID = 3339 ( numeric_poly_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_serialize _null_ _null_ _null_ )); DATA(insert OID = 3339 ( numeric_poly_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_serialize _null_ _null_ _null_ ));
DESCR("aggregate serial function"); DESCR("aggregate serial function");
DATA(insert OID = 3340 ( numeric_poly_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ )); DATA(insert OID = 3340 ( numeric_poly_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ ));
DESCR("aggregate deserial function"); DESCR("aggregate deserial function");
DATA(insert OID = 2746 ( int8_avg_accum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ )); DATA(insert OID = 2746 ( int8_avg_accum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ ));
DESCR("aggregate transition function"); DESCR("aggregate transition function");
@ -2485,9 +2485,9 @@ DATA(insert OID = 2785 ( int8_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f f
DESCR("aggregate combine function"); DESCR("aggregate combine function");
DATA(insert OID = 2786 ( int8_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ int8_avg_serialize _null_ _null_ _null_ )); DATA(insert OID = 2786 ( int8_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ int8_avg_serialize _null_ _null_ _null_ ));
DESCR("aggregate serial function"); DESCR("aggregate serial function");
DATA(insert OID = 2787 ( int8_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ )); DATA(insert OID = 2787 ( int8_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ ));
DESCR("aggregate deserial function"); DESCR("aggregate deserial function");
DATA(insert OID = 3324 ( int4_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ )); DATA(insert OID = 3324 ( int4_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 1016 "1016 1016" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ ));
DESCR("aggregate combine function"); DESCR("aggregate combine function");
DATA(insert OID = 3178 ( numeric_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 1 0 1700 "2281" _null_ _null_ _null_ _null_ _null_ numeric_sum _null_ _null_ _null_ )); DATA(insert OID = 3178 ( numeric_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 1 0 1700 "2281" _null_ _null_ _null_ _null_ _null_ numeric_sum _null_ _null_ _null_ ));
DESCR("aggregate final function"); DESCR("aggregate final function");

View File

@ -51,12 +51,12 @@ extern void build_aggregate_combinefn_expr(Oid agg_state_type,
Oid combinefn_oid, Oid combinefn_oid,
Expr **combinefnexpr); Expr **combinefnexpr);
extern void build_aggregate_serialfn_expr(Oid agg_state_type, extern void build_aggregate_serialfn_expr(Oid serialfn_oid,
Oid agg_serial_type,
Oid agg_input_collation,
Oid serialfn_oid,
Expr **serialfnexpr); Expr **serialfnexpr);
extern void build_aggregate_deserialfn_expr(Oid deserialfn_oid,
Expr **deserialfnexpr);
extern void build_aggregate_finalfn_expr(Oid *agg_input_types, extern void build_aggregate_finalfn_expr(Oid *agg_input_types,
int num_finalfn_inputs, int num_finalfn_inputs,
Oid agg_state_type, Oid agg_state_type,

View File

@ -102,36 +102,19 @@ CREATE AGGREGATE sumdouble (float8)
minvfunc = float8mi minvfunc = float8mi
); );
-- aggregate combine and serialization functions -- aggregate combine and serialization functions
-- Ensure stype and serialtype can't be the same -- can't specify just one of serialfunc and deserialfunc
CREATE AGGREGATE myavg (numeric) CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = internal
);
ERROR: aggregate serialization data type cannot be internal
-- if serialtype is specified we need a serialfunc and deserialfunc
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = bytea
);
ERROR: aggregate serialization function must be specified when serialization type is specified
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize serialfunc = numeric_avg_serialize
); );
ERROR: aggregate deserialization function must be specified when serialization type is specified ERROR: must specify both or neither of serialization and deserialization functions
-- serialfunc must have correct parameters -- serialfunc must have correct parameters
CREATE AGGREGATE myavg (numeric) CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_deserialize, serialfunc = numeric_avg_deserialize,
deserialfunc = numeric_avg_deserialize deserialfunc = numeric_avg_deserialize
); );
@ -141,27 +124,15 @@ CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_serialize deserialfunc = numeric_avg_serialize
); );
ERROR: function numeric_avg_serialize(bytea) does not exist ERROR: function numeric_avg_serialize(bytea, internal) does not exist
-- ensure return type of serialfunc is checked
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = text,
serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize
);
ERROR: return type of serialization function numeric_avg_serialize is not text
-- ensure combine function parameters are checked -- ensure combine function parameters are checked
CREATE AGGREGATE myavg (numeric) CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize,
combinefunc = int4larger combinefunc = int4larger
@ -173,18 +144,17 @@ CREATE AGGREGATE myavg (numeric)
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
finalfunc = numeric_avg, finalfunc = numeric_avg,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize,
combinefunc = numeric_avg_combine combinefunc = numeric_avg_combine
); );
-- Ensure all these functions made it into the catalog -- Ensure all these functions made it into the catalog
SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn
FROM pg_aggregate FROM pg_aggregate
WHERE aggfnoid = 'myavg'::REGPROC; WHERE aggfnoid = 'myavg'::REGPROC;
aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggserialtype aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn
----------+-------------------+---------------------+--------------+-----------------------+-------------------------+--------------- ----------+-------------------+---------------------+--------------+-----------------------+-------------------------
myavg | numeric_avg_accum | numeric_avg_combine | 2281 | numeric_avg_serialize | numeric_avg_deserialize | 17 myavg | numeric_avg_accum | numeric_avg_combine | 2281 | numeric_avg_serialize | numeric_avg_deserialize
(1 row) (1 row)
DROP AGGREGATE myavg (numeric); DROP AGGREGATE myavg (numeric);

View File

@ -279,21 +279,16 @@ ORDER BY 1, 2;
-- Look for functions that return type "internal" and do not have any -- Look for functions that return type "internal" and do not have any
-- "internal" argument. Such a function would be a security hole since -- "internal" argument. Such a function would be a security hole since
-- it might be used to call an internal function from an SQL command. -- it might be used to call an internal function from an SQL command.
-- As of 7.3 this query should find internal_in, and as of 9.6 aggregate -- As of 7.3 this query should find only internal_in, which is safe because
-- deserialization will be found too. These should contain a runtime check to -- it always throws an error when called.
-- ensure they can only be called in an aggregate context.
SELECT p1.oid, p1.proname SELECT p1.oid, p1.proname
FROM pg_proc as p1 FROM pg_proc as p1
WHERE p1.prorettype = 'internal'::regtype AND NOT WHERE p1.prorettype = 'internal'::regtype AND NOT
'internal'::regtype = ANY (p1.proargtypes); 'internal'::regtype = ANY (p1.proargtypes);
oid | proname oid | proname
------+-------------------------- ------+-------------
2741 | numeric_avg_deserialize
3336 | numeric_deserialize
3340 | numeric_poly_deserialize
2787 | int8_avg_deserialize
2304 | internal_in 2304 | internal_in
(5 rows) (1 row)
-- Look for functions that return a polymorphic type and do not have any -- Look for functions that return a polymorphic type and do not have any
-- polymorphic argument. Calls of such functions would be unresolvable -- polymorphic argument. Calls of such functions would be unresolvable
@ -1442,6 +1437,84 @@ WHERE a.aggfnoid = p.oid AND
----------+---------+-----+---------+-----+--------- ----------+---------+-----+---------+-----+---------
(0 rows) (0 rows)
-- Check that all combine functions have signature
-- combine(transtype, transtype) returns transtype
-- NOTE: use physically_coercible here, not binary_coercible, because
-- max and min on abstime are implemented using int4larger/int4smaller.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
(p.pronargs != 2 OR
p.prorettype != p.proargtypes[0] OR
p.prorettype != p.proargtypes[1] OR
NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
aggfnoid | proname
----------+---------
(0 rows)
-- Check that no combine function for an INTERNAL transtype is strict.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
a.aggtranstype = 'internal'::regtype AND p.proisstrict;
aggfnoid | proname
----------+---------
(0 rows)
-- serialize/deserialize functions should be specified only for aggregates
-- with transtype internal and a combine function, and we should have both
-- or neither of them.
SELECT aggfnoid, aggtranstype, aggserialfn, aggdeserialfn
FROM pg_aggregate
WHERE (aggserialfn != 0 OR aggdeserialfn != 0)
AND (aggtranstype != 'internal'::regtype OR aggcombinefn = 0 OR
aggserialfn = 0 OR aggdeserialfn = 0);
aggfnoid | aggtranstype | aggserialfn | aggdeserialfn
----------+--------------+-------------+---------------
(0 rows)
-- Check that all serialization functions have signature
-- serialize(internal) returns bytea
-- Also insist that they be strict; it's wasteful to run them on NULLs.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggserialfn = p.oid AND
(p.prorettype != 'bytea'::regtype OR p.pronargs != 1 OR
p.proargtypes[0] != 'internal'::regtype OR
NOT p.proisstrict);
aggfnoid | proname
----------+---------
(0 rows)
-- Check that all deserialization functions have signature
-- deserialize(bytea, internal) returns internal
-- Also insist that they be strict; it's wasteful to run them on NULLs.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggdeserialfn = p.oid AND
(p.prorettype != 'internal'::regtype OR p.pronargs != 2 OR
p.proargtypes[0] != 'bytea'::regtype OR
p.proargtypes[1] != 'internal'::regtype OR
NOT p.proisstrict);
aggfnoid | proname
----------+---------
(0 rows)
-- Check that aggregates which have the same transition function also have
-- the same combine, serialization, and deserialization functions.
-- While that isn't strictly necessary, it's fishy if they don't.
SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn,
b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn
FROM
pg_aggregate a, pg_aggregate b
WHERE
a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND
(a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn
OR a.aggdeserialfn != b.aggdeserialfn);
aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn | aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn
----------+--------------+-------------+---------------+----------+--------------+-------------+---------------
(0 rows)
-- Cross-check aggsortop (if present) against pg_operator. -- Cross-check aggsortop (if present) against pg_operator.
-- We expect to find entries for bool_and, bool_or, every, max, and min. -- We expect to find entries for bool_and, bool_or, every, max, and min.
SELECT DISTINCT proname, oprname SELECT DISTINCT proname, oprname
@ -1534,89 +1607,6 @@ WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n';
-----+--------- -----+---------
(0 rows) (0 rows)
-- Check that all serial functions have a return type the same as the serial
-- type.
SELECT a.aggserialfn,a.aggserialtype,p.prorettype
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggserialfn = p.oid
WHERE a.aggserialtype <> p.prorettype;
aggserialfn | aggserialtype | prorettype
-------------+---------------+------------
(0 rows)
-- Check that all the deserial functions have the same input type as the
-- serialtype
SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0]
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid
WHERE p.proargtypes[0] <> a.aggserialtype;
aggserialfn | aggserialtype | proargtypes
-------------+---------------+-------------
(0 rows)
-- An aggregate should either have a complete set of serialtype, serial func
-- and deserial func, or none of them.
SELECT aggserialtype,aggserialfn,aggdeserialfn
FROM pg_aggregate
WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0)
AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0);
aggserialtype | aggserialfn | aggdeserialfn
---------------+-------------+---------------
(0 rows)
-- Check that all aggregates with serialtypes have internal states.
-- (There's no point in serializing anything apart from internal)
SELECT aggfnoid,aggserialtype,aggtranstype
FROM pg_aggregate
WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype;
aggfnoid | aggserialtype | aggtranstype
----------+---------------+--------------
(0 rows)
-- Check that all serial functions are strict. It's wasteful for these to be
-- called with NULL values.
SELECT aggfnoid,aggserialfn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggserialfn = p.oid
WHERE p.proisstrict = false;
aggfnoid | aggserialfn
----------+-------------
(0 rows)
-- Check that all deserial functions are strict. It's wasteful for these to be
-- called with NULL values.
SELECT aggfnoid,aggdeserialfn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid
WHERE p.proisstrict = false;
aggfnoid | aggdeserialfn
----------+---------------
(0 rows)
-- Check that no combine functions with an INTERNAL return type are strict.
SELECT aggfnoid,aggcombinefn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggcombinefn = p.oid
INNER JOIN pg_type t ON a.aggtranstype = t.oid
WHERE t.typname = 'internal' AND p.proisstrict = true;
aggfnoid | aggcombinefn
----------+--------------
(0 rows)
-- Check that aggregates which have the same transition function also have
-- the same combine, serialization, and deserialization functions.
SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn,
b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn
FROM
pg_aggregate a, pg_aggregate b
WHERE
a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND
(a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn
OR a.aggdeserialfn != b.aggdeserialfn);
aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn | aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn
----------+--------------+-------------+---------------+----------+--------------+-------------+---------------
(0 rows)
-- **************** pg_opfamily **************** -- **************** pg_opfamily ****************
-- Look for illegal values in pg_opfamily fields -- Look for illegal values in pg_opfamily fields
SELECT p1.oid SELECT p1.oid

View File

@ -117,27 +117,11 @@ CREATE AGGREGATE sumdouble (float8)
-- aggregate combine and serialization functions -- aggregate combine and serialization functions
-- Ensure stype and serialtype can't be the same -- can't specify just one of serialfunc and deserialfunc
CREATE AGGREGATE myavg (numeric) CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = internal
);
-- if serialtype is specified we need a serialfunc and deserialfunc
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = bytea
);
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize serialfunc = numeric_avg_serialize
); );
@ -146,7 +130,6 @@ CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_deserialize, serialfunc = numeric_avg_deserialize,
deserialfunc = numeric_avg_deserialize deserialfunc = numeric_avg_deserialize
); );
@ -156,27 +139,15 @@ CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_serialize deserialfunc = numeric_avg_serialize
); );
-- ensure return type of serialfunc is checked
CREATE AGGREGATE myavg (numeric)
(
stype = internal,
sfunc = numeric_avg_accum,
serialtype = text,
serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize
);
-- ensure combine function parameters are checked -- ensure combine function parameters are checked
CREATE AGGREGATE myavg (numeric) CREATE AGGREGATE myavg (numeric)
( (
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize,
combinefunc = int4larger combinefunc = int4larger
@ -188,14 +159,13 @@ CREATE AGGREGATE myavg (numeric)
stype = internal, stype = internal,
sfunc = numeric_avg_accum, sfunc = numeric_avg_accum,
finalfunc = numeric_avg, finalfunc = numeric_avg,
serialtype = bytea,
serialfunc = numeric_avg_serialize, serialfunc = numeric_avg_serialize,
deserialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize,
combinefunc = numeric_avg_combine combinefunc = numeric_avg_combine
); );
-- Ensure all these functions made it into the catalog -- Ensure all these functions made it into the catalog
SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn
FROM pg_aggregate FROM pg_aggregate
WHERE aggfnoid = 'myavg'::REGPROC; WHERE aggfnoid = 'myavg'::REGPROC;

View File

@ -228,9 +228,8 @@ ORDER BY 1, 2;
-- Look for functions that return type "internal" and do not have any -- Look for functions that return type "internal" and do not have any
-- "internal" argument. Such a function would be a security hole since -- "internal" argument. Such a function would be a security hole since
-- it might be used to call an internal function from an SQL command. -- it might be used to call an internal function from an SQL command.
-- As of 7.3 this query should find internal_in, and as of 9.6 aggregate -- As of 7.3 this query should find only internal_in, which is safe because
-- deserialization will be found too. These should contain a runtime check to -- it always throws an error when called.
-- ensure they can only be called in an aggregate context.
SELECT p1.oid, p1.proname SELECT p1.oid, p1.proname
FROM pg_proc as p1 FROM pg_proc as p1
@ -937,6 +936,72 @@ WHERE a.aggfnoid = p.oid AND
a.aggminvtransfn = iptr.oid AND a.aggminvtransfn = iptr.oid AND
ptr.proisstrict != iptr.proisstrict; ptr.proisstrict != iptr.proisstrict;
-- Check that all combine functions have signature
-- combine(transtype, transtype) returns transtype
-- NOTE: use physically_coercible here, not binary_coercible, because
-- max and min on abstime are implemented using int4larger/int4smaller.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
(p.pronargs != 2 OR
p.prorettype != p.proargtypes[0] OR
p.prorettype != p.proargtypes[1] OR
NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
-- Check that no combine function for an INTERNAL transtype is strict.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
a.aggtranstype = 'internal'::regtype AND p.proisstrict;
-- serialize/deserialize functions should be specified only for aggregates
-- with transtype internal and a combine function, and we should have both
-- or neither of them.
SELECT aggfnoid, aggtranstype, aggserialfn, aggdeserialfn
FROM pg_aggregate
WHERE (aggserialfn != 0 OR aggdeserialfn != 0)
AND (aggtranstype != 'internal'::regtype OR aggcombinefn = 0 OR
aggserialfn = 0 OR aggdeserialfn = 0);
-- Check that all serialization functions have signature
-- serialize(internal) returns bytea
-- Also insist that they be strict; it's wasteful to run them on NULLs.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggserialfn = p.oid AND
(p.prorettype != 'bytea'::regtype OR p.pronargs != 1 OR
p.proargtypes[0] != 'internal'::regtype OR
NOT p.proisstrict);
-- Check that all deserialization functions have signature
-- deserialize(bytea, internal) returns internal
-- Also insist that they be strict; it's wasteful to run them on NULLs.
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggdeserialfn = p.oid AND
(p.prorettype != 'internal'::regtype OR p.pronargs != 2 OR
p.proargtypes[0] != 'bytea'::regtype OR
p.proargtypes[1] != 'internal'::regtype OR
NOT p.proisstrict);
-- Check that aggregates which have the same transition function also have
-- the same combine, serialization, and deserialization functions.
-- While that isn't strictly necessary, it's fishy if they don't.
SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn,
b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn
FROM
pg_aggregate a, pg_aggregate b
WHERE
a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND
(a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn
OR a.aggdeserialfn != b.aggdeserialfn);
-- Cross-check aggsortop (if present) against pg_operator. -- Cross-check aggsortop (if present) against pg_operator.
-- We expect to find entries for bool_and, bool_or, every, max, and min. -- We expect to find entries for bool_and, bool_or, every, max, and min.
@ -1004,64 +1069,6 @@ SELECT p.oid, proname
FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid
WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n';
-- Check that all serial functions have a return type the same as the serial
-- type.
SELECT a.aggserialfn,a.aggserialtype,p.prorettype
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggserialfn = p.oid
WHERE a.aggserialtype <> p.prorettype;
-- Check that all the deserial functions have the same input type as the
-- serialtype
SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0]
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid
WHERE p.proargtypes[0] <> a.aggserialtype;
-- An aggregate should either have a complete set of serialtype, serial func
-- and deserial func, or none of them.
SELECT aggserialtype,aggserialfn,aggdeserialfn
FROM pg_aggregate
WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0)
AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0);
-- Check that all aggregates with serialtypes have internal states.
-- (There's no point in serializing anything apart from internal)
SELECT aggfnoid,aggserialtype,aggtranstype
FROM pg_aggregate
WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype;
-- Check that all serial functions are strict. It's wasteful for these to be
-- called with NULL values.
SELECT aggfnoid,aggserialfn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggserialfn = p.oid
WHERE p.proisstrict = false;
-- Check that all deserial functions are strict. It's wasteful for these to be
-- called with NULL values.
SELECT aggfnoid,aggdeserialfn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid
WHERE p.proisstrict = false;
-- Check that no combine functions with an INTERNAL return type are strict.
SELECT aggfnoid,aggcombinefn
FROM pg_aggregate a
INNER JOIN pg_proc p ON a.aggcombinefn = p.oid
INNER JOIN pg_type t ON a.aggtranstype = t.oid
WHERE t.typname = 'internal' AND p.proisstrict = true;
-- Check that aggregates which have the same transition function also have
-- the same combine, serialization, and deserialization functions.
SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn,
b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn
FROM
pg_aggregate a, pg_aggregate b
WHERE
a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND
(a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn
OR a.aggdeserialfn != b.aggdeserialfn);
-- **************** pg_opfamily **************** -- **************** pg_opfamily ****************