Allow aggregate transition states to be serialized and deserialized.
authorRobert Haas <rhaas@postgresql.org>
Tue, 29 Mar 2016 19:04:05 +0000 (15:04 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 29 Mar 2016 19:04:05 +0000 (15:04 -0400)
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.

25 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_aggregate.sgml
src/backend/catalog/pg_aggregate.c
src/backend/commands/aggregatecmds.c
src/backend/executor/nodeAgg.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/tlist.c
src/backend/parser/parse_agg.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.h
src/include/nodes/execnodes.h
src/include/nodes/plannodes.h
src/include/nodes/relation.h
src/include/optimizer/pathnode.h
src/include/optimizer/planmain.h
src/include/parser/parse_agg.h

index 4a0ede6a72c515a9bccb78013ac97e69e72d64ef..bb752294c3fa3edbf9174f7d8e2362ccf94d1795 100644 (file)
       <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
       <entry>Combine function (zero if none)</entry>
      </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>
       <entry><structfield>aggmtransfn</structfield></entry>
       <entry><type>regproc</type></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>
      </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>
       <entry><structfield>aggtransspace</structfield></entry>
       <entry><type>int4</type></entry>
index 837b83c00b82fc055c7e45d45a42bdbba77172f1..7a6f8a97fdac11ec6f123523ce79af8bcf6a4430 100644 (file)
@@ -28,6 +28,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , FINALFUNC_EXTRA ]
     [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
+    [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
+    [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
+    [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
     [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
@@ -47,6 +50,9 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , FINALFUNC_EXTRA ]
     [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
+    [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
+    [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
+    [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , HYPOTHETICAL ]
 )
@@ -61,6 +67,9 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , FINALFUNC_EXTRA ]
     [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ]
+    [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ]
+    [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ]
+    [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
     [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
@@ -436,6 +445,47 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
     </listitem>
    </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>
     <term><replaceable class="PARAMETER">initial_condition</replaceable></term>
     <listitem>
index c612ab9809ec126de459b3327af7d429506f1588..b420349835b05a7740ea688f2d8b03eb0a02e7b1 100644 (file)
@@ -58,6 +58,8 @@ AggregateCreate(const char *aggName,
                                List *aggtransfnName,
                                List *aggfinalfnName,
                                List *aggcombinefnName,
+                               List *aggserialfnName,
+                               List *aggdeserialfnName,
                                List *aggmtransfnName,
                                List *aggminvtransfnName,
                                List *aggmfinalfnName,
@@ -65,6 +67,7 @@ AggregateCreate(const char *aggName,
                                bool mfinalfnExtraArgs,
                                List *aggsortopName,
                                Oid aggTransType,
+                               Oid aggSerialType,
                                int32 aggTransSpace,
                                Oid aggmTransType,
                                int32 aggmTransSpace,
@@ -79,6 +82,8 @@ AggregateCreate(const char *aggName,
        Oid                     transfn;
        Oid                     finalfn = 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                     minvtransfn = InvalidOid;               /* can be omitted */
        Oid                     mfinalfn = InvalidOid;  /* can be omitted */
@@ -420,6 +425,57 @@ AggregateCreate(const char *aggName,
                        errmsg("return type of combine function %s is not %s",
                                   NameListToString(aggcombinefnName),
                                   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,
        values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
        values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
        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_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
        values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
@@ -601,6 +659,7 @@ AggregateCreate(const char *aggName,
        values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
        values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
        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_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
        values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
@@ -627,7 +686,8 @@ AggregateCreate(const char *aggName,
         * Create dependencies for the aggregate (above and beyond those already
         * made by ProcedureCreate).  Note: we don't need an explicit dependency
         * 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 */
@@ -654,6 +714,24 @@ AggregateCreate(const char *aggName,
                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 */
        if (OidIsValid(mtransfn))
        {
index 59bc6e6fd8f7741cb9c66cc034b64e9b35f63606..3424f842b9c0b4e30098cc334772d273af35b175 100644 (file)
@@ -62,6 +62,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
        List       *transfuncName = NIL;
        List       *finalfuncName = NIL;
        List       *combinefuncName = NIL;
+       List       *serialfuncName = NIL;
+       List       *deserialfuncName = NIL;
        List       *mtransfuncName = NIL;
        List       *minvtransfuncName = NIL;
        List       *mfinalfuncName = NIL;
@@ -70,6 +72,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
        List       *sortoperatorName = NIL;
        TypeName   *baseType = NULL;
        TypeName   *transType = NULL;
+       TypeName   *serialType = NULL;
        TypeName   *mtransType = NULL;
        int32           transSpace = 0;
        int32           mtransSpace = 0;
@@ -84,6 +87,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
        List       *parameterDefaults;
        Oid                     variadicArgType;
        Oid                     transTypeId;
+       Oid                     serialTypeId = InvalidOid;
        Oid                     mtransTypeId = InvalidOid;
        char            transTypeType;
        char            mtransTypeType = 0;
@@ -127,6 +131,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                        finalfuncName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "combinefunc") == 0)
                        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)
                        mtransfuncName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "minvfunc") == 0)
@@ -154,6 +162,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                }
                else if (pg_strcasecmp(defel->defname, "stype") == 0)
                        transType = defGetTypeName(defel);
+               else if (pg_strcasecmp(defel->defname, "serialtype") == 0)
+                       serialType = defGetTypeName(defel);
                else if (pg_strcasecmp(defel->defname, "stype1") == 0)
                        transType = defGetTypeName(defel);
                else if (pg_strcasecmp(defel->defname, "sspace") == 0)
@@ -319,6 +329,75 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                                                        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
         * restrictions as for transtype.
@@ -387,6 +466,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                                                   transfuncName,               /* step function name */
                                                   finalfuncName,               /* final function name */
                                                   combinefuncName,             /* combine function name */
+                                                  serialfuncName,              /* serial function name */
+                                                  deserialfuncName,    /* deserial function name */
                                                   mtransfuncName,              /* fwd trans function name */
                                                   minvtransfuncName,   /* inv trans function name */
                                                   mfinalfuncName,              /* final function name */
@@ -394,6 +475,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                                                   mfinalfuncExtraArgs,
                                                   sortoperatorName,    /* sort operator name */
                                                   transTypeId, /* transition data type */
+                                                  serialTypeId, /* serialization data type */
                                                   transSpace,  /* transition space */
                                                   mtransTypeId,                /* transition data type */
                                                   mtransSpace, /* transition space */
index 03aa20f61e0d4ec5b5b99af07ab5f4a5f0fba371..aba54195a30ef6f449439abb8b4c8110c3e4cc10 100644 (file)
  *       incorrect. Instead a new state should be created in the correct aggregate
  *       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
  *       input tuples and eliminate duplicates (if required) before performing
  *       the above-depicted process.  (However, we don't do that for ordered-set
@@ -232,6 +238,12 @@ typedef struct AggStatePerTransData
        /* Oid of the state transition or combine function */
        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                     aggtranstype;
 
@@ -246,6 +258,12 @@ typedef struct AggStatePerTransData
         */
        FmgrInfo        transfn;
 
+       /* fmgr lookup data for serialization function */
+       FmgrInfo        serialfn;
+
+       /* fmgr lookup data for deserialization function */
+       FmgrInfo        deserialfn;
+
        /* Input collation derived for aggregate */
        Oid                     aggCollation;
 
@@ -326,6 +344,11 @@ typedef struct AggStatePerTransData
         * worth the extra space consumption.
         */
        FunctionCallInfoData transfn_fcinfo;
+
+       /* Likewise for serialization and deserialization functions */
+       FunctionCallInfoData serialfn_fcinfo;
+
+       FunctionCallInfoData deserialfn_fcinfo;
 }      AggStatePerTransData;
 
 /*
@@ -467,6 +490,10 @@ static void finalize_aggregate(AggState *aggstate,
                                   AggStatePerAgg peragg,
                                   AggStatePerGroup pergroupstate,
                                   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,
                                                TupleTableSlot *slot,
                                                int currentSet);
@@ -487,12 +514,15 @@ static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
 static void build_pertrans_for_aggref(AggStatePerTrans pertrans,
                                                  AggState *aggsate, EState *estate,
                                                  Aggref *aggref, Oid aggtransfn, Oid aggtranstype,
-                                                 Datum initValue, bool initValueIsNull,
-                                                 Oid *inputTypes, int numArguments);
+                                                 Oid aggserialtype, Oid aggserialfn,
+                                                 Oid aggdeserialfn, Datum initValue,
+                                                 bool initValueIsNull, Oid *inputTypes,
+                                                 int numArguments);
 static int find_compatible_peragg(Aggref *newagg, AggState *aggstate,
                                           int lastaggno, List **same_input_transnos);
 static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
                                                 Oid aggtransfn, Oid aggtranstype,
+                                                Oid aggserialfn, Oid aggdeserialfn,
                                                 Datum initValue, bool initValueIsNull,
                                                 List *transnos);
 
@@ -944,8 +974,45 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
                slot = ExecProject(pertrans->evalproj, NULL);
                Assert(slot->tts_nvalid >= 1);
 
-               fcinfo->arg[1] = slot->tts_values[0];
-               fcinfo->argnull[1] = slot->tts_isnull[0];
+               /*
+                * 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->argnull[1] = slot->tts_isnull[0];
+               }
 
                advance_combine_function(aggstate, pertrans, pergroupstate);
        }
@@ -1344,6 +1411,61 @@ finalize_aggregate(AggState *aggstate,
        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
@@ -1455,10 +1577,8 @@ finalize_aggregates(AggState *aggstate,
                        finalize_aggregate(aggstate, peragg, pergroupstate,
                                                           &aggvalues[aggno], &aggnulls[aggno]);
                else
-               {
-                       aggvalues[aggno] = pergroupstate->transValue;
-                       aggnulls[aggno] = pergroupstate->transValueIsNull;
-               }
+                       finalize_partialaggregate(aggstate, peragg, pergroupstate,
+                                                                         &aggvalues[aggno], &aggnulls[aggno]);
        }
 }
 
@@ -2238,6 +2358,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
        aggstate->agg_done = false;
        aggstate->combineStates = node->combineStates;
        aggstate->finalizeAggs = node->finalizeAggs;
+       aggstate->serialStates = node->serialStates;
        aggstate->input_done = false;
        aggstate->pergroup = NULL;
        aggstate->grp_firstTuple = NULL;
@@ -2546,6 +2667,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                AclResult       aclresult;
                Oid                     transfn_oid,
                                        finalfn_oid;
+               Oid                     serialtype_oid,
+                                       serialfn_oid,
+                                       deserialfn_oid;
                Expr       *finalfnexpr;
                Oid                     aggtranstype;
                Datum           textInitVal;
@@ -2610,6 +2734,47 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                else
                        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 */
                {
                        HeapTuple       procTuple;
@@ -2638,6 +2803,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                                                                   get_func_name(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,7 +2890,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                 */
                existing_transno = find_compatible_pertrans(aggstate, aggref,
                                                                                                        transfn_oid, aggtranstype,
-                                                                                                 initValue, initValueIsNull,
+                                                                                                 serialfn_oid, deserialfn_oid,
+                                                                                                       initValue, initValueIsNull,
                                                                                                        same_input_transnos);
                if (existing_transno != -1)
                {
@@ -2723,8 +2907,10 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                        pertrans = &pertransstates[++transno];
                        build_pertrans_for_aggref(pertrans, aggstate, estate,
                                                                          aggref, transfn_oid, aggtranstype,
-                                                                         initValue, initValueIsNull,
-                                                                         inputTypes, numArguments);
+                                                                         serialtype_oid, serialfn_oid,
+                                                                         deserialfn_oid, initValue,
+                                                                         initValueIsNull, inputTypes,
+                                                                         numArguments);
                        peragg->transno = transno;
                }
                ReleaseSysCache(aggTuple);
@@ -2752,11 +2938,14 @@ static void
 build_pertrans_for_aggref(AggStatePerTrans pertrans,
                                                  AggState *aggstate, EState *estate,
                                                  Aggref *aggref,
-                                                 Oid aggtransfn, Oid aggtranstype,
+                                                 Oid aggtransfn, Oid aggtranstype, Oid aggserialtype,
+                                                 Oid aggserialfn, Oid aggdeserialfn,
                                                  Datum initValue, bool initValueIsNull,
                                                  Oid *inputTypes, int numArguments)
 {
        int                     numGroupingSets = Max(aggstate->maxsets, 1);
+       Expr       *serialfnexpr = NULL;
+       Expr       *deserialfnexpr = NULL;
        ListCell   *lc;
        int                     numInputs;
        int                     numDirectArgs;
@@ -2770,6 +2959,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
        pertrans->aggref = aggref;
        pertrans->aggCollation = aggref->inputcollid;
        pertrans->transfn_oid = aggtransfn;
+       pertrans->serialfn_oid = aggserialfn;
+       pertrans->deserialfn_oid = aggdeserialfn;
        pertrans->initValue = initValue;
        pertrans->initValueIsNull = initValueIsNull;
 
@@ -2809,6 +3000,17 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
                                                                 2,
                                                                 pertrans->aggCollation,
                                                                 (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
        {
@@ -2861,6 +3063,41 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
                                        &pertrans->transtypeLen,
                                        &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
         * expressions) of the agg.
@@ -3107,6 +3344,7 @@ find_compatible_peragg(Aggref *newagg, AggState *aggstate,
 static int
 find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
                                                 Oid aggtransfn, Oid aggtranstype,
+                                                Oid aggserialfn, Oid aggdeserialfn,
                                                 Datum initValue, bool initValueIsNull,
                                                 List *transnos)
 {
@@ -3125,6 +3363,17 @@ find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
                        aggtranstype != pertrans->aggtranstype)
                        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. */
                if (initValueIsNull && pertrans->initValueIsNull)
                        return transno;
index 6378db8bbea1006f447190c8f23987f36a8d02e0..f4e4a91ba53a72d692e5b25fe6ef69c6ee02efbb 100644 (file)
@@ -871,6 +871,7 @@ _copyAgg(const Agg *from)
        COPY_SCALAR_FIELD(aggstrategy);
        COPY_SCALAR_FIELD(combineStates);
        COPY_SCALAR_FIELD(finalizeAggs);
+       COPY_SCALAR_FIELD(serialStates);
        COPY_SCALAR_FIELD(numCols);
        if (from->numCols > 0)
        {
index 83abaa68a386e2d7406fc6628faf73f3a30a3188..5b71c95ede782acd1ed3e3f65ddf13677b7d4a43 100644 (file)
@@ -708,6 +708,7 @@ _outAgg(StringInfo str, const Agg *node)
        WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
        WRITE_BOOL_FIELD(combineStates);
        WRITE_BOOL_FIELD(finalizeAggs);
+       WRITE_BOOL_FIELD(serialStates);
        WRITE_INT_FIELD(numCols);
 
        appendStringInfoString(str, " :grpColIdx");
index cb0752a6ad895862df25c22ef4f48ae5809d6036..202e90abc5328c26cf2582a9d329206f7b12f510 100644 (file)
@@ -1993,6 +1993,7 @@ _readAgg(void)
        READ_ENUM_FIELD(aggstrategy, AggStrategy);
        READ_BOOL_FIELD(combineStates);
        READ_BOOL_FIELD(finalizeAggs);
+       READ_BOOL_FIELD(serialStates);
        READ_INT_FIELD(numCols);
        READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
        READ_OID_ARRAY(grpOperators, local_node->numCols);
index e4bc14a1510e0044fc79fe6a4491a15da4240545..994983b9164fdea858c82b8239e67e1338c978c2 100644 (file)
@@ -1279,6 +1279,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
                                                                 AGG_HASHED,
                                                                 false,
                                                                 true,
+                                                                false,
                                                                 numGroupCols,
                                                                 groupColIdx,
                                                                 groupOperators,
@@ -1578,6 +1579,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path)
                                        best_path->aggstrategy,
                                        best_path->combineStates,
                                        best_path->finalizeAggs,
+                                       best_path->serialStates,
                                        list_length(best_path->groupClause),
                                        extract_grouping_cols(best_path->groupClause,
                                                                                  subplan->targetlist),
@@ -1732,6 +1734,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
                                                                                 AGG_SORTED,
                                                                                 false,
                                                                                 true,
+                                                                                false,
                                                                           list_length((List *) linitial(gsets)),
                                                                                 new_grpColIdx,
                                                                                 extract_grouping_ops(groupClause),
@@ -1768,6 +1771,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
                                                (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
                                                false,
                                                true,
+                                               false,
                                                numGroupCols,
                                                top_grpColIdx,
                                                extract_grouping_ops(groupClause),
@@ -5636,7 +5640,7 @@ materialize_finished_plan(Plan *subplan)
 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,
                 List *groupingSets, List *chain,
                 double dNumGroups, Plan *lefttree)
@@ -5651,6 +5655,7 @@ make_agg(List *tlist, List *qual,
        node->aggstrategy = aggstrategy;
        node->combineStates = combineStates;
        node->finalizeAggs = finalizeAggs;
+       node->serialStates = serialStates;
        node->numCols = numGroupCols;
        node->grpColIdx = grpColIdx;
        node->grpOperators = grpOperators;
index 86d80727ed9ac45a8fb0504923a142da66ce5a82..b2a9a8088f61d855945e5ec57eb7298a056a091d 100644 (file)
@@ -3455,7 +3455,8 @@ create_grouping_paths(PlannerInfo *root,
                                                                                                        &agg_costs,
                                                                                                        dNumPartialGroups,
                                                                                                        false,
-                                                                                                       false));
+                                                                                                       false,
+                                                                                                       true));
                                        else
                                                add_partial_path(grouped_rel, (Path *)
                                                                        create_group_path(root,
@@ -3496,7 +3497,8 @@ create_grouping_paths(PlannerInfo *root,
                                                                                        &agg_costs,
                                                                                        dNumPartialGroups,
                                                                                        false,
-                                                                                       false));
+                                                                                       false,
+                                                                                       true));
                        }
                }
        }
@@ -3560,7 +3562,8 @@ create_grouping_paths(PlannerInfo *root,
                                                                                         &agg_costs,
                                                                                         dNumGroups,
                                                                                         false,
-                                                                                        true));
+                                                                                        true,
+                                                                                        false));
                                }
                                else if (parse->groupClause)
                                {
@@ -3626,6 +3629,7 @@ create_grouping_paths(PlannerInfo *root,
                                                                                        &agg_costs,
                                                                                        dNumGroups,
                                                                                        true,
+                                                                                       true,
                                                                                        true));
                        else
                                add_path(grouped_rel, (Path *)
@@ -3668,7 +3672,8 @@ create_grouping_paths(PlannerInfo *root,
                                                                         &agg_costs,
                                                                         dNumGroups,
                                                                         false,
-                                                                        true));
+                                                                        true,
+                                                                        false));
                }
 
                /*
@@ -3706,6 +3711,7 @@ create_grouping_paths(PlannerInfo *root,
                                                                                        &agg_costs,
                                                                                        dNumGroups,
                                                                                        true,
+                                                                                       true,
                                                                                        true));
                        }
                }
@@ -4039,7 +4045,8 @@ create_distinct_paths(PlannerInfo *root,
                                                                 NULL,
                                                                 numDistinctRows,
                                                                 false,
-                                                                true));
+                                                                true,
+                                                                false));
        }
 
        /* Give a helpful error if we failed to find any implementation */
index 16f572faf425b3ea2f1c95e1b4d14b4262c884c1..dd2b9ed9f08bc639d1f51f4b1908b32c5e9d8b82 100644 (file)
@@ -2057,10 +2057,10 @@ search_indexed_tlist_for_sortgroupref(Node *node,
  * search_indexed_tlist_for_partial_aggref - find an Aggref in an indexed tlist
  *
  * Aggrefs for partial aggregates have their aggoutputtype adjusted to set it
- * to the aggregate state's type. This means that a standard equal() comparison
- * won't match when comparing an Aggref which is in partial mode with an Aggref
- * which is not. Here we manually compare all of the fields apart from
- * aggoutputtype.
+ * to the aggregate state's type, or serialization type. This means that a
+ * standard equal() comparison won't match when comparing an Aggref which is
+ * in partial mode with an Aggref which is not. Here we manually compare all of
+ * the fields apart from aggoutputtype.
  */
 static Var *
 search_indexed_tlist_for_partial_aggref(Aggref *aggref, indexed_tlist *itlist,
index fb139af2c1c9488b29f64a7535ed6b429e62e26d..a1ab4daf11a7d8e3361467d8837f6e0831ccbf5a 100644 (file)
@@ -861,7 +861,8 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
                                                                                NULL,
                                                                                dNumGroups,
                                                                                false,
-                                                                               true);
+                                                                               true,
+                                                                               false);
        }
        else
        {
index d80dfbe5c9fa6b8811c493179a327433ee82f282..c615717dea3214a36a475c5dcf9dc22bb8700e18 100644 (file)
@@ -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
-                * that pointers to aggregate states are not passed to other processes;
-                * therefore, we set the maximum allowed type to PAT_INTERNAL_ONLY.
+                * If we find any aggs with an internal transtype then we must check
+                * that these have a serialization type, serialization func and
+                * 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;
 
                ReleaseSysCache(aggTuple);
index 16b34fcf46a51898e3c3ed037c741cd03fc5f75b..89cae793ca3b26224bbd1c02b73a82777581fb4f 100644 (file)
@@ -2433,7 +2433,8 @@ create_agg_path(PlannerInfo *root,
                                const AggClauseCosts *aggcosts,
                                double numGroups,
                                bool combineStates,
-                               bool finalizeAggs)
+                               bool finalizeAggs,
+                               bool serialStates)
 {
        AggPath    *pathnode = makeNode(AggPath);
 
@@ -2458,6 +2459,7 @@ create_agg_path(PlannerInfo *root,
        pathnode->qual = qual;
        pathnode->finalizeAggs = finalizeAggs;
        pathnode->combineStates = combineStates;
+       pathnode->serialStates = serialStates;
 
        cost_agg(&pathnode->path, root,
                         aggstrategy, aggcosts,
index cd421b14632b2a73711409287b31625ff576f614..4c8c83da80dede8e7fd0a42cf43f75c2aee45d53 100644 (file)
@@ -756,8 +756,8 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
  * apply_partialaggref_adjustment
  *       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
- *       the aggtranstype. This allows exprType() to return the actual type that
- *       will be produced.
+ *       the aggtranstype or aggserialtype. This allows exprType() to return the
+ *       actual type that will be produced.
  *
  * Note: We expect 'target' to be a flat target list and not have Aggrefs burried
  * within other expressions.
@@ -785,7 +785,12 @@ apply_partialaggref_adjustment(PathTarget *target)
                        aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
 
                        newaggref = (Aggref *) copyObject(aggref);
-                       newaggref->aggoutputtype = aggform->aggtranstype;
+
+                       /* use the serialization type, if one exists */
+                       if (OidIsValid(aggform->aggserialtype))
+                               newaggref->aggoutputtype = aggform->aggserialtype;
+                       else
+                               newaggref->aggoutputtype = aggform->aggtranstype;
 
                        lfirst(lc) = newaggref;
 
index 583462a91810a0ba7596d1037ac6f3d9736dde3e..91bfe66c590abbb62e2795becc04ea4865b5a8b1 100644 (file)
@@ -1964,6 +1964,45 @@ build_aggregate_combinefn_expr(Oid agg_state_type,
        *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
  * final function of an aggregate, rather than the transition function.
index 077b37eb43dbedce1d2ecf0bec390f57880685db..454225da43c219042cc64b161649da86c19707fb 100644 (file)
@@ -12557,6 +12557,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        int                     i_aggtransfn;
        int                     i_aggfinalfn;
        int                     i_aggcombinefn;
+       int                     i_aggserialfn;
+       int                     i_aggdeserialfn;
        int                     i_aggmtransfn;
        int                     i_aggminvtransfn;
        int                     i_aggmfinalfn;
@@ -12565,6 +12567,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        int                     i_aggsortop;
        int                     i_hypothetical;
        int                     i_aggtranstype;
+       int                     i_aggserialtype;
        int                     i_aggtransspace;
        int                     i_aggmtranstype;
        int                     i_aggmtransspace;
@@ -12574,6 +12577,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        const char *aggtransfn;
        const char *aggfinalfn;
        const char *aggcombinefn;
+       const char *aggserialfn;
+       const char *aggdeserialfn;
        const char *aggmtransfn;
        const char *aggminvtransfn;
        const char *aggmfinalfn;
@@ -12583,6 +12588,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        char       *aggsortconvop;
        bool            hypothetical;
        const char *aggtranstype;
+       const char *aggserialtype;
        const char *aggtransspace;
        const char *aggmtranstype;
        const char *aggmtransspace;
@@ -12608,10 +12614,11 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                        "aggfinalfn, aggtranstype::pg_catalog.regtype, "
-                       "aggcombinefn, aggmtransfn, "
+                       "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
                        "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                        "aggfinalextra, aggmfinalextra, "
                        "aggsortop::pg_catalog.regoperator, "
+                       "aggserialtype::pg_catalog.regtype, "
                        "(aggkind = 'h') AS hypothetical, "
                        "aggtransspace, agginitval, "
                        "aggmtransspace, aggminitval, "
@@ -12627,10 +12634,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
-                                                 "'-' AS aggcombinefn, aggmtransfn, aggminvtransfn, "
+                                                 "'-' AS aggcombinefn, '-' AS aggserialfn, "
+                                                 "'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, "
                                                  "aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                                                  "aggfinalextra, aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
+                                                 "0 AS aggserialtype, "
                                                  "(aggkind = 'h') AS hypothetical, "
                                                  "aggtransspace, agginitval, "
                                                  "aggmtransspace, aggminitval, "
@@ -12646,11 +12655,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
-                                                 "'-' AS aggcombinefn, '-' AS aggmtransfn, "
+                                                 "'-' AS aggcombinefn, '-' AS aggserialfn, "
+                                                 "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                                                  "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
+                                                 "0 AS aggserialtype, "
                                                  "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -12666,11 +12677,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
-                                                 "'-' AS aggcombinefn, '-' AS aggmtransfn, "
+                                                 "'-' AS aggcombinefn, '-' AS aggserialfn, "
+                                                 "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                                                  "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
+                                                 "0 AS aggserialtype, "
                                                  "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -12684,10 +12697,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
-                                                 "'-' AS aggcombinefn, '-' AS aggmtransfn, "
+                                                 "'-' AS aggcombinefn, '-' AS aggserialfn, "
+                                                 "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                                                  "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, 0 AS aggsortop, "
+                                                 "0 AS aggserialtype, "
                                                  "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -12701,10 +12716,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
                                                  "format_type(aggtranstype, NULL) AS aggtranstype, "
-                                                 "'-' AS aggcombinefn, '-' AS aggmtransfn, "
+                                                 "'-' AS aggcombinefn, '-' AS aggserialfn, "
+                                                 "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                                                  "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, 0 AS aggsortop, "
+                                                 "0 AS aggserialtype, "
                                                  "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -12718,10 +12735,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, "
                                                  "aggfinalfn, "
                                                  "(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, "
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, 0 AS aggsortop, "
+                                                 "0 AS aggserialtype, "
                                                  "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval1 AS agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -12736,12 +12755,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        i_aggtransfn = PQfnumber(res, "aggtransfn");
        i_aggfinalfn = PQfnumber(res, "aggfinalfn");
        i_aggcombinefn = PQfnumber(res, "aggcombinefn");
+       i_aggserialfn = PQfnumber(res, "aggserialfn");
+       i_aggdeserialfn = PQfnumber(res, "aggdeserialfn");
        i_aggmtransfn = PQfnumber(res, "aggmtransfn");
        i_aggminvtransfn = PQfnumber(res, "aggminvtransfn");
        i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
        i_aggfinalextra = PQfnumber(res, "aggfinalextra");
        i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
        i_aggsortop = PQfnumber(res, "aggsortop");
+       i_aggserialtype = PQfnumber(res, "aggserialtype");
        i_hypothetical = PQfnumber(res, "hypothetical");
        i_aggtranstype = PQfnumber(res, "aggtranstype");
        i_aggtransspace = PQfnumber(res, "aggtransspace");
@@ -12754,6 +12776,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
        aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
        aggcombinefn = PQgetvalue(res, 0, i_aggcombinefn);
+       aggserialfn = PQgetvalue(res, 0, i_aggserialfn);
+       aggdeserialfn = PQgetvalue(res, 0, i_aggdeserialfn);
        aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn);
        aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn);
        aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
@@ -12762,6 +12786,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        aggsortop = PQgetvalue(res, 0, i_aggsortop);
        hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't');
        aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+       aggserialtype = PQgetvalue(res, 0, i_aggserialtype);
        aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
        aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
        aggmtransspace = PQgetvalue(res, 0, i_aggmtransspace);
@@ -12847,6 +12872,17 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                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)
        {
                appendPQExpBuffer(details, ",\n    MSFUNC = %s,\n    MINVFUNC = %s,\n    MSTYPE = %s",
index b690dc6b34f466e84f69026e928e69d48729ec9b..92ea48da8957dfb1c76d68818877d0f936ac61bf 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201603231
+#define CATALOG_VERSION_NO     201603291
 
 #endif
index 441db304dfb1b3918615b1944dac95712e1aaae7..4205fabb576f907a4127b169847445eda8ae8190 100644 (file)
@@ -34,6 +34,8 @@
  *     aggtransfn                      transition function
  *     aggfinalfn                      final 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)
  *     aggminvtransfn          inverse function for moving-aggregate mode (0 if none)
  *     aggmfinalfn                     final function for moving-aggregate mode (0 if none)
@@ -43,6 +45,7 @@
  *     aggtranstype            type of aggregate's transition (state) data
  *     aggtransspace           estimated size of state data (0 for default estimate)
  *     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)
  *     agginitval                      initial value for transition 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
        regproc         aggtransfn;
        regproc         aggfinalfn;
        regproc         aggcombinefn;
+       regproc         aggserialfn;
+       regproc         aggdeserialfn;
        regproc         aggmtransfn;
        regproc         aggminvtransfn;
        regproc         aggmfinalfn;
@@ -65,6 +70,7 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
        bool            aggmfinalextra;
        Oid                     aggsortop;
        Oid                     aggtranstype;
+       Oid                     aggserialtype;
        int32           aggtransspace;
        Oid                     aggmtranstype;
        int32           aggmtransspace;
@@ -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_aggkind                      2
 #define Anum_pg_aggregate_aggnumdirectargs     3
 #define Anum_pg_aggregate_aggtransfn           4
 #define Anum_pg_aggregate_aggfinalfn           5
 #define Anum_pg_aggregate_aggcombinefn         6
-#define Anum_pg_aggregate_aggmtransfn          7
-#define Anum_pg_aggregate_aggminvtransfn       8
-#define Anum_pg_aggregate_aggmfinalfn          9
-#define Anum_pg_aggregate_aggfinalextra                10
-#define Anum_pg_aggregate_aggmfinalextra       11
-#define Anum_pg_aggregate_aggsortop                    12
-#define Anum_pg_aggregate_aggtranstype         13
-#define Anum_pg_aggregate_aggtransspace                14
-#define Anum_pg_aggregate_aggmtranstype                15
-#define Anum_pg_aggregate_aggmtransspace       16
-#define Anum_pg_aggregate_agginitval           17
-#define Anum_pg_aggregate_aggminitval          18
+#define Anum_pg_aggregate_aggserialfn          7
+#define Anum_pg_aggregate_aggdeserialfn                8
+#define Anum_pg_aggregate_aggmtransfn          9
+#define Anum_pg_aggregate_aggminvtransfn       10
+#define Anum_pg_aggregate_aggmfinalfn          11
+#define Anum_pg_aggregate_aggfinalextra                12
+#define Anum_pg_aggregate_aggmfinalextra       13
+#define Anum_pg_aggregate_aggsortop                    14
+#define Anum_pg_aggregate_aggtranstype         15
+#define Anum_pg_aggregate_aggserialtype                16
+#define Anum_pg_aggregate_aggtransspace                17
+#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
@@ -129,184 +138,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
  */
 
 /* 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 ( 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 ( 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 ( 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 ( 2104     n 0 float4_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}" _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 ( 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       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    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,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       0       1187    0       "{0 second,0 second}" "{0 second,0 second}" ));
 
 /* 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 ( 2108     n 0 int4_sum            -                                       int8pl                          int4_avg_accum  int4_avg_accum_inv      int2int4_sum            f f 0   20              0       1016    0       _null_ "{0,0}" ));
-DATA(insert ( 2109     n 0 int2_sum            -                                       int8pl                          int2_avg_accum  int2_avg_accum_inv      int2int4_sum            f f 0   20              0       1016    0       _null_ "{0,0}" ));
-DATA(insert ( 2110     n 0 float4pl            -                                       float4pl                        -                               -                                       -                                       f f 0   700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2111     n 0 float8pl            -                                       float8pl                        -                               -                                       -                                       f f 0   701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2112     n 0 cash_pl                     -                                       cash_pl                         cash_pl                 cash_mi                         -                                       f f 0   790             0       790             0       _null_ _null_ ));
-DATA(insert ( 2113     n 0 interval_pl         -                                       interval_pl                     interval_pl             interval_mi                     -                                       f f 0   1186    0       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 ( 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       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               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       0       790             0       _null_ _null_ ));
+DATA(insert ( 2113     n 0 interval_pl         -                                       interval_pl                     -       -       interval_pl             interval_mi                     -                                       f f 0   1186    0       0       1186    0       _null_ _null_ ));
+DATA(insert ( 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 */
-DATA(insert ( 2115     n 0 int8larger          -                               int8larger                      -                               -                               -                               f f 413         20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2116     n 0 int4larger          -                               int4larger                      -                               -                               -                               f f 521         23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2117     n 0 int2larger          -                               int2larger                      -                               -                               -                               f f 520         21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2118     n 0 oidlarger           -                               oidlarger                       -                               -                               -                               f f 610         26              0       0               0       _null_ _null_ ));
-DATA(insert ( 2119     n 0 float4larger        -                               float4larger            -                               -                               -                               f f 623         700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2120     n 0 float8larger        -                               float8larger            -                               -                               -                               f f 674         701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2121     n 0 int4larger          -                               int4larger                      -                               -                               -                               f f 563         702             0       0               0       _null_ _null_ ));
-DATA(insert ( 2122     n 0 date_larger         -                               date_larger                     -                               -                               -                               f f 1097        1082    0       0               0       _null_ _null_ ));
-DATA(insert ( 2123     n 0 time_larger         -                               time_larger                     -                               -                               -                               f f 1112        1083    0       0               0       _null_ _null_ ));
-DATA(insert ( 2124     n 0 timetz_larger       -                               timetz_larger           -                               -                               -                               f f 1554        1266    0       0               0       _null_ _null_ ));
-DATA(insert ( 2125     n 0 cashlarger          -                               cashlarger                      -                               -                               -                               f f 903         790             0       0               0       _null_ _null_ ));
-DATA(insert ( 2126     n 0 timestamp_larger    -                       timestamp_larger        -                               -                               -                               f f 2064        1114    0       0               0       _null_ _null_ ));
-DATA(insert ( 2127     n 0 timestamptz_larger  -                       timestamptz_larger      -                               -                               -                               f f 1324        1184    0       0               0       _null_ _null_ ));
-DATA(insert ( 2128     n 0 interval_larger -                           interval_larger         -                               -                               -                               f f 1334        1186    0       0               0       _null_ _null_ ));
-DATA(insert ( 2129     n 0 text_larger         -                               text_larger                     -                               -                               -                               f f 666         25              0       0               0       _null_ _null_ ));
-DATA(insert ( 2130     n 0 numeric_larger      -                               numeric_larger          -                               -                               -                               f f 1756        1700    0       0               0       _null_ _null_ ));
-DATA(insert ( 2050     n 0 array_larger        -                               array_larger            -                               -                               -                               f f 1073        2277    0       0               0       _null_ _null_ ));
-DATA(insert ( 2244     n 0 bpchar_larger       -                               bpchar_larger           -                               -                               -                               f f 1060        1042    0       0               0       _null_ _null_ ));
-DATA(insert ( 2797     n 0 tidlarger           -                               tidlarger                       -                               -                               -                               f f 2800        27              0       0               0       _null_ _null_ ));
-DATA(insert ( 3526     n 0 enum_larger         -                               enum_larger                     -                               -                               -                               f f 3519        3500    0       0               0       _null_ _null_ ));
-DATA(insert ( 3564     n 0 network_larger      -                               network_larger          -                               -                               -                               f f 1205        869             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               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               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               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               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               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               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               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               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               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               0       _null_ _null_ ));
+DATA(insert ( 3564     n 0 network_larger      -                               network_larger          -       -       -                               -                               -                               f f 1205        869             0       0       0               0       _null_ _null_ ));
 
 /* min */
-DATA(insert ( 2131     n 0 int8smaller         -                               int8smaller                     -                               -                               -                               f f 412         20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2132     n 0 int4smaller         -                               int4smaller                     -                               -                               -                               f f 97          23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2133     n 0 int2smaller         -                               int2smaller                     -                               -                               -                               f f 95          21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2134     n 0 oidsmaller          -                               oidsmaller                      -                               -                               -                               f f 609         26              0       0               0       _null_ _null_ ));
-DATA(insert ( 2135     n 0 float4smaller       -                               float4smaller           -                               -                               -                               f f 622         700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2136     n 0 float8smaller       -                               float8smaller           -                               -                               -                               f f 672         701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2137     n 0 int4smaller         -                               int4smaller                     -                               -                               -                               f f 562         702             0       0               0       _null_ _null_ ));
-DATA(insert ( 2138     n 0 date_smaller        -                               date_smaller            -                               -                               -                               f f 1095        1082    0       0               0       _null_ _null_ ));
-DATA(insert ( 2139     n 0 time_smaller        -                               time_smaller            -                               -                               -                               f f 1110        1083    0       0               0       _null_ _null_ ));
-DATA(insert ( 2140     n 0 timetz_smaller      -                               timetz_smaller          -                               -                               -                               f f 1552        1266    0       0               0       _null_ _null_ ));
-DATA(insert ( 2141     n 0 cashsmaller         -                               cashsmaller                     -                               -                               -                               f f 902         790             0       0               0       _null_ _null_ ));
-DATA(insert ( 2142     n 0 timestamp_smaller   -                       timestamp_smaller       -                               -                               -                               f f 2062        1114    0       0               0       _null_ _null_ ));
-DATA(insert ( 2143     n 0 timestamptz_smaller -                       timestamptz_smaller     -                               -                               -                               f f 1322        1184    0       0               0       _null_ _null_ ));
-DATA(insert ( 2144     n 0 interval_smaller    -                       interval_smaller        -                               -                               -                               f f 1332        1186    0       0               0       _null_ _null_ ));
-DATA(insert ( 2145     n 0 text_smaller        -                               text_smaller            -                               -                               -                               f f 664         25              0       0               0       _null_ _null_ ));
-DATA(insert ( 2146     n 0 numeric_smaller -                           numeric_smaller         -                               -                               -                               f f 1754        1700    0       0               0       _null_ _null_ ));
-DATA(insert ( 2051     n 0 array_smaller       -                               array_smaller           -                               -                               -                               f f 1072        2277    0       0               0       _null_ _null_ ));
-DATA(insert ( 2245     n 0 bpchar_smaller      -                               bpchar_smaller          -                               -                               -                               f f 1058        1042    0       0               0       _null_ _null_ ));
-DATA(insert ( 2798     n 0 tidsmaller          -                               tidsmaller                      -                               -                               -                               f f 2799        27              0       0               0       _null_ _null_ ));
-DATA(insert ( 3527     n 0 enum_smaller        -                               enum_smaller            -                               -                               -                               f f 3518        3500    0       0               0       _null_ _null_ ));
-DATA(insert ( 3565     n 0 network_smaller -                           network_smaller         -                               -                               -                               f f 1203        869             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               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               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               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               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               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               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               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               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               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               0       _null_ _null_ ));
+DATA(insert ( 3565     n 0 network_smaller -                           network_smaller         -       -       -                               -                               -                               f f 1203        869             0       0       0               0       _null_ _null_ ));
 
 /* count */
-DATA(insert ( 2147     n 0 int8inc_any         -                               int8pl  int8inc_any             int8dec_any             -                               f f 0           20              0       20              0       "0" "0" ));
-DATA(insert ( 2803     n 0 int8inc                     -                               int8pl  int8inc                 int8dec                 -                               f f 0           20              0       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       0       20              0       "0" "0" ));
 
 /* 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 ( 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 ( 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 ( 2721     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* 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 ( 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 ( 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 ( 2644     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* 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 ( 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 ( 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 ( 2151     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* 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 ( 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 ( 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 ( 2727     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* 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 ( 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 ( 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 ( 2715     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* 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 ( 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 ( 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 ( 2157     n 0 float4_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}" _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 ( 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    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    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,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    0       128 2281        128 _null_ _null_ ));
 
 /* SQL2003 binary regression aggregates */
-DATA(insert ( 2818     n 0 int8inc_float8_float8       -                                       -       -                               -                               -                       f f 0   20              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 ( 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 ( 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 ( 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 ( 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 ( 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 ( 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 ( 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 ( 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 ( 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 ( 2829     n 0 float8_regr_accum   float8_corr                             -       -                               -                               -                       f f 0   1022    0       0               0       "{0,0,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,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,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,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,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,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,0}" _null_ ));
 
 /* 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 ( 2518     n 0 boolor_statefunc    -       -       bool_accum      bool_accum_inv  bool_anytrue    f f 59  16              0       2281    16      _null_ _null_ ));
-DATA(insert ( 2519     n 0 booland_statefunc   -       -       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               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 */
-DATA(insert ( 2236     n 0 int2and             -                               int2and -                               -                               -                               f f 0   21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2237     n 0 int2or              -                               int2or  -                               -                               -                               f f 0   21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2238     n 0 int4and             -                               int4and -                               -                               -                               f f 0   23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2239     n 0 int4or              -                               int4or  -                               -                               -                               f f 0   23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2240     n 0 int8and             -                               int8and -                               -                               -                               f f 0   20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2241     n 0 int8or              -                               int8or  -                               -                               -                               f f 0   20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2242     n 0 bitand              -                               bitand  -                               -                               -                               f f 0   1560    0       0               0       _null_ _null_ ));
-DATA(insert ( 2243     n 0 bitor               -                               bitor   -                               -                               -                               f f 0   1560    0       0               0       _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               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               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               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               0       _null_ _null_ ));
 
 /* 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 */
-DATA(insert ( 2335     n 0 array_agg_transfn           array_agg_finalfn               -       -               -                               -                               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 4053     n 0 array_agg_array_transfn array_agg_array_finalfn     -       -               -                               -                               t f 0   2281    0       0               0       _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               0       _null_ _null_ ));
 
 /* 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 */
-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 */
-DATA(insert ( 3175     n 0 json_agg_transfn    json_agg_finalfn                        -       -                               -                               -                               f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3197     n 0 json_object_agg_transfn json_object_agg_finalfn -   -                               -                               -                               f f 0   2281    0       0               0       _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               0       _null_ _null_ ));
 
 /* jsonb */
-DATA(insert ( 3267     n 0 jsonb_agg_transfn   jsonb_agg_finalfn                               -       -                               -                               -                       f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3270     n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn   -       -                               -                               -                       f f 0   2281    0       0               0       _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               0       _null_ _null_ ));
 
 /* 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 ( 3974     o 1 ordered_set_transition                      percentile_cont_float8_final                    -       -               -               -               f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3976     o 1 ordered_set_transition                      percentile_cont_interval_final                  -       -               -               -               f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3978     o 1 ordered_set_transition                      percentile_disc_multi_final                             -       -               -               -               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3980     o 1 ordered_set_transition                      percentile_cont_float8_multi_final              -       -               -               -               f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3982     o 1 ordered_set_transition                      percentile_cont_interval_multi_final    -       -               -               -               f f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3984     o 0 ordered_set_transition                      mode_final                                                              -       -               -               -               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3986     h 1 ordered_set_transition_multi        rank_final                                                              -       -               -               -               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3988     h 1 ordered_set_transition_multi        percent_rank_final                                              -       -               -               -               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3990     h 1 ordered_set_transition_multi        cume_dist_final                                                 -       -               -               -               t f 0   2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3992     h 1 ordered_set_transition_multi        dense_rank_final                                                -       -               -               -               t f 0   2281    0       0               0       _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               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               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               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               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               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,
                                List *aggtransfnName,
                                List *aggfinalfnName,
                                List *aggcombinefnName,
+                               List *aggserialfnName,
+                               List *aggdeserialfnName,
                                List *aggmtransfnName,
                                List *aggminvtransfnName,
                                List *aggmfinalfnName,
@@ -333,6 +344,7 @@ extern ObjectAddress AggregateCreate(const char *aggName,
                                bool mfinalfnExtraArgs,
                                List *aggsortopName,
                                Oid aggTransType,
+                               Oid aggSerialType,
                                int32 aggTransSpace,
                                Oid aggmTransType,
                                int32 aggmTransSpace,
index bf2a09bc39c8085359fb140556324055b23e98af..dbec07e5a375cbf235feddf5dc6c8120f23bb53f 100644 (file)
@@ -1836,6 +1836,7 @@ typedef struct AggState
        bool            agg_done;               /* indicates completion of Agg scan */
        bool            combineStates;  /* input tuples contain transition 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                     current_set;    /* The current grouping set being evaluated */
        Bitmapset  *grouped_cols;       /* grouped cols in current projection */
index 465d72fe890d697378ec4df121d74741f4ba2b6a..ea8554f275cc362b68e33ee4e47c7a47c947d9c9 100644 (file)
@@ -712,6 +712,7 @@ typedef struct Agg
        AggStrategy aggstrategy;        /* basic strategy, see nodes.h */
        bool            combineStates;  /* input tuples contain transition 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 */
        AttrNumber *grpColIdx;          /* their indexes in the target list */
        Oid                *grpOperators;       /* equality operators to compare with */
index 32f04b25dde08699ac257cc3c749d31cd2d87816..641446ca7123a693228432882abc22d313faa391 100644 (file)
@@ -1296,6 +1296,7 @@ typedef struct AggPath
        List       *qual;                       /* quals (HAVING quals), if any */
        bool            combineStates;  /* input is partially aggregated agg states */
        bool            finalizeAggs;   /* should the executor call the finalfn? */
+       bool            serialStates;   /* should agg states be (de)serialized? */
 } AggPath;
 
 /*
index 1744ff058e8999ab0f6c1a02e33db500c7fc82f5..acc827de488f7567fa368cdd7f6ec7dbd2241fb8 100644 (file)
@@ -171,7 +171,8 @@ extern AggPath *create_agg_path(PlannerInfo *root,
                                const AggClauseCosts *aggcosts,
                                double numGroups,
                                bool combineStates,
-                               bool finalizeAggs);
+                               bool finalizeAggs,
+                               bool serialStates);
 extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root,
                                                 RelOptInfo *rel,
                                                 Path *subpath,
index 596ffb3d175246099eb841fcd0d2ce70aba99347..1f96e27034c7d4d898ca3a64650d6be536e9cea9 100644 (file)
@@ -58,7 +58,7 @@ extern bool is_projection_capable_plan(Plan *plan);
 /* External use of these functions is deprecated: */
 extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree);
 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,
                 List *groupingSets, List *chain,
                 double dNumGroups, Plan *lefttree);
index 699b61c528e4b6bf12ae72d330314b2b2045c6ae..23ce8d6ce3538db4a89f6fb01dd5f074dd70eda6 100644 (file)
@@ -51,6 +51,12 @@ extern void build_aggregate_combinefn_expr(Oid agg_state_type,
                                                                                   Oid combinefn_oid,
                                                                                   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,
                                                int num_finalfn_inputs,
                                                Oid agg_state_type,