Commit 5fe5a2ce authored by Robert Haas's avatar Robert Haas

Allow aggregate transition states to be serialized and deserialized.

This is necessary infrastructure for supporting parallel aggregation
for aggregates whose transition type is "internal".  Such values
can't be passed between cooperating processes, because they are
just pointers.

David Rowley, reviewed by Tomas Vondra and by me.
parent 7f0a2c85
...@@ -412,6 +412,18 @@ ...@@ -412,6 +412,18 @@
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Combine function (zero if none)</entry> <entry>Combine function (zero if none)</entry>
</row> </row>
<row>
<entry><structfield>aggserialfn</structfield></entry>
<entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Serialization function (zero if none)</entry>
</row>
<row>
<entry><structfield>aggdeserialfn</structfield></entry>
<entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Deserialization function (zero if none)</entry>
</row>
<row> <row>
<entry><structfield>aggmtransfn</structfield></entry> <entry><structfield>aggmtransfn</structfield></entry>
<entry><type>regproc</type></entry> <entry><type>regproc</type></entry>
...@@ -454,6 +466,12 @@ ...@@ -454,6 +466,12 @@
<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>
......
...@@ -28,6 +28,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea ...@@ -28,6 +28,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , FINALFUNC_EXTRA ] [ , FINALFUNC_EXTRA ]
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , 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> ]
[ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
[ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
...@@ -47,6 +50,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac ...@@ -47,6 +50,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , FINALFUNC_EXTRA ] [ , FINALFUNC_EXTRA ]
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , 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 ]
) )
...@@ -61,6 +67,9 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( ...@@ -61,6 +67,9 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , FINALFUNC_EXTRA ] [ , FINALFUNC_EXTRA ]
[ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , 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> ]
[ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
[ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
...@@ -436,6 +445,47 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; ...@@ -436,6 +445,47 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">serialfunc</replaceable></term>
<listitem>
<para>
In order to allow aggregate functions with an <literal>INTERNAL</>
<replaceable class="PARAMETER">state_data_type</replaceable> to
participate in parallel aggregation, the aggregate must have a valid
<replaceable class="PARAMETER">serialfunc</replaceable>, which must
serialize the aggregate state into <replaceable class="PARAMETER">
serialtype</replaceable>. This function must take a single argument of
<replaceable class="PARAMETER">state_data_type</replaceable> and return
<replaceable class="PARAMETER">serialtype</replaceable>. A
corresponding <replaceable class="PARAMETER">deserialfunc</replaceable>
is also required.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">deserialfunc</replaceable></term>
<listitem>
<para>
Deserializes a previously serialized aggregate state back into
<replaceable class="PARAMETER">state_data_type</replaceable>. This
function must take a single argument of <replaceable class="PARAMETER">
serialtype</replaceable> and return <replaceable class="PARAMETER">
state_data_type</replaceable>.
</para>
</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>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable class="PARAMETER">initial_condition</replaceable></term> <term><replaceable class="PARAMETER">initial_condition</replaceable></term>
<listitem> <listitem>
......
...@@ -58,6 +58,8 @@ AggregateCreate(const char *aggName, ...@@ -58,6 +58,8 @@ AggregateCreate(const char *aggName,
List *aggtransfnName, List *aggtransfnName,
List *aggfinalfnName, List *aggfinalfnName,
List *aggcombinefnName, List *aggcombinefnName,
List *aggserialfnName,
List *aggdeserialfnName,
List *aggmtransfnName, List *aggmtransfnName,
List *aggminvtransfnName, List *aggminvtransfnName,
List *aggmfinalfnName, List *aggmfinalfnName,
...@@ -65,6 +67,7 @@ AggregateCreate(const char *aggName, ...@@ -65,6 +67,7 @@ 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,
...@@ -79,6 +82,8 @@ AggregateCreate(const char *aggName, ...@@ -79,6 +82,8 @@ AggregateCreate(const char *aggName,
Oid transfn; Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */ Oid finalfn = InvalidOid; /* can be omitted */
Oid combinefn = InvalidOid; /* can be omitted */ Oid combinefn = InvalidOid; /* can be omitted */
Oid serialfn = InvalidOid; /* can be omitted */
Oid deserialfn = InvalidOid; /* can be omitted */
Oid mtransfn = InvalidOid; /* can be omitted */ Oid mtransfn = InvalidOid; /* can be omitted */
Oid minvtransfn = InvalidOid; /* can be omitted */ Oid minvtransfn = InvalidOid; /* can be omitted */
Oid mfinalfn = InvalidOid; /* can be omitted */ Oid mfinalfn = InvalidOid; /* can be omitted */
...@@ -420,6 +425,57 @@ AggregateCreate(const char *aggName, ...@@ -420,6 +425,57 @@ AggregateCreate(const char *aggName,
errmsg("return type of combine function %s is not %s", errmsg("return type of combine function %s is not %s",
NameListToString(aggcombinefnName), NameListToString(aggcombinefnName),
format_type_be(aggTransType)))); format_type_be(aggTransType))));
/*
* A combine function to combine INTERNAL states must accept nulls and
* ensure that the returned state is in the correct memory context.
*/
if (aggTransType == INTERNALOID && func_strict(combinefn))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("combine function with \"%s\" transition type must not be declared STRICT",
format_type_be(aggTransType))));
}
/*
* Validate the serialization function, if present. We must ensure that the
* return type of this function is the same as the specified serialType.
*/
if (aggserialfnName)
{
fnArgs[0] = aggTransType;
serialfn = lookup_agg_function(aggserialfnName, 1,
fnArgs, variadicArgType,
&rettype);
if (rettype != aggSerialType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of serialization function %s is not %s",
NameListToString(aggserialfnName),
format_type_be(aggSerialType))));
}
/*
* Validate the deserialization function, if present. We must ensure that
* the return type of this function is the same as the transType.
*/
if (aggdeserialfnName)
{
fnArgs[0] = aggSerialType;
deserialfn = lookup_agg_function(aggdeserialfnName, 1,
fnArgs, variadicArgType,
&rettype);
if (rettype != aggTransType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of deserialization function %s is not %s",
NameListToString(aggdeserialfnName),
format_type_be(aggTransType))));
} }
/* /*
...@@ -594,6 +650,8 @@ AggregateCreate(const char *aggName, ...@@ -594,6 +650,8 @@ AggregateCreate(const char *aggName,
values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn); values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn); values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn); values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn); values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn); values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn); values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
...@@ -601,6 +659,7 @@ AggregateCreate(const char *aggName, ...@@ -601,6 +659,7 @@ 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);
...@@ -627,7 +686,8 @@ AggregateCreate(const char *aggName, ...@@ -627,7 +686,8 @@ 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 if any. * Likewise for aggmTransType using the mtransfunc, and also for
* aggSerialType using the serialfn, if they exist.
*/ */
/* Depends on transition function */ /* Depends on transition function */
...@@ -654,6 +714,24 @@ AggregateCreate(const char *aggName, ...@@ -654,6 +714,24 @@ AggregateCreate(const char *aggName,
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
/* Depends on serialization function, if any */
if (OidIsValid(serialfn))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = serialfn;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Depends on deserialization function, if any */
if (OidIsValid(deserialfn))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = deserialfn;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Depends on forward transition function, if any */ /* Depends on forward transition function, if any */
if (OidIsValid(mtransfn)) if (OidIsValid(mtransfn))
{ {
......
...@@ -62,6 +62,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -62,6 +62,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
List *transfuncName = NIL; List *transfuncName = NIL;
List *finalfuncName = NIL; List *finalfuncName = NIL;
List *combinefuncName = NIL; List *combinefuncName = NIL;
List *serialfuncName = NIL;
List *deserialfuncName = NIL;
List *mtransfuncName = NIL; List *mtransfuncName = NIL;
List *minvtransfuncName = NIL; List *minvtransfuncName = NIL;
List *mfinalfuncName = NIL; List *mfinalfuncName = NIL;
...@@ -70,6 +72,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -70,6 +72,7 @@ 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;
...@@ -84,6 +87,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -84,6 +87,7 @@ 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;
...@@ -127,6 +131,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -127,6 +131,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
finalfuncName = defGetQualifiedName(defel); finalfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "combinefunc") == 0) else if (pg_strcasecmp(defel->defname, "combinefunc") == 0)
combinefuncName = defGetQualifiedName(defel); combinefuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "serialfunc") == 0)
serialfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "deserialfunc") == 0)
deserialfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "msfunc") == 0) else if (pg_strcasecmp(defel->defname, "msfunc") == 0)
mtransfuncName = defGetQualifiedName(defel); mtransfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "minvfunc") == 0) else if (pg_strcasecmp(defel->defname, "minvfunc") == 0)
...@@ -154,6 +162,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -154,6 +162,8 @@ 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)
...@@ -319,6 +329,75 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -319,6 +329,75 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
format_type_be(transTypeId)))); format_type_be(transTypeId))));
} }
if (serialType)
{
/*
* There's little point in having a serialization/deserialization
* 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)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("a serialization type must only be specified when the aggregate transition data type is \"%s\"",
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 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
{
/*
* If serialization type was not specified then there shouldn't be a
* serialization function.
*/
if (serialfuncName != NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must specify serialization type when specifying serialization function")));
/* likewise for the deserialization function */
if (deserialfuncName != NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must specify serialization type when specifying deserialization function")));
}
/* /*
* If a moving-aggregate transtype is specified, look that up. Same * If a moving-aggregate transtype is specified, look that up. Same
* restrictions as for transtype. * restrictions as for transtype.
...@@ -387,6 +466,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -387,6 +466,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
transfuncName, /* step function name */ transfuncName, /* step function name */
finalfuncName, /* final function name */ finalfuncName, /* final function name */
combinefuncName, /* combine function name */ combinefuncName, /* combine function name */
serialfuncName, /* serial function name */
deserialfuncName, /* deserial function name */
mtransfuncName, /* fwd trans function name */ mtransfuncName, /* fwd trans function name */
minvtransfuncName, /* inv trans function name */ minvtransfuncName, /* inv trans function name */
mfinalfuncName, /* final function name */ mfinalfuncName, /* final function name */
...@@ -394,6 +475,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ...@@ -394,6 +475,7 @@ 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 */
......
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
* incorrect. Instead a new state should be created in the correct aggregate * incorrect. Instead a new state should be created in the correct aggregate
* memory context and the 2nd state should be copied over. * memory context and the 2nd state should be copied over.
* *
* The 'serialStates' option can be used to allow multi-stage aggregation
* for aggregates with an INTERNAL state type. When this mode is disabled
* only a pointer to the INTERNAL aggregate states are passed around the
* executor. When enabled, INTERNAL states are serialized and deserialized
* as required; this is useful when data must be passed between processes.
*
* If a normal aggregate call specifies DISTINCT or ORDER BY, we sort the * If a normal aggregate call specifies DISTINCT or ORDER BY, we sort the
* input tuples and eliminate duplicates (if required) before performing * input tuples and eliminate duplicates (if required) before performing
* the above-depicted process. (However, we don't do that for ordered-set * the above-depicted process. (However, we don't do that for ordered-set
...@@ -232,6 +238,12 @@ typedef struct AggStatePerTransData ...@@ -232,6 +238,12 @@ typedef struct AggStatePerTransData
/* Oid of the state transition or combine function */ /* Oid of the state transition or combine function */
Oid transfn_oid; Oid transfn_oid;
/* Oid of the serialization function or InvalidOid */
Oid serialfn_oid;
/* Oid of the deserialization function or InvalidOid */
Oid deserialfn_oid;
/* Oid of state value's datatype */ /* Oid of state value's datatype */
Oid aggtranstype; Oid aggtranstype;
...@@ -246,6 +258,12 @@ typedef struct AggStatePerTransData ...@@ -246,6 +258,12 @@ typedef struct AggStatePerTransData
*/ */
FmgrInfo transfn; FmgrInfo transfn;
/* fmgr lookup data for serialization function */
FmgrInfo serialfn;
/* fmgr lookup data for deserialization function */
FmgrInfo deserialfn;
/* Input collation derived for aggregate */ /* Input collation derived for aggregate */
Oid aggCollation; Oid aggCollation;
...@@ -326,6 +344,11 @@ typedef struct AggStatePerTransData ...@@ -326,6 +344,11 @@ typedef struct AggStatePerTransData
* worth the extra space consumption. * worth the extra space consumption.
*/ */
FunctionCallInfoData transfn_fcinfo; FunctionCallInfoData transfn_fcinfo;
/* Likewise for serialization and deserialization functions */
FunctionCallInfoData serialfn_fcinfo;
FunctionCallInfoData deserialfn_fcinfo;
} AggStatePerTransData; } AggStatePerTransData;
/* /*
...@@ -467,6 +490,10 @@ static void finalize_aggregate(AggState *aggstate, ...@@ -467,6 +490,10 @@ static void finalize_aggregate(AggState *aggstate,
AggStatePerAgg peragg, AggStatePerAgg peragg,
AggStatePerGroup pergroupstate, AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull); Datum *resultVal, bool *resultIsNull);
static void finalize_partialaggregate(AggState *aggstate,
AggStatePerAgg peragg,
AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull);
static void prepare_projection_slot(AggState *aggstate, static void prepare_projection_slot(AggState *aggstate,
TupleTableSlot *slot, TupleTableSlot *slot,
int currentSet); int currentSet);
...@@ -487,12 +514,15 @@ static Datum GetAggInitVal(Datum textInitVal, Oid transtype); ...@@ -487,12 +514,15 @@ 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,
Datum initValue, bool initValueIsNull, Oid aggserialtype, Oid aggserialfn,
Oid *inputTypes, int numArguments); Oid aggdeserialfn, Datum initValue,
bool initValueIsNull, Oid *inputTypes,
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,
Oid aggtransfn, Oid aggtranstype, Oid aggtransfn, Oid aggtranstype,
Oid aggserialfn, Oid aggdeserialfn,
Datum initValue, bool initValueIsNull, Datum initValue, bool initValueIsNull,
List *transnos); List *transnos);
...@@ -944,8 +974,45 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup) ...@@ -944,8 +974,45 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
slot = ExecProject(pertrans->evalproj, NULL); slot = ExecProject(pertrans->evalproj, NULL);
Assert(slot->tts_nvalid >= 1); Assert(slot->tts_nvalid >= 1);
/*
* deserialfn_oid will be set if we must deserialize the input state
* before calling the combine function
*/
if (OidIsValid(pertrans->deserialfn_oid))
{
/*
* Don't call a strict deserialization function with NULL input.
* A strict deserialization function and a null value means we skip
* calling the combine function for this state. We assume that this
* would be a waste of time and effort anyway so just skip it.
*/
if (pertrans->deserialfn.fn_strict && slot->tts_isnull[0])
continue;
else
{
FunctionCallInfo dsinfo = &pertrans->deserialfn_fcinfo;
MemoryContext oldContext;
dsinfo->arg[0] = slot->tts_values[0];
dsinfo->argnull[0] = slot->tts_isnull[0];
/*
* We run the deserialization functions in per-input-tuple
* memory context.
*/
oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
fcinfo->arg[1] = FunctionCallInvoke(dsinfo);
fcinfo->argnull[1] = dsinfo->isnull;
MemoryContextSwitchTo(oldContext);
}
}
else
{
fcinfo->arg[1] = slot->tts_values[0]; fcinfo->arg[1] = slot->tts_values[0];
fcinfo->argnull[1] = slot->tts_isnull[0]; fcinfo->argnull[1] = slot->tts_isnull[0];
}
advance_combine_function(aggstate, pertrans, pergroupstate); advance_combine_function(aggstate, pertrans, pergroupstate);
} }
...@@ -1344,6 +1411,61 @@ finalize_aggregate(AggState *aggstate, ...@@ -1344,6 +1411,61 @@ finalize_aggregate(AggState *aggstate,
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
} }
/*
* Compute the final value of one partial aggregate.
*
* The serialization function will be run, and the result delivered, in the
* output-tuple context; caller's CurrentMemoryContext does not matter.
*/
static void
finalize_partialaggregate(AggState *aggstate,
AggStatePerAgg peragg,
AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull)
{
AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno];
MemoryContext oldContext;
oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
/*
* serialfn_oid will be set if we must serialize the input state
* before calling the combine function on the state.
*/
if (OidIsValid(pertrans->serialfn_oid))
{
/* Don't call a strict serialization function with NULL input. */
if (pertrans->serialfn.fn_strict && pergroupstate->transValueIsNull)
{
*resultVal = (Datum) 0;
*resultIsNull = true;
}
else
{
FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo;
fcinfo->arg[0] = pergroupstate->transValue;
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
*resultVal = FunctionCallInvoke(fcinfo);
*resultIsNull = fcinfo->isnull;
}
}
else
{
*resultVal = pergroupstate->transValue;
*resultIsNull = pergroupstate->transValueIsNull;
}
/* If result is pass-by-ref, make sure it is in the right context. */
if (!peragg->resulttypeByVal && !*resultIsNull &&
!MemoryContextContains(CurrentMemoryContext,
DatumGetPointer(*resultVal)))
*resultVal = datumCopy(*resultVal,
peragg->resulttypeByVal,
peragg->resulttypeLen);
MemoryContextSwitchTo(oldContext);
}
/* /*
* Prepare to finalize and project based on the specified representative tuple * Prepare to finalize and project based on the specified representative tuple
...@@ -1455,10 +1577,8 @@ finalize_aggregates(AggState *aggstate, ...@@ -1455,10 +1577,8 @@ finalize_aggregates(AggState *aggstate,
finalize_aggregate(aggstate, peragg, pergroupstate, finalize_aggregate(aggstate, peragg, pergroupstate,
&aggvalues[aggno], &aggnulls[aggno]); &aggvalues[aggno], &aggnulls[aggno]);
else else
{ finalize_partialaggregate(aggstate, peragg, pergroupstate,
aggvalues[aggno] = pergroupstate->transValue; &aggvalues[aggno], &aggnulls[aggno]);
aggnulls[aggno] = pergroupstate->transValueIsNull;
}
} }
} }
...@@ -2238,6 +2358,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2238,6 +2358,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->agg_done = false; aggstate->agg_done = false;
aggstate->combineStates = node->combineStates; aggstate->combineStates = node->combineStates;
aggstate->finalizeAggs = node->finalizeAggs; aggstate->finalizeAggs = node->finalizeAggs;
aggstate->serialStates = node->serialStates;
aggstate->input_done = false; aggstate->input_done = false;
aggstate->pergroup = NULL; aggstate->pergroup = NULL;
aggstate->grp_firstTuple = NULL; aggstate->grp_firstTuple = NULL;
...@@ -2546,6 +2667,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2546,6 +2667,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
AclResult aclresult; AclResult aclresult;
Oid transfn_oid, Oid transfn_oid,
finalfn_oid; finalfn_oid;
Oid serialtype_oid,
serialfn_oid,
deserialfn_oid;
Expr *finalfnexpr; Expr *finalfnexpr;
Oid aggtranstype; Oid aggtranstype;
Datum textInitVal; Datum textInitVal;
...@@ -2610,6 +2734,47 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2610,6 +2734,47 @@ 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;
deserialfn_oid = InvalidOid;
/*
* Determine if we require serialization or deserialization of the
* aggregate states. This is only required if the aggregate state is
* internal.
*/
if (aggstate->serialStates && aggform->aggtranstype == INTERNALOID)
{
/*
* The planner should only have generated an agg node with
* serialStates if every aggregate with an INTERNAL state has a
* serialization type, serialization function and deserialization
* 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))
elog(ERROR, "serialfunc not set during serialStates aggregation step");
if (!OidIsValid(aggform->aggdeserialfn))
elog(ERROR, "deserialfunc not set during serialStates aggregation step");
/* serialization func only required when not finalizing aggs */
if (!aggstate->finalizeAggs)
{
serialfn_oid = aggform->aggserialfn;
serialtype_oid = aggform->aggserialtype;
}
/* deserialization func only required when combining states */
if (aggstate->combineStates)
{
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 */
{ {
HeapTuple procTuple; HeapTuple procTuple;
...@@ -2638,6 +2803,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2638,6 +2803,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
get_func_name(finalfn_oid)); get_func_name(finalfn_oid));
InvokeFunctionExecuteHook(finalfn_oid); InvokeFunctionExecuteHook(finalfn_oid);
} }
if (OidIsValid(serialfn_oid))
{
aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
get_func_name(serialfn_oid));
InvokeFunctionExecuteHook(serialfn_oid);
}
if (OidIsValid(deserialfn_oid))
{
aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
get_func_name(deserialfn_oid));
InvokeFunctionExecuteHook(deserialfn_oid);
}
} }
/* /*
...@@ -2707,6 +2890,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2707,6 +2890,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
*/ */
existing_transno = find_compatible_pertrans(aggstate, aggref, existing_transno = find_compatible_pertrans(aggstate, aggref,
transfn_oid, aggtranstype, transfn_oid, aggtranstype,
serialfn_oid, deserialfn_oid,
initValue, initValueIsNull, initValue, initValueIsNull,
same_input_transnos); same_input_transnos);
if (existing_transno != -1) if (existing_transno != -1)
...@@ -2723,8 +2907,10 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2723,8 +2907,10 @@ 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,
initValue, initValueIsNull, serialtype_oid, serialfn_oid,
inputTypes, numArguments); deserialfn_oid, initValue,
initValueIsNull, inputTypes,
numArguments);
peragg->transno = transno; peragg->transno = transno;
} }
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
...@@ -2752,11 +2938,14 @@ static void ...@@ -2752,11 +2938,14 @@ 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 aggtransfn, Oid aggtranstype, Oid aggserialtype,
Oid aggserialfn, Oid aggdeserialfn,
Datum initValue, bool initValueIsNull, Datum initValue, bool initValueIsNull,
Oid *inputTypes, int numArguments) Oid *inputTypes, int numArguments)
{ {
int numGroupingSets = Max(aggstate->maxsets, 1); int numGroupingSets = Max(aggstate->maxsets, 1);
Expr *serialfnexpr = NULL;
Expr *deserialfnexpr = NULL;
ListCell *lc; ListCell *lc;
int numInputs; int numInputs;
int numDirectArgs; int numDirectArgs;
...@@ -2770,6 +2959,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, ...@@ -2770,6 +2959,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
pertrans->aggref = aggref; pertrans->aggref = aggref;
pertrans->aggCollation = aggref->inputcollid; pertrans->aggCollation = aggref->inputcollid;
pertrans->transfn_oid = aggtransfn; pertrans->transfn_oid = aggtransfn;
pertrans->serialfn_oid = aggserialfn;
pertrans->deserialfn_oid = aggdeserialfn;
pertrans->initValue = initValue; pertrans->initValue = initValue;
pertrans->initValueIsNull = initValueIsNull; pertrans->initValueIsNull = initValueIsNull;
...@@ -2809,6 +3000,17 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, ...@@ -2809,6 +3000,17 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
2, 2,
pertrans->aggCollation, pertrans->aggCollation,
(void *) aggstate, NULL); (void *) aggstate, NULL);
/*
* Ensure that a combine function to combine INTERNAL states is not
* strict. This should have been checked during CREATE AGGREGATE, but
* the strict property could have been changed since then.
*/
if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("combine function for aggregate %u must to be declared as strict",
aggref->aggfnoid)));
} }
else else
{ {
...@@ -2861,6 +3063,41 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, ...@@ -2861,6 +3063,41 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
&pertrans->transtypeLen, &pertrans->transtypeLen,
&pertrans->transtypeByVal); &pertrans->transtypeByVal);
if (OidIsValid(aggserialfn))
{
build_aggregate_serialfn_expr(aggtranstype,
aggserialtype,
aggref->inputcollid,
aggserialfn,
&serialfnexpr);
fmgr_info(aggserialfn, &pertrans->serialfn);
fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
InitFunctionCallInfoData(pertrans->serialfn_fcinfo,
&pertrans->serialfn,
1,
pertrans->aggCollation,
(void *) aggstate, NULL);
}
if (OidIsValid(aggdeserialfn))
{
build_aggregate_serialfn_expr(aggserialtype,
aggtranstype,
aggref->inputcollid,
aggdeserialfn,
&deserialfnexpr);
fmgr_info(aggdeserialfn, &pertrans->deserialfn);
fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
InitFunctionCallInfoData(pertrans->deserialfn_fcinfo,
&pertrans->deserialfn,
1,
pertrans->aggCollation,
(void *) aggstate, NULL);
}
/* /*
* Get a tupledesc corresponding to the aggregated inputs (including sort * Get a tupledesc corresponding to the aggregated inputs (including sort
* expressions) of the agg. * expressions) of the agg.
...@@ -3107,6 +3344,7 @@ find_compatible_peragg(Aggref *newagg, AggState *aggstate, ...@@ -3107,6 +3344,7 @@ find_compatible_peragg(Aggref *newagg, AggState *aggstate,
static int static int
find_compatible_pertrans(AggState *aggstate, Aggref *newagg, find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
Oid aggtransfn, Oid aggtranstype, Oid aggtransfn, Oid aggtranstype,
Oid aggserialfn, Oid aggdeserialfn,
Datum initValue, bool initValueIsNull, Datum initValue, bool initValueIsNull,
List *transnos) List *transnos)
{ {
...@@ -3125,6 +3363,17 @@ find_compatible_pertrans(AggState *aggstate, Aggref *newagg, ...@@ -3125,6 +3363,17 @@ find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
aggtranstype != pertrans->aggtranstype) aggtranstype != pertrans->aggtranstype)
continue; continue;
/*
* The serialization and deserialization functions must match, if
* present, as we're unable to share the trans state for aggregates
* which will serialize or deserialize into different formats. Remember
* that these will be InvalidOid if they're not required for this agg
* node.
*/
if (aggserialfn != pertrans->serialfn_oid ||
aggdeserialfn != pertrans->deserialfn_oid)
continue;
/* Check that the initial condition matches, too. */ /* Check that the initial condition matches, too. */
if (initValueIsNull && pertrans->initValueIsNull) if (initValueIsNull && pertrans->initValueIsNull)
return transno; return transno;
......
...@@ -871,6 +871,7 @@ _copyAgg(const Agg *from) ...@@ -871,6 +871,7 @@ _copyAgg(const Agg *from)
COPY_SCALAR_FIELD(aggstrategy); COPY_SCALAR_FIELD(aggstrategy);
COPY_SCALAR_FIELD(combineStates); COPY_SCALAR_FIELD(combineStates);
COPY_SCALAR_FIELD(finalizeAggs); COPY_SCALAR_FIELD(finalizeAggs);
COPY_SCALAR_FIELD(serialStates);
COPY_SCALAR_FIELD(numCols); COPY_SCALAR_FIELD(numCols);
if (from->numCols > 0) if (from->numCols > 0)
{ {
......
...@@ -708,6 +708,7 @@ _outAgg(StringInfo str, const Agg *node) ...@@ -708,6 +708,7 @@ _outAgg(StringInfo str, const Agg *node)
WRITE_ENUM_FIELD(aggstrategy, AggStrategy); WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
WRITE_BOOL_FIELD(combineStates); WRITE_BOOL_FIELD(combineStates);
WRITE_BOOL_FIELD(finalizeAggs); WRITE_BOOL_FIELD(finalizeAggs);
WRITE_BOOL_FIELD(serialStates);
WRITE_INT_FIELD(numCols); WRITE_INT_FIELD(numCols);
appendStringInfoString(str, " :grpColIdx"); appendStringInfoString(str, " :grpColIdx");
......
...@@ -1993,6 +1993,7 @@ _readAgg(void) ...@@ -1993,6 +1993,7 @@ _readAgg(void)
READ_ENUM_FIELD(aggstrategy, AggStrategy); READ_ENUM_FIELD(aggstrategy, AggStrategy);
READ_BOOL_FIELD(combineStates); READ_BOOL_FIELD(combineStates);
READ_BOOL_FIELD(finalizeAggs); READ_BOOL_FIELD(finalizeAggs);
READ_BOOL_FIELD(serialStates);
READ_INT_FIELD(numCols); READ_INT_FIELD(numCols);
READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols); READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
READ_OID_ARRAY(grpOperators, local_node->numCols); READ_OID_ARRAY(grpOperators, local_node->numCols);
......
...@@ -1279,6 +1279,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags) ...@@ -1279,6 +1279,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
AGG_HASHED, AGG_HASHED,
false, false,
true, true,
false,
numGroupCols, numGroupCols,
groupColIdx, groupColIdx,
groupOperators, groupOperators,
...@@ -1578,6 +1579,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path) ...@@ -1578,6 +1579,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path)
best_path->aggstrategy, best_path->aggstrategy,
best_path->combineStates, best_path->combineStates,
best_path->finalizeAggs, best_path->finalizeAggs,
best_path->serialStates,
list_length(best_path->groupClause), list_length(best_path->groupClause),
extract_grouping_cols(best_path->groupClause, extract_grouping_cols(best_path->groupClause,
subplan->targetlist), subplan->targetlist),
...@@ -1732,6 +1734,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) ...@@ -1732,6 +1734,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
AGG_SORTED, AGG_SORTED,
false, false,
true, true,
false,
list_length((List *) linitial(gsets)), list_length((List *) linitial(gsets)),
new_grpColIdx, new_grpColIdx,
extract_grouping_ops(groupClause), extract_grouping_ops(groupClause),
...@@ -1768,6 +1771,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) ...@@ -1768,6 +1771,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
(numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN, (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
false, false,
true, true,
false,
numGroupCols, numGroupCols,
top_grpColIdx, top_grpColIdx,
extract_grouping_ops(groupClause), extract_grouping_ops(groupClause),
...@@ -5636,7 +5640,7 @@ materialize_finished_plan(Plan *subplan) ...@@ -5636,7 +5640,7 @@ materialize_finished_plan(Plan *subplan)
Agg * Agg *
make_agg(List *tlist, List *qual, make_agg(List *tlist, List *qual,
AggStrategy aggstrategy, AggStrategy aggstrategy,
bool combineStates, bool finalizeAggs, bool combineStates, bool finalizeAggs, bool serialStates,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
List *groupingSets, List *chain, List *groupingSets, List *chain,
double dNumGroups, Plan *lefttree) double dNumGroups, Plan *lefttree)
...@@ -5651,6 +5655,7 @@ make_agg(List *tlist, List *qual, ...@@ -5651,6 +5655,7 @@ make_agg(List *tlist, List *qual,
node->aggstrategy = aggstrategy; node->aggstrategy = aggstrategy;
node->combineStates = combineStates; node->combineStates = combineStates;
node->finalizeAggs = finalizeAggs; node->finalizeAggs = finalizeAggs;
node->serialStates = serialStates;
node->numCols = numGroupCols; node->numCols = numGroupCols;
node->grpColIdx = grpColIdx; node->grpColIdx = grpColIdx;
node->grpOperators = grpOperators; node->grpOperators = grpOperators;
......
...@@ -3455,7 +3455,8 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3455,7 +3455,8 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumPartialGroups, dNumPartialGroups,
false, false,
false)); false,
true));
else else
add_partial_path(grouped_rel, (Path *) add_partial_path(grouped_rel, (Path *)
create_group_path(root, create_group_path(root,
...@@ -3496,7 +3497,8 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3496,7 +3497,8 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumPartialGroups, dNumPartialGroups,
false, false,
false)); false,
true));
} }
} }
} }
...@@ -3560,7 +3562,8 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3560,7 +3562,8 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups,
false, false,
true)); true,
false));
} }
else if (parse->groupClause) else if (parse->groupClause)
{ {
...@@ -3626,6 +3629,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3626,6 +3629,7 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups,
true, true,
true,
true)); true));
else else
add_path(grouped_rel, (Path *) add_path(grouped_rel, (Path *)
...@@ -3668,7 +3672,8 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3668,7 +3672,8 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups,
false, false,
true)); true,
false));
} }
/* /*
...@@ -3706,6 +3711,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3706,6 +3711,7 @@ create_grouping_paths(PlannerInfo *root,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups,
true, true,
true,
true)); true));
} }
} }
...@@ -4039,7 +4045,8 @@ create_distinct_paths(PlannerInfo *root, ...@@ -4039,7 +4045,8 @@ create_distinct_paths(PlannerInfo *root,
NULL, NULL,
numDistinctRows, numDistinctRows,
false, false,
true)); true,
false));
} }
/* Give a helpful error if we failed to find any implementation */ /* Give a helpful error if we failed to find any implementation */
......
...@@ -2057,10 +2057,10 @@ search_indexed_tlist_for_sortgroupref(Node *node, ...@@ -2057,10 +2057,10 @@ search_indexed_tlist_for_sortgroupref(Node *node,
* search_indexed_tlist_for_partial_aggref - find an Aggref in an indexed tlist * search_indexed_tlist_for_partial_aggref - find an Aggref in an indexed tlist
* *
* Aggrefs for partial aggregates have their aggoutputtype adjusted to set it * Aggrefs for partial aggregates have their aggoutputtype adjusted to set it
* to the aggregate state's type. This means that a standard equal() comparison * to the aggregate state's type, or serialization type. This means that a
* won't match when comparing an Aggref which is in partial mode with an Aggref * standard equal() comparison won't match when comparing an Aggref which is
* which is not. Here we manually compare all of the fields apart from * in partial mode with an Aggref which is not. Here we manually compare all of
* aggoutputtype. * the fields apart from aggoutputtype.
*/ */
static Var * static Var *
search_indexed_tlist_for_partial_aggref(Aggref *aggref, indexed_tlist *itlist, search_indexed_tlist_for_partial_aggref(Aggref *aggref, indexed_tlist *itlist,
......
...@@ -861,7 +861,8 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist, ...@@ -861,7 +861,8 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
NULL, NULL,
dNumGroups, dNumGroups,
false, false,
true); true,
false);
} }
else else
{ {
......
...@@ -464,11 +464,15 @@ aggregates_allow_partial_walker(Node *node, partial_agg_context *context) ...@@ -464,11 +464,15 @@ aggregates_allow_partial_walker(Node *node, partial_agg_context *context)
} }
/* /*
* If we find any aggs with an internal transtype then we must ensure * If we find any aggs with an internal transtype then we must check
* that pointers to aggregate states are not passed to other processes; * that these have a serialization type, serialization func and
* therefore, we set the maximum allowed type to PAT_INTERNAL_ONLY. * deserialization func; otherwise, we set the maximum allowed type to
*/ * PAT_INTERNAL_ONLY.
if (aggform->aggtranstype == INTERNALOID) */
if (aggform->aggtranstype == INTERNALOID &&
(!OidIsValid(aggform->aggserialtype) ||
!OidIsValid(aggform->aggserialfn) ||
!OidIsValid(aggform->aggdeserialfn)))
context->allowedtype = PAT_INTERNAL_ONLY; context->allowedtype = PAT_INTERNAL_ONLY;
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
......
...@@ -2433,7 +2433,8 @@ create_agg_path(PlannerInfo *root, ...@@ -2433,7 +2433,8 @@ create_agg_path(PlannerInfo *root,
const AggClauseCosts *aggcosts, const AggClauseCosts *aggcosts,
double numGroups, double numGroups,
bool combineStates, bool combineStates,
bool finalizeAggs) bool finalizeAggs,
bool serialStates)
{ {
AggPath *pathnode = makeNode(AggPath); AggPath *pathnode = makeNode(AggPath);
...@@ -2458,6 +2459,7 @@ create_agg_path(PlannerInfo *root, ...@@ -2458,6 +2459,7 @@ create_agg_path(PlannerInfo *root,
pathnode->qual = qual; pathnode->qual = qual;
pathnode->finalizeAggs = finalizeAggs; pathnode->finalizeAggs = finalizeAggs;
pathnode->combineStates = combineStates; pathnode->combineStates = combineStates;
pathnode->serialStates = serialStates;
cost_agg(&pathnode->path, root, cost_agg(&pathnode->path, root,
aggstrategy, aggcosts, aggstrategy, aggcosts,
......
...@@ -756,8 +756,8 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target) ...@@ -756,8 +756,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 to
* the aggtranstype. This allows exprType() to return the actual type that * the aggtranstype or aggserialtype. This allows exprType() to return the
* will be produced. * actual type that will be produced.
* *
* Note: We expect 'target' to be a flat target list and not have Aggrefs burried * Note: We expect 'target' to be a flat target list and not have Aggrefs burried
* within other expressions. * within other expressions.
...@@ -785,6 +785,11 @@ apply_partialaggref_adjustment(PathTarget *target) ...@@ -785,6 +785,11 @@ apply_partialaggref_adjustment(PathTarget *target)
aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
newaggref = (Aggref *) copyObject(aggref); newaggref = (Aggref *) copyObject(aggref);
/* use the serialization type, if one exists */
if (OidIsValid(aggform->aggserialtype))
newaggref->aggoutputtype = aggform->aggserialtype;
else
newaggref->aggoutputtype = aggform->aggtranstype; newaggref->aggoutputtype = aggform->aggtranstype;
lfirst(lc) = newaggref; lfirst(lc) = newaggref;
......
...@@ -1964,6 +1964,45 @@ build_aggregate_combinefn_expr(Oid agg_state_type, ...@@ -1964,6 +1964,45 @@ build_aggregate_combinefn_expr(Oid agg_state_type,
*combinefnexpr = (Expr *) fexpr; *combinefnexpr = (Expr *) fexpr;
} }
/*
* Like build_aggregate_transfn_expr, but creates an expression tree for the
* serialization or deserialization function of an aggregate, rather than the
* transition function. This may be used for either the serialization or
* deserialization function by swapping the first two parameters over.
*/
void
build_aggregate_serialfn_expr(Oid agg_input_type,
Oid agg_output_type,
Oid agg_input_collation,
Oid serialfn_oid,
Expr **serialfnexpr)
{
Param *argp;
List *args;
FuncExpr *fexpr;
/* Build arg list to use in the FuncExpr node. */
argp = makeNode(Param);
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,
agg_output_type,
args,
InvalidOid,
agg_input_collation,
COERCE_EXPLICIT_CALL);
fexpr->funcvariadic = false;
*serialfnexpr = (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.
......
...@@ -12557,6 +12557,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12557,6 +12557,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
int i_aggtransfn; int i_aggtransfn;
int i_aggfinalfn; int i_aggfinalfn;
int i_aggcombinefn; int i_aggcombinefn;
int i_aggserialfn;
int i_aggdeserialfn;
int i_aggmtransfn; int i_aggmtransfn;
int i_aggminvtransfn; int i_aggminvtransfn;
int i_aggmfinalfn; int i_aggmfinalfn;
...@@ -12565,6 +12567,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12565,6 +12567,7 @@ 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;
...@@ -12574,6 +12577,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12574,6 +12577,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
const char *aggtransfn; const char *aggtransfn;
const char *aggfinalfn; const char *aggfinalfn;
const char *aggcombinefn; const char *aggcombinefn;
const char *aggserialfn;
const char *aggdeserialfn;
const char *aggmtransfn; const char *aggmtransfn;
const char *aggminvtransfn; const char *aggminvtransfn;
const char *aggmfinalfn; const char *aggmfinalfn;
...@@ -12583,6 +12588,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12583,6 +12588,7 @@ 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;
...@@ -12608,10 +12614,11 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12608,10 +12614,11 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"aggcombinefn, aggmtransfn, " "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
"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, "
...@@ -12627,10 +12634,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12627,10 +12634,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"'-' AS aggcombinefn, aggmtransfn, aggminvtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, "
"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, "
...@@ -12646,11 +12655,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12646,11 +12655,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"'-' AS aggcombinefn, '-' AS aggmtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"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, "
...@@ -12666,11 +12677,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12666,11 +12677,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"'-' AS aggcombinefn, '-' AS aggmtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"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, "
...@@ -12684,10 +12697,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12684,10 +12697,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"'-' AS aggcombinefn, '-' AS aggmtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' 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, "
...@@ -12701,10 +12716,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12701,10 +12716,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, " appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
"format_type(aggtranstype, NULL) AS aggtranstype, " "format_type(aggtranstype, NULL) AS aggtranstype, "
"'-' AS aggcombinefn, '-' AS aggmtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' 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, "
...@@ -12718,10 +12735,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12718,10 +12735,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, "
"aggfinalfn, " "aggfinalfn, "
"(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, " "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
"'-' AS aggcombinefn, '-' AS aggmtransfn, " "'-' AS aggcombinefn, '-' AS aggserialfn, "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' 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, "
...@@ -12736,12 +12755,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12736,12 +12755,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
i_aggtransfn = PQfnumber(res, "aggtransfn"); i_aggtransfn = PQfnumber(res, "aggtransfn");
i_aggfinalfn = PQfnumber(res, "aggfinalfn"); i_aggfinalfn = PQfnumber(res, "aggfinalfn");
i_aggcombinefn = PQfnumber(res, "aggcombinefn"); i_aggcombinefn = PQfnumber(res, "aggcombinefn");
i_aggserialfn = PQfnumber(res, "aggserialfn");
i_aggdeserialfn = PQfnumber(res, "aggdeserialfn");
i_aggmtransfn = PQfnumber(res, "aggmtransfn"); i_aggmtransfn = PQfnumber(res, "aggmtransfn");
i_aggminvtransfn = PQfnumber(res, "aggminvtransfn"); i_aggminvtransfn = PQfnumber(res, "aggminvtransfn");
i_aggmfinalfn = PQfnumber(res, "aggmfinalfn"); i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
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");
...@@ -12754,6 +12776,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12754,6 +12776,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
aggtransfn = PQgetvalue(res, 0, i_aggtransfn); aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn); aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
aggcombinefn = PQgetvalue(res, 0, i_aggcombinefn); aggcombinefn = PQgetvalue(res, 0, i_aggcombinefn);
aggserialfn = PQgetvalue(res, 0, i_aggserialfn);
aggdeserialfn = PQgetvalue(res, 0, i_aggdeserialfn);
aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn); aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn);
aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn); aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn);
aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn); aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
...@@ -12762,6 +12786,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12762,6 +12786,7 @@ 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);
...@@ -12847,6 +12872,17 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -12847,6 +12872,17 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
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)
{
appendPQExpBuffer(details, ",\n SERIALFUNC = %s", aggserialfn);
appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn);
appendPQExpBuffer(details, ",\n SERIALTYPE = %s", aggserialtype);
}
if (strcmp(aggmtransfn, "-") != 0) if (strcmp(aggmtransfn, "-") != 0)
{ {
appendPQExpBuffer(details, ",\n MSFUNC = %s,\n MINVFUNC = %s,\n MSTYPE = %s", appendPQExpBuffer(details, ",\n MSFUNC = %s,\n MINVFUNC = %s,\n MSTYPE = %s",
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201603231 #define CATALOG_VERSION_NO 201603291
#endif #endif
...@@ -34,6 +34,8 @@ ...@@ -34,6 +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)
* aggdeserialfn function to convert serialtype 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)
...@@ -43,6 +45,7 @@ ...@@ -43,6 +45,7 @@
* 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)
...@@ -58,6 +61,8 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS ...@@ -58,6 +61,8 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
regproc aggtransfn; regproc aggtransfn;
regproc aggfinalfn; regproc aggfinalfn;
regproc aggcombinefn; regproc aggcombinefn;
regproc aggserialfn;
regproc aggdeserialfn;
regproc aggmtransfn; regproc aggmtransfn;
regproc aggminvtransfn; regproc aggminvtransfn;
regproc aggmfinalfn; regproc aggmfinalfn;
...@@ -65,6 +70,7 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS ...@@ -65,6 +70,7 @@ 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;
...@@ -87,25 +93,28 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; ...@@ -87,25 +93,28 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
* ---------------- * ----------------
*/ */
#define Natts_pg_aggregate 18 #define Natts_pg_aggregate 21
#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
#define Anum_pg_aggregate_aggtransfn 4 #define Anum_pg_aggregate_aggtransfn 4
#define Anum_pg_aggregate_aggfinalfn 5 #define Anum_pg_aggregate_aggfinalfn 5
#define Anum_pg_aggregate_aggcombinefn 6 #define Anum_pg_aggregate_aggcombinefn 6
#define Anum_pg_aggregate_aggmtransfn 7 #define Anum_pg_aggregate_aggserialfn 7
#define Anum_pg_aggregate_aggminvtransfn 8 #define Anum_pg_aggregate_aggdeserialfn 8
#define Anum_pg_aggregate_aggmfinalfn 9 #define Anum_pg_aggregate_aggmtransfn 9
#define Anum_pg_aggregate_aggfinalextra 10 #define Anum_pg_aggregate_aggminvtransfn 10
#define Anum_pg_aggregate_aggmfinalextra 11 #define Anum_pg_aggregate_aggmfinalfn 11
#define Anum_pg_aggregate_aggsortop 12 #define Anum_pg_aggregate_aggfinalextra 12
#define Anum_pg_aggregate_aggtranstype 13 #define Anum_pg_aggregate_aggmfinalextra 13
#define Anum_pg_aggregate_aggtransspace 14 #define Anum_pg_aggregate_aggsortop 14
#define Anum_pg_aggregate_aggmtranstype 15 #define Anum_pg_aggregate_aggtranstype 15
#define Anum_pg_aggregate_aggmtransspace 16 #define Anum_pg_aggregate_aggserialtype 16
#define Anum_pg_aggregate_agginitval 17 #define Anum_pg_aggregate_aggtransspace 17
#define Anum_pg_aggregate_aggminitval 18 #define Anum_pg_aggregate_aggmtranstype 18
#define Anum_pg_aggregate_aggmtransspace 19
#define Anum_pg_aggregate_agginitval 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
...@@ -129,184 +138,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; ...@@ -129,184 +138,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
*/ */
/* avg */ /* avg */
DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg - int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg - - - int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2101 n 0 int4_avg_accum int8_avg - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); DATA(insert ( 2101 n 0 int4_avg_accum int8_avg - - - int4_avg_accum int4_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 - int2_avg_accum int2_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 - - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" ));
DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg - numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg - - - numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2104 n 0 float4_accum float8_avg - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2104 n 0 float4_accum float8_avg - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2105 n 0 float8_accum float8_avg - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2105 n 0 float8_accum float8_avg - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2106 n 0 interval_accum interval_avg - interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); DATA(insert ( 2106 n 0 interval_accum interval_avg - - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 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_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum - - - int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 0 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 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 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 ( 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 ( 2110 n 0 float4pl - float4pl - - - f f 0 700 0 0 0 _null_ _null_ )); DATA(insert ( 2110 n 0 float4pl - float4pl - - - - - f f 0 700 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2111 n 0 float8pl - float8pl - - - f f 0 701 0 0 0 _null_ _null_ )); DATA(insert ( 2111 n 0 float8pl - float8pl - - - - - f f 0 701 0 0 0 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 ( 2112 n 0 cash_pl - cash_pl - - cash_pl cash_mi - f f 0 790 0 0 790 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 ( 2113 n 0 interval_pl - interval_pl - - interval_pl interval_mi - f f 0 1186 0 0 1186 0 _null_ _null_ ));
DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum - numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum - - - numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 0 128 2281 128 _null_ _null_ ));
/* max */ /* max */
DATA(insert ( 2115 n 0 int8larger - int8larger - - - f f 413 20 0 0 0 _null_ _null_ )); DATA(insert ( 2115 n 0 int8larger - int8larger - - - - - f f 413 20 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2116 n 0 int4larger - int4larger - - - f f 521 23 0 0 0 _null_ _null_ )); DATA(insert ( 2116 n 0 int4larger - int4larger - - - - - f f 521 23 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2117 n 0 int2larger - int2larger - - - f f 520 21 0 0 0 _null_ _null_ )); DATA(insert ( 2117 n 0 int2larger - int2larger - - - - - f f 520 21 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - f f 610 26 0 0 0 _null_ _null_ )); DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - - - f f 610 26 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2119 n 0 float4larger - float4larger - - - f f 623 700 0 0 0 _null_ _null_ )); DATA(insert ( 2119 n 0 float4larger - float4larger - - - - - f f 623 700 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2120 n 0 float8larger - float8larger - - - f f 674 701 0 0 0 _null_ _null_ )); DATA(insert ( 2120 n 0 float8larger - float8larger - - - - - f f 674 701 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2121 n 0 int4larger - int4larger - - - f f 563 702 0 0 0 _null_ _null_ )); DATA(insert ( 2121 n 0 int4larger - int4larger - - - - - f f 563 702 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 ( 2122 n 0 date_larger - date_larger - - - - - f f 1097 1082 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 ( 2123 n 0 time_larger - time_larger - - - - - f f 1112 1083 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 ( 2124 n 0 timetz_larger - timetz_larger - - - - - f f 1554 1266 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - f f 903 790 0 0 0 _null_ _null_ )); DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - - - f f 903 790 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 ( 2126 n 0 timestamp_larger - timestamp_larger - - - - - f f 2064 1114 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 ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - - - f f 1324 1184 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 ( 2128 n 0 interval_larger - interval_larger - - - - - f f 1334 1186 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 ( 2129 n 0 text_larger - text_larger - - - - - f f 666 25 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 ( 2130 n 0 numeric_larger - numeric_larger - - - - - f f 1756 1700 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 ( 2050 n 0 array_larger - array_larger - - - - - f f 1073 2277 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 ( 2244 n 0 bpchar_larger - bpchar_larger - - - - - f f 1060 1042 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - f f 2800 27 0 0 0 _null_ _null_ )); DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - - - f f 2800 27 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 ( 3526 n 0 enum_larger - enum_larger - - - - - f f 3519 3500 0 0 0 0 _null_ _null_ ));
DATA(insert ( 3564 n 0 network_larger - network_larger - - - f f 1205 869 0 0 0 _null_ _null_ )); DATA(insert ( 3564 n 0 network_larger - network_larger - - - - - f f 1205 869 0 0 0 0 _null_ _null_ ));
/* min */ /* min */
DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - f f 412 20 0 0 0 _null_ _null_ )); DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - - - f f 412 20 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - f f 97 23 0 0 0 _null_ _null_ )); DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - - - f f 97 23 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - f f 95 21 0 0 0 _null_ _null_ )); DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - - - f f 95 21 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - f f 609 26 0 0 0 _null_ _null_ )); DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - - - f f 609 26 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - f f 622 700 0 0 0 _null_ _null_ )); DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - - - f f 622 700 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - f f 672 701 0 0 0 _null_ _null_ )); DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - - - f f 672 701 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - f f 562 702 0 0 0 _null_ _null_ )); DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - - - f f 562 702 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 ( 2138 n 0 date_smaller - date_smaller - - - - - f f 1095 1082 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 ( 2139 n 0 time_smaller - time_smaller - - - - - f f 1110 1083 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 ( 2140 n 0 timetz_smaller - timetz_smaller - - - - - f f 1552 1266 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - f f 902 790 0 0 0 _null_ _null_ )); DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - - - f f 902 790 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 ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - - - f f 2062 1114 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 ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - - - f f 1322 1184 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 ( 2144 n 0 interval_smaller - interval_smaller - - - - - f f 1332 1186 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 ( 2145 n 0 text_smaller - text_smaller - - - - - f f 664 25 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 ( 2146 n 0 numeric_smaller - numeric_smaller - - - - - f f 1754 1700 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 ( 2051 n 0 array_smaller - array_smaller - - - - - f f 1072 2277 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 ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - - - f f 1058 1042 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - f f 2799 27 0 0 0 _null_ _null_ )); DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - - - f f 2799 27 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 ( 3527 n 0 enum_smaller - enum_smaller - - - - - f f 3518 3500 0 0 0 0 _null_ _null_ ));
DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - f f 1203 869 0 0 0 _null_ _null_ )); DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - - - f f 1203 869 0 0 0 0 _null_ _null_ ));
/* count */ /* count */
DATA(insert ( 2147 n 0 int8inc_any - int8pl int8inc_any int8dec_any - f f 0 20 0 20 0 "0" "0" )); DATA(insert ( 2147 n 0 int8inc_any - int8pl - - int8inc_any int8dec_any - 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" )); DATA(insert ( 2803 n 0 int8inc - int8pl - - int8inc int8dec - f f 0 20 0 0 20 0 "0" "0" ));
/* var_pop */ /* var_pop */
DATA(insert ( 2718 n 0 int8_accum numeric_var_pop - int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2718 n 0 int8_accum numeric_var_pop - - - int8_accum int8_accum_inv numeric_var_pop f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop - int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop - - - int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2721 n 0 float4_accum float8_var_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2721 n 0 float4_accum float8_var_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop - numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop - - - numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 0 128 2281 128 _null_ _null_ ));
/* var_samp */ /* var_samp */
DATA(insert ( 2641 n 0 int8_accum numeric_var_samp - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2641 n 0 int8_accum numeric_var_samp - - - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp - - - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2644 n 0 float4_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2644 n 0 float4_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp - - - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 0 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 - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2148 n 0 int8_accum numeric_var_samp - - - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp - - - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2151 n 0 float4_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2151 n 0 float4_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp - - - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
/* stddev_pop */ /* stddev_pop */
DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop - int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop - - - int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop - int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop - - - int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop - numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop - - - numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 0 128 2281 128 _null_ _null_ ));
/* stddev_samp */ /* stddev_samp */
DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp - - - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp - - - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp - - - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 0 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 - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp - - - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp - - - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp - int2_accum int2_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 - - - int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ ));
DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ ));
DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp - - - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ ));
/* SQL2003 binary regression aggregates */ /* SQL2003 binary regression aggregates */
DATA(insert ( 2818 n 0 int8inc_float8_float8 - - - - - f f 0 20 0 0 0 "0" _null_ )); DATA(insert ( 2818 n 0 int8inc_float8_float8 - - - - - - - f f 0 20 0 0 0 0 "0" _null_ ));
DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - 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 - - - - - - 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 - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); DATA(insert ( 2829 n 0 float8_regr_accum float8_corr - - - - - - f f 0 1022 0 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 - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); DATA(insert ( 2517 n 0 booland_statefunc - - - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ ));
DATA(insert ( 2518 n 0 boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 2281 16 _null_ _null_ )); DATA(insert ( 2518 n 0 boolor_statefunc - - - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 0 2281 16 _null_ _null_ ));
DATA(insert ( 2519 n 0 booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); DATA(insert ( 2519 n 0 booland_statefunc - - - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ ));
/* bitwise integer */ /* bitwise integer */
DATA(insert ( 2236 n 0 int2and - int2and - - - f f 0 21 0 0 0 _null_ _null_ )); DATA(insert ( 2236 n 0 int2and - int2and - - - - - 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 ( 2237 n 0 int2or - int2or - - - - - f f 0 21 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2238 n 0 int4and - int4and - - - f f 0 23 0 0 0 _null_ _null_ )); DATA(insert ( 2238 n 0 int4and - int4and - - - - - 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 ( 2239 n 0 int4or - int4or - - - - - f f 0 23 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2240 n 0 int8and - int8and - - - f f 0 20 0 0 0 _null_ _null_ )); DATA(insert ( 2240 n 0 int8and - int8and - - - - - 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 ( 2241 n 0 int8or - int8or - - - - - f f 0 20 0 0 0 0 _null_ _null_ ));
DATA(insert ( 2242 n 0 bitand - bitand - - - f f 0 1560 0 0 0 _null_ _null_ )); DATA(insert ( 2242 n 0 bitand - bitand - - - - - 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_ )); DATA(insert ( 2243 n 0 bitor - bitor - - - - - f f 0 1560 0 0 0 0 _null_ _null_ ));
/* xml */ /* xml */
DATA(insert ( 2901 n 0 xmlconcat2 - - - - - f f 0 142 0 0 0 _null_ _null_ )); DATA(insert ( 2901 n 0 xmlconcat2 - - - - - - - f f 0 142 0 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 _null_ _null_ )); DATA(insert ( 2335 n 0 array_agg_transfn array_agg_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_ )); DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - - - t f 0 2281 0 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 _null_ _null_ )); DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - - - f f 0 2281 0 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 _null_ _null_ )); DATA(insert ( 3545 n 0 bytea_string_agg_transfn bytea_string_agg_finalfn - - - - - - f f 0 2281 0 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 _null_ _null_ )); DATA(insert ( 3175 n 0 json_agg_transfn json_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_ )); DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - - - f f 0 2281 0 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 _null_ _null_ )); DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_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_ )); DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - - - f f 0 2281 0 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 _null_ _null_ )); DATA(insert ( 3972 o 1 ordered_set_transition percentile_disc_final - - - - - - t 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 ( 3974 o 1 ordered_set_transition percentile_cont_float8_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 ( 3976 o 1 ordered_set_transition percentile_cont_interval_final - - - - - - f 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 ( 3978 o 1 ordered_set_transition percentile_disc_multi_final - - - - - - t 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 ( 3980 o 1 ordered_set_transition percentile_cont_float8_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 ( 3982 o 1 ordered_set_transition percentile_cont_interval_multi_final - - - - - - f 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 ( 3984 o 0 ordered_set_transition mode_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 ( 3986 h 1 ordered_set_transition_multi 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 ( 3988 h 1 ordered_set_transition_multi percent_rank_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 ( 3990 h 1 ordered_set_transition_multi cume_dist_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_ )); DATA(insert ( 3992 h 1 ordered_set_transition_multi dense_rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ ));
/* /*
...@@ -326,6 +335,8 @@ extern ObjectAddress AggregateCreate(const char *aggName, ...@@ -326,6 +335,8 @@ extern ObjectAddress AggregateCreate(const char *aggName,
List *aggtransfnName, List *aggtransfnName,
List *aggfinalfnName, List *aggfinalfnName,
List *aggcombinefnName, List *aggcombinefnName,
List *aggserialfnName,
List *aggdeserialfnName,
List *aggmtransfnName, List *aggmtransfnName,
List *aggminvtransfnName, List *aggminvtransfnName,
List *aggmfinalfnName, List *aggmfinalfnName,
...@@ -333,6 +344,7 @@ extern ObjectAddress AggregateCreate(const char *aggName, ...@@ -333,6 +344,7 @@ 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,
......
...@@ -1836,6 +1836,7 @@ typedef struct AggState ...@@ -1836,6 +1836,7 @@ typedef struct AggState
bool agg_done; /* indicates completion of Agg scan */ bool agg_done; /* indicates completion of Agg scan */
bool combineStates; /* input tuples contain transition states */ bool combineStates; /* input tuples contain transition states */
bool finalizeAggs; /* should we call the finalfn on agg states? */ bool finalizeAggs; /* should we call the finalfn on agg states? */
bool serialStates; /* should agg states be (de)serialized? */
int projected_set; /* The last projected grouping set */ int projected_set; /* The last projected grouping set */
int current_set; /* The current grouping set being evaluated */ int current_set; /* The current grouping set being evaluated */
Bitmapset *grouped_cols; /* grouped cols in current projection */ Bitmapset *grouped_cols; /* grouped cols in current projection */
......
...@@ -712,6 +712,7 @@ typedef struct Agg ...@@ -712,6 +712,7 @@ typedef struct Agg
AggStrategy aggstrategy; /* basic strategy, see nodes.h */ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
bool combineStates; /* input tuples contain transition states */ bool combineStates; /* input tuples contain transition states */
bool finalizeAggs; /* should we call the finalfn on agg states? */ bool finalizeAggs; /* should we call the finalfn on agg states? */
bool serialStates; /* should agg states be (de)serialized? */
int numCols; /* number of grouping columns */ int numCols; /* number of grouping columns */
AttrNumber *grpColIdx; /* their indexes in the target list */ AttrNumber *grpColIdx; /* their indexes in the target list */
Oid *grpOperators; /* equality operators to compare with */ Oid *grpOperators; /* equality operators to compare with */
......
...@@ -1296,6 +1296,7 @@ typedef struct AggPath ...@@ -1296,6 +1296,7 @@ typedef struct AggPath
List *qual; /* quals (HAVING quals), if any */ List *qual; /* quals (HAVING quals), if any */
bool combineStates; /* input is partially aggregated agg states */ bool combineStates; /* input is partially aggregated agg states */
bool finalizeAggs; /* should the executor call the finalfn? */ bool finalizeAggs; /* should the executor call the finalfn? */
bool serialStates; /* should agg states be (de)serialized? */
} AggPath; } AggPath;
/* /*
......
...@@ -171,7 +171,8 @@ extern AggPath *create_agg_path(PlannerInfo *root, ...@@ -171,7 +171,8 @@ extern AggPath *create_agg_path(PlannerInfo *root,
const AggClauseCosts *aggcosts, const AggClauseCosts *aggcosts,
double numGroups, double numGroups,
bool combineStates, bool combineStates,
bool finalizeAggs); bool finalizeAggs,
bool serialStates);
extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root, extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root,
RelOptInfo *rel, RelOptInfo *rel,
Path *subpath, Path *subpath,
......
...@@ -58,7 +58,7 @@ extern bool is_projection_capable_plan(Plan *plan); ...@@ -58,7 +58,7 @@ extern bool is_projection_capable_plan(Plan *plan);
/* External use of these functions is deprecated: */ /* External use of these functions is deprecated: */
extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree); extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree);
extern Agg *make_agg(List *tlist, List *qual, AggStrategy aggstrategy, extern Agg *make_agg(List *tlist, List *qual, AggStrategy aggstrategy,
bool combineStates, bool finalizeAggs, bool combineStates, bool finalizeAggs, bool serialStates,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
List *groupingSets, List *chain, List *groupingSets, List *chain,
double dNumGroups, Plan *lefttree); double dNumGroups, Plan *lefttree);
......
...@@ -51,6 +51,12 @@ extern void build_aggregate_combinefn_expr(Oid agg_state_type, ...@@ -51,6 +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,
Oid agg_serial_type,
Oid agg_input_collation,
Oid serialfn_oid,
Expr **serialfnexpr);
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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment