Re: [HACKERS] Aggregate transition state merging vs. hypothetical set functions

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: [HACKERS] Aggregate transition state merging vs. hypothetical set functions
Дата
Msg-id 7410.1507935678@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: [HACKERS] Aggregate transition state merging vs. hypothetical set functions  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: [HACKERS] Aggregate transition state merging vs. hypothetical setfunctions  (Peter Eisentraut <peter.eisentraut@2ndquadrant.com>)
Список pgsql-hackers
I wrote:
> Moving on to the exact color of the bikeshed: it seems like the right
> way to present this to users of CREATE AGGREGATE is in terms of "does
> the final function modify the transition state?".  So maybe the values
> could be spelled
> SMODIFY = READ_ONLY   ffunc never touches state, ok as window agg
> SMODIFY = SHARABLE    ffunc does some one-time change like sorting,
>                       so state merging is OK but not window agg
> SMODIFY = READ_WRITE  ffunc trashes state, can't do merging either
> I'm not set on these names by any means; anyone have a better idea?

After contemplating the existing CREATE AGGREGATE parameters, particularly
[M]FINALFUNC_EXTRA, it seemed to me that better nomenclature is

[M]FINALFUNC_MODIFY = READ_ONLY
[M]FINALFUNC_MODIFY = STOP_UPDATES
[M]FINALFUNC_MODIFY = READ_WRITE

where "stop updates" is intended to imply "you can't call the transfn
anymore after the first finalfn call".  I'm still not that much in
love with that terminology, but don't have a better idea now.

Attached is a WIP patch; I believe it's code-complete but the SGML
docs are lacking.  Barring objections I'll finish up the docs and
push this.

            regards, tom lane

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 9af77c1..cfec246 100644
*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 487,492 ****
--- 487,512 ----
        <entry>True to pass extra dummy arguments to <structfield>aggmfinalfn</structfield></entry>
       </row>
       <row>
+       <entry><structfield>aggfinalmodify</structfield></entry>
+       <entry><type>char</type></entry>
+       <entry></entry>
+       <entry>Whether <structfield>aggfinalfn</structfield> modifies the
+        transition state value:
+        <literal>r</literal> if it is read-only,
+        <literal>s</literal> if the <structfield>aggtransfn</structfield>
+        cannot be applied after the <structfield>aggfinalfn</structfield>, or
+        <literal>w</literal> if it writes on the value
+       </entry>
+      </row>
+      <row>
+       <entry><structfield>aggmfinalmodify</structfield></entry>
+       <entry><type>char</type></entry>
+       <entry></entry>
+       <entry>Like <structfield>aggfinalmodify</structfield>, but for
+        the <structfield>aggmfinalfn</structfield>
+       </entry>
+      </row>
+      <row>
        <entry><structfield>aggsortop</structfield></entry>
        <entry><type>oid</type></entry>
        <entry><literal><link
linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index a920450..ca3fd81 100644
*** a/src/backend/catalog/pg_aggregate.c
--- b/src/backend/catalog/pg_aggregate.c
***************
*** 19,24 ****
--- 19,25 ----
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/pg_aggregate.h"
+ #include "catalog/pg_aggregate_fn.h"
  #include "catalog/pg_language.h"
  #include "catalog/pg_operator.h"
  #include "catalog/pg_proc.h"
*************** AggregateCreate(const char *aggName,
*** 65,70 ****
--- 66,73 ----
                  List *aggmfinalfnName,
                  bool finalfnExtraArgs,
                  bool mfinalfnExtraArgs,
+                 char finalfnModify,
+                 char mfinalfnModify,
                  List *aggsortopName,
                  Oid aggTransType,
                  int32 aggTransSpace,
*************** AggregateCreate(const char *aggName,
*** 656,661 ****
--- 659,666 ----
      values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
      values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
      values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
+     values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
+     values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
      values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
      values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
      values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index a63539a..07ef4c5 100644
*** a/src/backend/commands/aggregatecmds.c
--- b/src/backend/commands/aggregatecmds.c
***************
*** 26,31 ****
--- 26,32 ----
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/pg_aggregate.h"
+ #include "catalog/pg_aggregate_fn.h"
  #include "catalog/pg_proc.h"
  #include "catalog/pg_type.h"
  #include "commands/alter.h"
***************
*** 39,44 ****
--- 40,48 ----
  #include "utils/syscache.h"


+ static char extractModify(DefElem *defel);
+
+
  /*
   *    DefineAggregate
   *
*************** DefineAggregate(ParseState *pstate, List
*** 67,72 ****
--- 71,78 ----
      List       *mfinalfuncName = NIL;
      bool        finalfuncExtraArgs = false;
      bool        mfinalfuncExtraArgs = false;
+     char        finalfuncModify = 0;
+     char        mfinalfuncModify = 0;
      List       *sortoperatorName = NIL;
      TypeName   *baseType = NULL;
      TypeName   *transType = NULL;
*************** DefineAggregate(ParseState *pstate, List
*** 143,148 ****
--- 149,158 ----
              finalfuncExtraArgs = defGetBoolean(defel);
          else if (pg_strcasecmp(defel->defname, "mfinalfunc_extra") == 0)
              mfinalfuncExtraArgs = defGetBoolean(defel);
+         else if (pg_strcasecmp(defel->defname, "finalfunc_modify") == 0)
+             finalfuncModify = extractModify(defel);
+         else if (pg_strcasecmp(defel->defname, "mfinalfunc_modify") == 0)
+             mfinalfuncModify = extractModify(defel);
          else if (pg_strcasecmp(defel->defname, "sortop") == 0)
              sortoperatorName = defGetQualifiedName(defel);
          else if (pg_strcasecmp(defel->defname, "basetype") == 0)
*************** DefineAggregate(ParseState *pstate, List
*** 236,241 ****
--- 246,260 ----
      }

      /*
+      * Default values for modify flags can only be determined once we know the
+      * aggKind.
+      */
+     if (finalfuncModify == 0)
+         finalfuncModify = (aggKind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
+     if (mfinalfuncModify == 0)
+         mfinalfuncModify = (aggKind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
+
+     /*
       * look up the aggregate's input datatype(s).
       */
      if (oldstyle)
*************** DefineAggregate(ParseState *pstate, List
*** 437,442 ****
--- 456,463 ----
                             mfinalfuncName,    /* final function name */
                             finalfuncExtraArgs,
                             mfinalfuncExtraArgs,
+                            finalfuncModify,
+                            mfinalfuncModify,
                             sortoperatorName,    /* sort operator name */
                             transTypeId, /* transition data type */
                             transSpace,    /* transition space */
*************** DefineAggregate(ParseState *pstate, List
*** 446,448 ****
--- 467,490 ----
                             minitval,    /* initial condition */
                             proparallel);    /* parallel safe? */
  }
+
+ /*
+  * Convert the string form of [m]finalfunc_modify to the catalog representation
+  */
+ static char
+ extractModify(DefElem *defel)
+ {
+     char       *val = defGetString(defel);
+
+     if (strcmp(val, "read_only") == 0)
+         return AGGMODIFY_READ_ONLY;
+     if (strcmp(val, "stop_updates") == 0)
+         return AGGMODIFY_STOP_UPDATES;
+     if (strcmp(val, "read_write") == 0)
+         return AGGMODIFY_READ_WRITE;
+     ereport(ERROR,
+             (errcode(ERRCODE_SYNTAX_ERROR),
+              errmsg("parameter \"%s\" must be READ_ONLY, STOP_UPDATES, or READ_WRITE",
+                     defel->defname)));
+     return 0;                    /* keep compiler quiet */
+ }
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 6543ece..36c6ecb 100644
*** a/src/backend/executor/nodeAgg.c
--- b/src/backend/executor/nodeAgg.c
*************** typedef struct AggStatePerTransData
*** 248,256 ****
      /*
       * Link to an Aggref expr this state value is for.
       *
!      * There can be multiple Aggref's sharing the same state value, as long as
!      * the inputs and transition function are identical. This points to the
!      * first one of them.
       */
      Aggref       *aggref;

--- 248,256 ----
      /*
       * Link to an Aggref expr this state value is for.
       *
!      * There can be multiple Aggref's sharing the same state value, so long as
!      * the inputs and transition functions are identical and the final
!      * functions are not read-write.  This points to the first one of them.
       */
      Aggref       *aggref;

*************** typedef struct AggStatePerAggData
*** 419,426 ****
      Oid            finalfn_oid;

      /*
!      * fmgr lookup data for final function --- only valid when finalfn_oid oid
!      * is not InvalidOid.
       */
      FmgrInfo    finalfn;

--- 419,426 ----
      Oid            finalfn_oid;

      /*
!      * fmgr lookup data for final function --- only valid when finalfn_oid is
!      * not InvalidOid.
       */
      FmgrInfo    finalfn;

*************** typedef struct AggStatePerAggData
*** 439,444 ****
--- 439,449 ----
      int16        resulttypeLen;
      bool        resulttypeByVal;

+     /*
+      * "sharable" is false if this agg cannot share state values with other
+      * aggregates because the final function is read-write.
+      */
+     bool        sharable;
  }            AggStatePerAggData;

  /*
*************** static void build_pertrans_for_aggref(Ag
*** 572,577 ****
--- 577,583 ----
  static int find_compatible_peragg(Aggref *newagg, AggState *aggstate,
                         int lastaggno, List **same_input_transnos);
  static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
+                          bool sharable,
                           Oid aggtransfn, Oid aggtranstype,
                           Oid aggserialfn, Oid aggdeserialfn,
                           Datum initValue, bool initValueIsNull,
*************** ExecInitAgg(Agg *node, EState *estate, i
*** 3105,3110 ****
--- 3111,3117 ----
          AclResult    aclresult;
          Oid            transfn_oid,
                      finalfn_oid;
+         bool        sharable;
          Oid            serialfn_oid,
                      deserialfn_oid;
          Expr       *finalfnexpr;
*************** ExecInitAgg(Agg *node, EState *estate, i
*** 3177,3182 ****
--- 3184,3198 ----
          else
              peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;

+         /*
+          * If finalfn is marked read-write, we can't share transition states;
+          * but it is okay to share for AGGMODIFY_STOP_UPDATES aggs.  Also, if
+          * we're not executing the finalfn here, we can share regardless.
+          */
+         sharable = (aggform->aggfinalmodify != AGGMODIFY_READ_WRITE) ||
+             (finalfn_oid == InvalidOid);
+         peragg->sharable = sharable;
+
          serialfn_oid = InvalidOid;
          deserialfn_oid = InvalidOid;

*************** ExecInitAgg(Agg *node, EState *estate, i
*** 3315,3325 ****
           * 2. Build working state for invoking the transition function, or
           * look up previously initialized working state, if we can share it.
           *
!          * find_compatible_peragg() already collected a list of per-Trans's
!          * with the same inputs. Check if any of them have the same transition
!          * function and initial value.
           */
          existing_transno = find_compatible_pertrans(aggstate, aggref,
                                                      transfn_oid, aggtranstype,
                                                      serialfn_oid, deserialfn_oid,
                                                      initValue, initValueIsNull,
--- 3331,3342 ----
           * 2. Build working state for invoking the transition function, or
           * look up previously initialized working state, if we can share it.
           *
!          * find_compatible_peragg() already collected a list of sharable
!          * per-Trans's with the same inputs. Check if any of them have the
!          * same transition function and initial value.
           */
          existing_transno = find_compatible_pertrans(aggstate, aggref,
+                                                     sharable,
                                                      transfn_oid, aggtranstype,
                                                      serialfn_oid, deserialfn_oid,
                                                      initValue, initValueIsNull,
*************** GetAggInitVal(Datum textInitVal, Oid tra
*** 3724,3733 ****
   * with this one, with the same input parameters. If no compatible aggregate
   * can be found, returns -1.
   *
!  * As a side-effect, this also collects a list of existing per-Trans structs
!  * with matching inputs. If no identical Aggref is found, the list is passed
!  * later to find_compatible_pertrans, to see if we can at least reuse the
!  * state value of another aggregate.
   */
  static int
  find_compatible_peragg(Aggref *newagg, AggState *aggstate,
--- 3741,3750 ----
   * with this one, with the same input parameters. If no compatible aggregate
   * can be found, returns -1.
   *
!  * As a side-effect, this also collects a list of existing, sharable per-Trans
!  * structs with matching inputs. If no identical Aggref is found, the list is
!  * passed later to find_compatible_pertrans, to see if we can at least reuse
!  * the state value of another aggregate.
   */
  static int
  find_compatible_peragg(Aggref *newagg, AggState *aggstate,
*************** find_compatible_peragg(Aggref *newagg, A
*** 3785,3795 ****
          }

          /*
!          * Not identical, but it had the same inputs. Return it to the caller,
!          * in case we can re-use its per-trans state.
           */
!         *same_input_transnos = lappend_int(*same_input_transnos,
!                                            peragg->transno);
      }

      return -1;
--- 3802,3816 ----
          }

          /*
!          * Not identical, but it had the same inputs.  If the final function
!          * permits sharing, return its transno to the caller, in case we can
!          * re-use its per-trans state.  (If there's already sharing going on,
!          * we can report a transno more than once.  find_compatible_pertrans
!          * is cheap enough that it's not worth working hard to avoid that.)
           */
!         if (peragg->sharable)
!             *same_input_transnos = lappend_int(*same_input_transnos,
!                                                peragg->transno);
      }

      return -1;
*************** find_compatible_peragg(Aggref *newagg, A
*** 3804,3810 ****
   * verified to match.)
   */
  static int
! find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
                           Oid aggtransfn, Oid aggtranstype,
                           Oid aggserialfn, Oid aggdeserialfn,
                           Datum initValue, bool initValueIsNull,
--- 3825,3831 ----
   * verified to match.)
   */
  static int
! find_compatible_pertrans(AggState *aggstate, Aggref *newagg, bool sharable,
                           Oid aggtransfn, Oid aggtranstype,
                           Oid aggserialfn, Oid aggdeserialfn,
                           Datum initValue, bool initValueIsNull,
*************** find_compatible_pertrans(AggState *aggst
*** 3812,3825 ****
  {
      ListCell   *lc;

!     /*
!      * For the moment, never try to share transition states between different
!      * ordered-set aggregates.  This is necessary because the finalfns of the
!      * built-in OSAs (see orderedsetaggs.c) are destructive of their
!      * transition states.  We should fix them so we can allow this, but not
!      * losing performance in the normal non-shared case will take some work.
!      */
!     if (AGGKIND_IS_ORDERED_SET(newagg->aggkind))
          return -1;

      foreach(lc, transnos)
--- 3833,3840 ----
  {
      ListCell   *lc;

!     /* If this aggregate can't share transition states, give up */
!     if (!sharable)
          return -1;

      foreach(lc, transnos)
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 80be460..35174fe 100644
*** a/src/backend/executor/nodeWindowAgg.c
--- b/src/backend/executor/nodeWindowAgg.c
***************
*** 49,54 ****
--- 49,55 ----
  #include "utils/datum.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
+ #include "utils/regproc.h"
  #include "utils/syscache.h"
  #include "windowapi.h"

*************** initialize_peragg(WindowAggState *winsta
*** 2100,2105 ****
--- 2101,2107 ----
                  invtransfn_oid,
                  finalfn_oid;
      bool        finalextra;
+     char        finalmodify;
      Expr       *transfnexpr,
                 *invtransfnexpr,
                 *finalfnexpr;
*************** initialize_peragg(WindowAggState *winsta
*** 2139,2144 ****
--- 2141,2147 ----
          peraggstate->invtransfn_oid = invtransfn_oid = aggform->aggminvtransfn;
          peraggstate->finalfn_oid = finalfn_oid = aggform->aggmfinalfn;
          finalextra = aggform->aggmfinalextra;
+         finalmodify = aggform->aggmfinalmodify;
          aggtranstype = aggform->aggmtranstype;
          initvalAttNo = Anum_pg_aggregate_aggminitval;
      }
*************** initialize_peragg(WindowAggState *winsta
*** 2148,2153 ****
--- 2151,2157 ----
          peraggstate->invtransfn_oid = invtransfn_oid = InvalidOid;
          peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
          finalextra = aggform->aggfinalextra;
+         finalmodify = aggform->aggfinalmodify;
          aggtranstype = aggform->aggtranstype;
          initvalAttNo = Anum_pg_aggregate_agginitval;
      }
*************** initialize_peragg(WindowAggState *winsta
*** 2198,2203 ****
--- 2202,2218 ----
          }
      }

+     /*
+      * If the selected finalfn isn't read-only, we can't run this aggregate as
+      * a window function.  This is a user-facing error, so we take a bit more
+      * care with the error message than elsewhere in this function.
+      */
+     if (finalmodify != AGGMODIFY_READ_ONLY)
+         ereport(ERROR,
+                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                  errmsg("aggregate function %s does not support use as a window function",
+                         format_procedure(wfunc->winfnoid))));
+
      /* Detect how many arguments to pass to the finalfn */
      if (finalextra)
          peraggstate->numFinalArgs = numArguments + 1;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index e34c83a..898abd7 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "access/attnum.h"
  #include "access/sysattr.h"
  #include "access/transam.h"
+ #include "catalog/pg_aggregate.h"
  #include "catalog/pg_am.h"
  #include "catalog/pg_attribute.h"
  #include "catalog/pg_cast.h"
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13433,13440 ****
      int            i_aggmfinalfn;
      int            i_aggfinalextra;
      int            i_aggmfinalextra;
      int            i_aggsortop;
!     int            i_hypothetical;
      int            i_aggtranstype;
      int            i_aggtransspace;
      int            i_aggmtranstype;
--- 13434,13443 ----
      int            i_aggmfinalfn;
      int            i_aggfinalextra;
      int            i_aggmfinalextra;
+     int            i_aggfinalmodify;
+     int            i_aggmfinalmodify;
      int            i_aggsortop;
!     int            i_aggkind;
      int            i_aggtranstype;
      int            i_aggtransspace;
      int            i_aggmtranstype;
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13453,13461 ****
      const char *aggmfinalfn;
      bool        aggfinalextra;
      bool        aggmfinalextra;
      const char *aggsortop;
      char       *aggsortconvop;
!     bool        hypothetical;
      const char *aggtranstype;
      const char *aggtransspace;
      const char *aggmtranstype;
--- 13456,13466 ----
      const char *aggmfinalfn;
      bool        aggfinalextra;
      bool        aggmfinalextra;
+     char        aggfinalmodify;
+     char        aggmfinalmodify;
      const char *aggsortop;
      char       *aggsortconvop;
!     char        aggkind;
      const char *aggtranstype;
      const char *aggtransspace;
      const char *aggmtranstype;
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13464,13469 ****
--- 13469,13475 ----
      const char *aggminitval;
      bool        convertok;
      const char *proparallel;
+     char        defaultfinalmodify;

      /* Skip if not to be dumped */
      if (!agginfo->aggfn.dobj.dump || dopt->dataOnly)
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13479,13493 ****
      selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);

      /* Get aggregate-specific details */
!     if (fout->remoteVersion >= 90600)
      {
          appendPQExpBuffer(query, "SELECT aggtransfn, "
                            "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                            "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
                            "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                            "aggfinalextra, aggmfinalextra, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "(aggkind = 'h') AS hypothetical, "
                            "aggtransspace, agginitval, "
                            "aggmtransspace, aggminitval, "
                            "true AS convertok, "
--- 13485,13521 ----
      selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);

      /* Get aggregate-specific details */
!     if (fout->remoteVersion >= 110000)
      {
          appendPQExpBuffer(query, "SELECT aggtransfn, "
                            "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                            "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
                            "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                            "aggfinalextra, aggmfinalextra, "
+                           "aggfinalmodify, aggmfinalmodify, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "aggkind, "
!                           "aggtransspace, agginitval, "
!                           "aggmtransspace, aggminitval, "
!                           "true AS convertok, "
!                           "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
!                           "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs, "
!                           "p.proparallel "
!                           "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
!                           "WHERE a.aggfnoid = p.oid "
!                           "AND p.oid = '%u'::pg_catalog.oid",
!                           agginfo->aggfn.dobj.catId.oid);
!     }
!     else if (fout->remoteVersion >= 90600)
!     {
!         appendPQExpBuffer(query, "SELECT aggtransfn, "
!                           "aggfinalfn, aggtranstype::pg_catalog.regtype, "
!                           "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
!                           "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
!                           "aggfinalextra, aggmfinalextra, "
!                           "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
!                           "aggsortop::pg_catalog.regoperator, "
!                           "aggkind, "
                            "aggtransspace, agginitval, "
                            "aggmtransspace, aggminitval, "
                            "true AS convertok, "
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13507,13514 ****
                            "'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, "
                            "aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                            "aggfinalextra, aggmfinalextra, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "(aggkind = 'h') AS hypothetical, "
                            "aggtransspace, agginitval, "
                            "aggmtransspace, aggminitval, "
                            "true AS convertok, "
--- 13535,13543 ----
                            "'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, "
                            "aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                            "aggfinalextra, aggmfinalextra, "
+                           "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "aggkind, "
                            "aggtransspace, agginitval, "
                            "aggmtransspace, aggminitval, "
                            "true AS convertok, "
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13528,13535 ****
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
                            "false AS aggmfinalextra, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "false AS hypothetical, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok, "
--- 13557,13565 ----
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
                            "false AS aggmfinalextra, "
+                           "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "'n' AS aggkind, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok, "
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13549,13556 ****
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
                            "false AS aggmfinalextra, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "false AS hypothetical, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok "
--- 13579,13587 ----
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
                            "false AS aggmfinalextra, "
+                           "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
                            "aggsortop::pg_catalog.regoperator, "
!                           "'n' AS aggkind, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok "
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13567,13574 ****
                            "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
!                           "false AS aggmfinalextra, 0 AS aggsortop, "
!                           "false AS hypothetical, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok "
--- 13598,13607 ----
                            "'-' AS aggdeserialfn, '-' AS aggmtransfn, "
                            "'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
                            "0 AS aggmtranstype, false AS aggfinalextra, "
!                           "false AS aggmfinalextra, "
!                           "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
!                           "0 AS aggsortop, "
!                           "'n' AS aggkind, "
                            "0 AS aggtransspace, agginitval, "
                            "0 AS aggmtransspace, NULL AS aggminitval, "
                            "true AS convertok "
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13590,13597 ****
      i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
      i_aggfinalextra = PQfnumber(res, "aggfinalextra");
      i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
      i_aggsortop = PQfnumber(res, "aggsortop");
!     i_hypothetical = PQfnumber(res, "hypothetical");
      i_aggtranstype = PQfnumber(res, "aggtranstype");
      i_aggtransspace = PQfnumber(res, "aggtransspace");
      i_aggmtranstype = PQfnumber(res, "aggmtranstype");
--- 13623,13632 ----
      i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
      i_aggfinalextra = PQfnumber(res, "aggfinalextra");
      i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
+     i_aggfinalmodify = PQfnumber(res, "aggfinalmodify");
+     i_aggmfinalmodify = PQfnumber(res, "aggmfinalmodify");
      i_aggsortop = PQfnumber(res, "aggsortop");
!     i_aggkind = PQfnumber(res, "aggkind");
      i_aggtranstype = PQfnumber(res, "aggtranstype");
      i_aggtransspace = PQfnumber(res, "aggtransspace");
      i_aggmtranstype = PQfnumber(res, "aggmtranstype");
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13611,13618 ****
      aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
      aggfinalextra = (PQgetvalue(res, 0, i_aggfinalextra)[0] == 't');
      aggmfinalextra = (PQgetvalue(res, 0, i_aggmfinalextra)[0] == 't');
      aggsortop = PQgetvalue(res, 0, i_aggsortop);
!     hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't');
      aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
      aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
      aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
--- 13646,13655 ----
      aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
      aggfinalextra = (PQgetvalue(res, 0, i_aggfinalextra)[0] == 't');
      aggmfinalextra = (PQgetvalue(res, 0, i_aggmfinalextra)[0] == 't');
+     aggfinalmodify = PQgetvalue(res, 0, i_aggfinalmodify)[0];
+     aggmfinalmodify = PQgetvalue(res, 0, i_aggmfinalmodify)[0];
      aggsortop = PQgetvalue(res, 0, i_aggsortop);
!     aggkind = PQgetvalue(res, 0, i_aggkind)[0];
      aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
      aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
      aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13656,13661 ****
--- 13693,13706 ----
          return;
      }

+     /* identify default modify flag for aggkind (must match DefineAggregate) */
+     defaultfinalmodify = (aggkind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
+     /* replace omitted flags for old versions */
+     if (aggfinalmodify == '0')
+         aggfinalmodify = defaultfinalmodify;
+     if (aggmfinalmodify == '0')
+         aggmfinalmodify = defaultfinalmodify;
+
      /* regproc and regtype output is already sufficiently quoted */
      appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
                        aggtransfn, aggtranstype);
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13678,13683 ****
--- 13723,13747 ----
                            aggfinalfn);
          if (aggfinalextra)
              appendPQExpBufferStr(details, ",\n    FINALFUNC_EXTRA");
+         if (aggfinalmodify != defaultfinalmodify)
+         {
+             switch (aggfinalmodify)
+             {
+                 case AGGMODIFY_READ_ONLY:
+                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_ONLY");
+                     break;
+                 case AGGMODIFY_STOP_UPDATES:
+                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = STOP_UPDATES");
+                     break;
+                 case AGGMODIFY_READ_WRITE:
+                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_WRITE");
+                     break;
+                 default:
+                     exit_horribly(NULL, "unrecognized aggfinalmodify value for aggregate \"%s\"\n",
+                                   agginfo->aggfn.dobj.name);
+                     break;
+             }
+         }
      }

      if (strcmp(aggcombinefn, "-") != 0)
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13715,13720 ****
--- 13779,13803 ----
                            aggmfinalfn);
          if (aggmfinalextra)
              appendPQExpBufferStr(details, ",\n    MFINALFUNC_EXTRA");
+         if (aggmfinalmodify != defaultfinalmodify)
+         {
+             switch (aggmfinalmodify)
+             {
+                 case AGGMODIFY_READ_ONLY:
+                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_ONLY");
+                     break;
+                 case AGGMODIFY_STOP_UPDATES:
+                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = STOP_UPDATES");
+                     break;
+                 case AGGMODIFY_READ_WRITE:
+                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_WRITE");
+                     break;
+                 default:
+                     exit_horribly(NULL, "unrecognized aggmfinalmodify value for aggregate \"%s\"\n",
+                                   agginfo->aggfn.dobj.name);
+                     break;
+             }
+         }
      }

      aggsortconvop = convertOperatorReference(fout, aggsortop);
*************** dumpAgg(Archive *fout, AggInfo *agginfo)
*** 13725,13731 ****
          free(aggsortconvop);
      }

!     if (hypothetical)
          appendPQExpBufferStr(details, ",\n    HYPOTHETICAL");

      if (proparallel != NULL && proparallel[0] != PROPARALLEL_UNSAFE)
--- 13808,13814 ----
          free(aggsortconvop);
      }

!     if (aggkind == AGGKIND_HYPOTHETICAL)
          appendPQExpBufferStr(details, ",\n    HYPOTHETICAL");

      if (proparallel != NULL && proparallel[0] != PROPARALLEL_UNSAFE)
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index c492fbd..df87fb5 100644
*** a/src/bin/pg_dump/t/002_pg_dump.pl
--- b/src/bin/pg_dump/t/002_pg_dump.pl
*************** qr/CREATE CAST \(timestamp with time zon
*** 2784,2789 ****
--- 2784,2790 ----
                            basetype = int4,
                            stype = _int8,
                            finalfunc = int8_avg,
+                           finalfunc_modify = stop_updates,
                            initcond1 = \'{0,0}\'
                         );',
          regexp => qr/^
*************** qr/CREATE CAST \(timestamp with time zon
*** 2791,2797 ****
              \n\s+\QSFUNC = int4_avg_accum,\E
              \n\s+\QSTYPE = bigint[],\E
              \n\s+\QINITCOND = '{0,0}',\E
!             \n\s+\QFINALFUNC = int8_avg\E
              \n\);/xm,
          like => {
              binary_upgrade          => 1,
--- 2792,2799 ----
              \n\s+\QSFUNC = int4_avg_accum,\E
              \n\s+\QSTYPE = bigint[],\E
              \n\s+\QINITCOND = '{0,0}',\E
!             \n\s+\QFINALFUNC = int8_avg,\E
!             \n\s+\QFINALFUNC_MODIFY = STOP_UPDATES\E
              \n\);/xm,
          like => {
              binary_upgrade          => 1,
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 4d5b9bb..5fd68d3 100644
*** a/src/include/catalog/pg_aggregate.h
--- b/src/include/catalog/pg_aggregate.h
***************
*** 20,27 ****
  #define PG_AGGREGATE_H

  #include "catalog/genbki.h"
- #include "catalog/objectaddress.h"
- #include "nodes/pg_list.h"

  /* ----------------------------------------------------------------
   *        pg_aggregate definition.
--- 20,25 ----
***************
*** 41,46 ****
--- 39,46 ----
   *    aggmfinalfn            final function for moving-aggregate mode (0 if none)
   *    aggfinalextra        true to pass extra dummy arguments to aggfinalfn
   *    aggmfinalextra        true to pass extra dummy arguments to aggmfinalfn
+  *    aggfinalmodify        tells whether aggfinalfn modifies transition state
+  *    aggmfinalmodify        tells whether aggmfinalfn modifies transition state
   *    aggsortop            associated sort operator (0 if none)
   *    aggtranstype        type of aggregate's transition (state) data
   *    aggtransspace        estimated size of state data (0 for default estimate)
*************** CATALOG(pg_aggregate,2600) BKI_WITHOUT_O
*** 67,72 ****
--- 67,74 ----
      regproc        aggmfinalfn;
      bool        aggfinalextra;
      bool        aggmfinalextra;
+     char        aggfinalmodify;
+     char        aggmfinalmodify;
      Oid            aggsortop;
      Oid            aggtranstype;
      int32        aggtransspace;
*************** typedef FormData_pg_aggregate *Form_pg_a
*** 91,97 ****
   * ----------------
   */

! #define Natts_pg_aggregate                    20
  #define Anum_pg_aggregate_aggfnoid            1
  #define Anum_pg_aggregate_aggkind            2
  #define Anum_pg_aggregate_aggnumdirectargs    3
--- 93,99 ----
   * ----------------
   */

! #define Natts_pg_aggregate                    22
  #define Anum_pg_aggregate_aggfnoid            1
  #define Anum_pg_aggregate_aggkind            2
  #define Anum_pg_aggregate_aggnumdirectargs    3
*************** typedef FormData_pg_aggregate *Form_pg_a
*** 105,117 ****
  #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_aggtransspace        16
! #define Anum_pg_aggregate_aggmtranstype        17
! #define Anum_pg_aggregate_aggmtransspace    18
! #define Anum_pg_aggregate_agginitval        19
! #define Anum_pg_aggregate_aggminitval        20

  /*
   * Symbolic values for aggkind column.  We distinguish normal aggregates
--- 107,121 ----
  #define Anum_pg_aggregate_aggmfinalfn        11
  #define Anum_pg_aggregate_aggfinalextra        12
  #define Anum_pg_aggregate_aggmfinalextra    13
! #define Anum_pg_aggregate_aggfinalmodify    14
! #define Anum_pg_aggregate_aggmfinalmodify    15
! #define Anum_pg_aggregate_aggsortop            16
! #define Anum_pg_aggregate_aggtranstype        17
! #define Anum_pg_aggregate_aggtransspace        18
! #define Anum_pg_aggregate_aggmtranstype        19
! #define Anum_pg_aggregate_aggmtransspace    20
! #define Anum_pg_aggregate_agginitval        21
! #define Anum_pg_aggregate_aggminitval        22

  /*
   * Symbolic values for aggkind column.  We distinguish normal aggregates
*************** typedef FormData_pg_aggregate *Form_pg_a
*** 128,133 ****
--- 132,149 ----
  /* Use this macro to test for "ordered-set agg including hypothetical case" */
  #define AGGKIND_IS_ORDERED_SET(kind)  ((kind) != AGGKIND_NORMAL)

+ /*
+  * Symbolic values for aggfinalmodify and aggmfinalmodify columns.
+  * Preferably, finalfns do not modify the transition state value at all,
+  * but in some cases that would cost too much performance.  We distinguish
+  * "pure read only" and "trashes it arbitrarily" cases, as well as the
+  * intermediate case where the finalfn can be applied multiple times but
+  * the transfn cannot be applied anymore after the first finalfn call.
+  */
+ #define AGGMODIFY_READ_ONLY            'r'
+ #define AGGMODIFY_STOP_UPDATES        's'
+ #define AGGMODIFY_READ_WRITE        'w'
+

  /* ----------------
   * initial contents of pg_aggregate
*************** typedef FormData_pg_aggregate *Form_pg_a
*** 135,351 ****
   */

  /* avg */
! DATA(insert ( 2100    n 0 int8_avg_accum        numeric_poly_avg    int8_avg_combine    int8_avg_serialize
int8_avg_deserialize   int8_avg_accum    int8_avg_accum_inv    numeric_poly_avg    f f 0    2281    48    2281    48
_null__null_ )); 
! DATA(insert ( 2101    n 0 int4_avg_accum        int8_avg            int4_avg_combine    -                        -
                   int4_avg_accum    int4_avg_accum_inv    int8_avg            f f 0    1016    0    1016    0
"{0,0}""{0,0}" )); 
! DATA(insert ( 2102    n 0 int2_avg_accum        int8_avg            int4_avg_combine    -                        -
                   int2_avg_accum    int2_avg_accum_inv    int8_avg            f f 0    1016    0    1016    0
"{0,0}""{0,0}" )); 
! DATA(insert ( 2103    n 0 numeric_avg_accum    numeric_avg            numeric_avg_combine numeric_avg_serialize
numeric_avg_deserializenumeric_avg_accum numeric_accum_inv numeric_avg            f f 0    2281    128 2281    128
_null__null_ )); 
! DATA(insert ( 2104    n 0 float4_accum        float8_avg            float8_combine        -                        -
                     -                -                -                        f f 0    1022    0    0        0
"{0,0,0}"_null_ )); 
! DATA(insert ( 2105    n 0 float8_accum        float8_avg            float8_combine        -                        -
                     -                -                -                        f f 0    1022    0    0        0
"{0,0,0}"_null_ )); 
! DATA(insert ( 2106    n 0 interval_accum        interval_avg        interval_combine    -                        -
                   interval_accum    interval_accum_inv    interval_avg        f f 0    1187    0    1187    0    "{0
second,0second}" "{0 second,0 second}" )); 

  /* sum */
! DATA(insert ( 2107    n 0 int8_avg_accum        numeric_poly_sum    int8_avg_combine    int8_avg_serialize
int8_avg_deserialize   int8_avg_accum    int8_avg_accum_inv    numeric_poly_sum    f f 0    2281    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_combine numeric_avg_serialize
numeric_avg_deserializenumeric_avg_accum numeric_accum_inv numeric_sum            f f 0    2281    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_ )); 

  /* 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_ )); 

  /* 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" )); 

  /* var_pop */
! DATA(insert ( 2718    n 0 int8_accum        numeric_var_pop            numeric_combine            numeric_serialize
    numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_pop            f f 0    2281    128
2281   128 _null_ _null_ )); 
! DATA(insert ( 2719    n 0 int4_accum        numeric_poly_var_pop    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int4_accum        int4_accum_inv    numeric_poly_var_pop    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2720    n 0 int2_accum        numeric_poly_var_pop    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int2_accum        int2_accum_inv    numeric_poly_var_pop    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2721    n 0 float4_accum    float8_var_pop            float8_combine            -
-                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2722    n 0 float8_accum    float8_var_pop            float8_combine            -
-                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2723    n 0 numeric_accum    numeric_var_pop            numeric_combine            numeric_serialize
   numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_pop        f f 0    2281    128 2281
128 _null_ _null_ )); 

  /* var_samp */
! DATA(insert ( 2641    n 0 int8_accum        numeric_var_samp        numeric_combine            numeric_serialize
 numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_samp        f f 0    2281    128 2281
128 _null_ _null_ )); 
! DATA(insert ( 2642    n 0 int4_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_var_samp    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2643    n 0 int2_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_var_samp    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2644    n 0 float4_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2645    n 0 float8_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2646    n 0 numeric_accum    numeric_var_samp        numeric_combine            numeric_serialize
numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_samp        f f 0    2281    128 2281
128_null_ _null_ )); 

  /* variance: historical Postgres syntax for var_samp */
! DATA(insert ( 2148    n 0 int8_accum        numeric_var_samp        numeric_combine            numeric_serialize
 numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_samp        f f 0    2281    128 2281
128 _null_ _null_ )); 
! DATA(insert ( 2149    n 0 int4_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_var_samp    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2150    n 0 int2_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_var_samp    f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2151    n 0 float4_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2152    n 0 float8_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f 0    1022    0    0
0   "{0,0,0}" _null_ )); 
! DATA(insert ( 2153    n 0 numeric_accum    numeric_var_samp        numeric_combine            numeric_serialize
numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_samp        f f 0    2281    128 2281
128_null_ _null_ )); 

  /* stddev_pop */
! DATA(insert ( 2724    n 0 int8_accum        numeric_stddev_pop        numeric_combine            numeric_serialize
   numeric_deserialize            int8_accum        int8_accum_inv    numeric_stddev_pop        f f 0    2281    128
2281   128 _null_ _null_ )); 
! DATA(insert ( 2725    n 0 int4_accum        numeric_poly_stddev_pop numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int4_accum        int4_accum_inv    numeric_poly_stddev_pop f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2726    n 0 int2_accum        numeric_poly_stddev_pop numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int2_accum        int2_accum_inv    numeric_poly_stddev_pop f f 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2727    n 0 float4_accum    float8_stddev_pop        float8_combine            -
-                           -                -                -                        f f 0    1022    0    0        0
  "{0,0,0}" _null_ )); 
! DATA(insert ( 2728    n 0 float8_accum    float8_stddev_pop        float8_combine            -
-                           -                -                -                        f f 0    1022    0    0        0
  "{0,0,0}" _null_ )); 
! DATA(insert ( 2729    n 0 numeric_accum    numeric_stddev_pop        numeric_combine            numeric_serialize
  numeric_deserialize            numeric_accum    numeric_accum_inv numeric_stddev_pop    f f 0    2281    128 2281
128_null_ _null_ )); 

  /* stddev_samp */
! DATA(insert ( 2712    n 0 int8_accum        numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            int8_accum    int8_accum_inv    numeric_stddev_samp            f
f0    2281    128 2281    128 _null_ _null_ )); 
! DATA(insert ( 2713    n 0 int4_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int4_accum    int4_accum_inv    numeric_poly_stddev_samp    f f 0
 2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2714    n 0 int2_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int2_accum    int2_accum_inv    numeric_poly_stddev_samp    f f 0
 2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2715    n 0 float4_accum    float8_stddev_samp            float8_combine            -
    -                            -            -                -                            f f 0    1022    0    0
  0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2716    n 0 float8_accum    float8_stddev_samp            float8_combine            -
    -                            -            -                -                            f f 0    1022    0    0
  0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2717    n 0 numeric_accum    numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            numeric_accum numeric_accum_inv numeric_stddev_samp        f f 0
  2281    128 2281    128 _null_ _null_ )); 

  /* stddev: historical Postgres syntax for stddev_samp */
! DATA(insert ( 2154    n 0 int8_accum        numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            int8_accum        int8_accum_inv    numeric_stddev_samp
 f f 0    2281    128 2281    128 _null_ _null_ )); 
! DATA(insert ( 2155    n 0 int4_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_stddev_samp    f
f0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2156    n 0 int2_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_stddev_samp    f
f0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2157    n 0 float4_accum    float8_stddev_samp            float8_combine            -
    -                            -                -                -                            f f 0    1022    0    0
      0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2158    n 0 float8_accum    float8_stddev_samp            float8_combine            -
    -                            -                -                -                            f f 0    1022    0    0
      0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2159    n 0 numeric_accum    numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            numeric_accum    numeric_accum_inv numeric_stddev_samp        f
f0    2281    128 2281    128 _null_ _null_ )); 

  /* SQL2003 binary regression aggregates */
! DATA(insert ( 2818    n 0 int8inc_float8_float8    -                    int8pl                -    -    -
  -                -            f f 0    20        0    0        0    "0" _null_ )); 
! DATA(insert ( 2819    n 0 float8_regr_accum    float8_regr_sxx            float8_regr_combine -    -    -
  -                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2820    n 0 float8_regr_accum    float8_regr_syy            float8_regr_combine -    -    -
  -                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2821    n 0 float8_regr_accum    float8_regr_sxy            float8_regr_combine -    -    -
  -                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2822    n 0 float8_regr_accum    float8_regr_avgx        float8_regr_combine -    -    -
-               -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2823    n 0 float8_regr_accum    float8_regr_avgy        float8_regr_combine -    -    -
-               -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2824    n 0 float8_regr_accum    float8_regr_r2            float8_regr_combine -    -    -
 -                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2825    n 0 float8_regr_accum    float8_regr_slope        float8_regr_combine -    -    -
-                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2826    n 0 float8_regr_accum    float8_regr_intercept    float8_regr_combine -    -    -
-                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2827    n 0 float8_regr_accum    float8_covar_pop        float8_regr_combine -    -    -
-               -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2828    n 0 float8_regr_accum    float8_covar_samp        float8_regr_combine -    -    -
-                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2829    n 0 float8_regr_accum    float8_corr                float8_regr_combine -    -    -
  -                -            f f 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 

  /* boolean-and and boolean-or */
! DATA(insert ( 2517    n 0 booland_statefunc    -    booland_statefunc    -    -    bool_accum    bool_accum_inv
bool_alltrue   f f 58    16    0    2281    16    _null_ _null_ )); 
! DATA(insert ( 2518    n 0 boolor_statefunc    -    boolor_statefunc    -    -    bool_accum    bool_accum_inv
bool_anytrue   f f 59    16    0    2281    16    _null_ _null_ )); 
! DATA(insert ( 2519    n 0 booland_statefunc    -    booland_statefunc    -    -    bool_accum    bool_accum_inv
bool_alltrue   f f 58    16    0    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_ )); 

  /* xml */
! DATA(insert ( 2901    n 0 xmlconcat2    -                -        -    -    -                -                -
        f f 0    142        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_ )); 

  /* text */
! DATA(insert ( 3538    n 0 string_agg_transfn    string_agg_finalfn    -    -    -    -                -
-                f f 0    2281    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_ )); 

  /* 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_ )); 

  /* 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_ )); 

  /* 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_ )); 
!
!
! /*
!  * prototypes for functions in pg_aggregate.c
!  */
! extern ObjectAddress AggregateCreate(const char *aggName,
!                 Oid aggNamespace,
!                 char aggKind,
!                 int numArgs,
!                 int numDirectArgs,
!                 oidvector *parameterTypes,
!                 Datum allParameterTypes,
!                 Datum parameterModes,
!                 Datum parameterNames,
!                 List *parameterDefaults,
!                 Oid variadicArgType,
!                 List *aggtransfnName,
!                 List *aggfinalfnName,
!                 List *aggcombinefnName,
!                 List *aggserialfnName,
!                 List *aggdeserialfnName,
!                 List *aggmtransfnName,
!                 List *aggminvtransfnName,
!                 List *aggmfinalfnName,
!                 bool finalfnExtraArgs,
!                 bool mfinalfnExtraArgs,
!                 List *aggsortopName,
!                 Oid aggTransType,
!                 int32 aggTransSpace,
!                 Oid aggmTransType,
!                 int32 aggmTransSpace,
!                 const char *agginitval,
!                 const char *aggminitval,
!                 char proparallel);

  #endif                            /* PG_AGGREGATE_H */
--- 151,333 ----
   */

  /* avg */
! DATA(insert ( 2100    n 0 int8_avg_accum        numeric_poly_avg    int8_avg_combine    int8_avg_serialize
int8_avg_deserialize   int8_avg_accum    int8_avg_accum_inv    numeric_poly_avg    f f r r 0    2281    48    2281
48   _null_ _null_ )); 
! DATA(insert ( 2101    n 0 int4_avg_accum        int8_avg            int4_avg_combine    -                        -
                   int4_avg_accum    int4_avg_accum_inv    int8_avg            f f r r 0    1016    0    1016    0
"{0,0}""{0,0}" )); 
! DATA(insert ( 2102    n 0 int2_avg_accum        int8_avg            int4_avg_combine    -                        -
                   int2_avg_accum    int2_avg_accum_inv    int8_avg            f f r r 0    1016    0    1016    0
"{0,0}""{0,0}" )); 
! DATA(insert ( 2103    n 0 numeric_avg_accum    numeric_avg            numeric_avg_combine numeric_avg_serialize
numeric_avg_deserializenumeric_avg_accum numeric_accum_inv numeric_avg            f f r r 0    2281    128 2281    128
_null__null_ )); 
! DATA(insert ( 2104    n 0 float4_accum        float8_avg            float8_combine        -                        -
                     -                -                -                        f f r r 0    1022    0    0        0
"{0,0,0}"_null_ )); 
! DATA(insert ( 2105    n 0 float8_accum        float8_avg            float8_combine        -                        -
                     -                -                -                        f f r r 0    1022    0    0        0
"{0,0,0}"_null_ )); 
! DATA(insert ( 2106    n 0 interval_accum        interval_avg        interval_combine    -                        -
                   interval_accum    interval_accum_inv    interval_avg        f f r r 0    1187    0    1187    0
"{0second,0 second}" "{0 second,0 second}" )); 

  /* sum */
! DATA(insert ( 2107    n 0 int8_avg_accum        numeric_poly_sum    int8_avg_combine    int8_avg_serialize
int8_avg_deserialize   int8_avg_accum    int8_avg_accum_inv    numeric_poly_sum    f f r r 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 r r 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 r r 0    20        0    1016    0
_null_ "{0,0}" )); 
! DATA(insert ( 2110    n 0 float4pl            -                    float4pl            -                        -
                  -                -                    -                    f f r r 0    700        0    0        0
_null__null_ )); 
! DATA(insert ( 2111    n 0 float8pl            -                    float8pl            -                        -
                  -                -                    -                    f f r r 0    701        0    0        0
_null__null_ )); 
! DATA(insert ( 2112    n 0 cash_pl                -                    cash_pl                -
-                       cash_pl            cash_mi                -                    f f r r 0    790        0    790
      0    _null_ _null_ )); 
! DATA(insert ( 2113    n 0 interval_pl            -                    interval_pl            -
-                       interval_pl        interval_mi            -                    f f r r 0    1186    0    1186
0    _null_ _null_ )); 
! DATA(insert ( 2114    n 0 numeric_avg_accum    numeric_sum            numeric_avg_combine numeric_avg_serialize
numeric_avg_deserializenumeric_avg_accum numeric_accum_inv numeric_sum            f f r r 0    2281    128 2281    128
_null__null_ )); 

  /* max */
! DATA(insert ( 2115    n 0 int8larger        -                int8larger            -    -    -                -
        -                f f r r 413        20        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2116    n 0 int4larger        -                int4larger            -    -    -                -
        -                f f r r 521        23        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2117    n 0 int2larger        -                int2larger            -    -    -                -
        -                f f r r 520        21        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2118    n 0 oidlarger        -                oidlarger            -    -    -                -
      -                f f r r 610        26        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2119    n 0 float4larger    -                float4larger        -    -    -                -
    -                f f r r 623        700        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2120    n 0 float8larger    -                float8larger        -    -    -                -
    -                f f r r 674        701        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2121    n 0 int4larger        -                int4larger            -    -    -                -
        -                f f r r 563        702        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2122    n 0 date_larger        -                date_larger            -    -    -                -
          -                f f r r 1097    1082    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2123    n 0 time_larger        -                time_larger            -    -    -                -
          -                f f r r 1112    1083    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2124    n 0 timetz_larger    -                timetz_larger        -    -    -                -
      -                f f r r 1554    1266    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2125    n 0 cashlarger        -                cashlarger            -    -    -                -
        -                f f r r 903        790        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2126    n 0 timestamp_larger    -            timestamp_larger    -    -    -                -
    -                f f r r 2064    1114    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2127    n 0 timestamptz_larger    -            timestamptz_larger    -    -    -                -
        -                f f r r 1324    1184    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2128    n 0 interval_larger -                interval_larger        -    -    -                -
       -                f f r r 1334    1186    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2129    n 0 text_larger        -                text_larger            -    -    -                -
          -                f f r r 666        25        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2130    n 0 numeric_larger    -                numeric_larger        -    -    -                -
        -                f f r r 1756    1700    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2050    n 0 array_larger    -                array_larger        -    -    -                -
    -                f f r r 1073    2277    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2244    n 0 bpchar_larger    -                bpchar_larger        -    -    -                -
      -                f f r r 1060    1042    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2797    n 0 tidlarger        -                tidlarger            -    -    -                -
      -                f f r r 2800    27        0    0        0    _null_ _null_ )); 
! DATA(insert ( 3526    n 0 enum_larger        -                enum_larger            -    -    -                -
          -                f f r r 3519    3500    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3564    n 0 network_larger    -                network_larger        -    -    -                -
        -                f f r r 1205    869        0    0        0    _null_ _null_ )); 

  /* min */
! DATA(insert ( 2131    n 0 int8smaller        -                int8smaller            -    -    -                -
          -                f f r r 412        20        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2132    n 0 int4smaller        -                int4smaller            -    -    -                -
          -                f f r r 97        23        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2133    n 0 int2smaller        -                int2smaller            -    -    -                -
          -                f f r r 95        21        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2134    n 0 oidsmaller        -                oidsmaller            -    -    -                -
        -                f f r r 609        26        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2135    n 0 float4smaller    -                float4smaller        -    -    -                -
      -                f f r r 622        700        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2136    n 0 float8smaller    -                float8smaller        -    -    -                -
      -                f f r r 672        701        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2137    n 0 int4smaller        -                int4smaller            -    -    -                -
          -                f f r r 562        702        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2138    n 0 date_smaller    -                date_smaller        -    -    -                -
    -                f f r r 1095    1082    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2139    n 0 time_smaller    -                time_smaller        -    -    -                -
    -                f f r r 1110    1083    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2140    n 0 timetz_smaller    -                timetz_smaller        -    -    -                -
        -                f f r r 1552    1266    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2141    n 0 cashsmaller        -                cashsmaller            -    -    -                -
          -                f f r r 902        790        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2142    n 0 timestamp_smaller    -            timestamp_smaller    -    -    -                -
      -                f f r r 2062    1114    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2143    n 0 timestamptz_smaller -            timestamptz_smaller -    -    -                -
    -                f f r r 1322    1184    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2144    n 0 interval_smaller    -            interval_smaller    -    -    -                -
    -                f f r r 1332    1186    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2145    n 0 text_smaller    -                text_smaller        -    -    -                -
    -                f f r r 664        25        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2146    n 0 numeric_smaller -                numeric_smaller        -    -    -                -
       -                f f r r 1754    1700    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2051    n 0 array_smaller    -                array_smaller        -    -    -                -
      -                f f r r 1072    2277    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2245    n 0 bpchar_smaller    -                bpchar_smaller        -    -    -                -
        -                f f r r 1058    1042    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2798    n 0 tidsmaller        -                tidsmaller            -    -    -                -
        -                f f r r 2799    27        0    0        0    _null_ _null_ )); 
! DATA(insert ( 3527    n 0 enum_smaller    -                enum_smaller        -    -    -                -
    -                f f r r 3518    3500    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3565    n 0 network_smaller -                network_smaller        -    -    -                -
       -                f f r r 1203    869        0    0        0    _null_ _null_ )); 

  /* count */
! DATA(insert ( 2147    n 0 int8inc_any        -                int8pl    -    -    int8inc_any        int8dec_any
 -                f f r r 0        20        0    20        0    "0" "0" )); 
! DATA(insert ( 2803    n 0 int8inc            -                int8pl    -    -    int8inc            int8dec
 -                f f r r 0        20        0    20        0    "0" "0" )); 

  /* var_pop */
! DATA(insert ( 2718    n 0 int8_accum        numeric_var_pop            numeric_combine            numeric_serialize
    numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_pop            f f r r 0    2281
1282281    128 _null_ _null_ )); 
! DATA(insert ( 2719    n 0 int4_accum        numeric_poly_var_pop    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int4_accum        int4_accum_inv    numeric_poly_var_pop    f f r r 0    2281    48    2281
 48    _null_ _null_ )); 
! DATA(insert ( 2720    n 0 int2_accum        numeric_poly_var_pop    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int2_accum        int2_accum_inv    numeric_poly_var_pop    f f r r 0    2281    48    2281
 48    _null_ _null_ )); 
! DATA(insert ( 2721    n 0 float4_accum    float8_var_pop            float8_combine            -
-                            -                -                -                        f f r r 0    1022    0    0
  0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2722    n 0 float8_accum    float8_var_pop            float8_combine            -
-                            -                -                -                        f f r r 0    1022    0    0
  0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2723    n 0 numeric_accum    numeric_var_pop            numeric_combine            numeric_serialize
   numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_pop        f f r r 0    2281    128
2281   128 _null_ _null_ )); 

  /* var_samp */
! DATA(insert ( 2641    n 0 int8_accum        numeric_var_samp        numeric_combine            numeric_serialize
 numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_samp        f f r r 0    2281    128
2281   128 _null_ _null_ )); 
! DATA(insert ( 2642    n 0 int4_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_var_samp    f f r r 0    2281    48
2281   48    _null_ _null_ )); 
! DATA(insert ( 2643    n 0 int2_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_var_samp    f f r r 0    2281    48
2281   48    _null_ _null_ )); 
! DATA(insert ( 2644    n 0 float4_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f r r 0    1022    0    0
   0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2645    n 0 float8_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f r r 0    1022    0    0
   0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2646    n 0 numeric_accum    numeric_var_samp        numeric_combine            numeric_serialize
numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_samp        f f r r 0    2281    128 2281
  128 _null_ _null_ )); 

  /* variance: historical Postgres syntax for var_samp */
! DATA(insert ( 2148    n 0 int8_accum        numeric_var_samp        numeric_combine            numeric_serialize
 numeric_deserialize            int8_accum        int8_accum_inv    numeric_var_samp        f f r r 0    2281    128
2281   128 _null_ _null_ )); 
! DATA(insert ( 2149    n 0 int4_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_var_samp    f f r r 0    2281    48
2281   48    _null_ _null_ )); 
! DATA(insert ( 2150    n 0 int2_accum        numeric_poly_var_samp    numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_var_samp    f f r r 0    2281    48
2281   48    _null_ _null_ )); 
! DATA(insert ( 2151    n 0 float4_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f r r 0    1022    0    0
   0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2152    n 0 float8_accum    float8_var_samp            float8_combine            -
 -                            -                -                -                        f f r r 0    1022    0    0
   0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2153    n 0 numeric_accum    numeric_var_samp        numeric_combine            numeric_serialize
numeric_deserialize            numeric_accum    numeric_accum_inv numeric_var_samp        f f r r 0    2281    128 2281
  128 _null_ _null_ )); 

  /* stddev_pop */
! DATA(insert ( 2724    n 0 int8_accum        numeric_stddev_pop        numeric_combine            numeric_serialize
   numeric_deserialize            int8_accum        int8_accum_inv    numeric_stddev_pop        f f r r 0    2281
1282281    128 _null_ _null_ )); 
! DATA(insert ( 2725    n 0 int4_accum        numeric_poly_stddev_pop numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int4_accum        int4_accum_inv    numeric_poly_stddev_pop f f r r 0    2281    48    2281
 48    _null_ _null_ )); 
! DATA(insert ( 2726    n 0 int2_accum        numeric_poly_stddev_pop numeric_poly_combine    numeric_poly_serialize
numeric_poly_deserialize   int2_accum        int2_accum_inv    numeric_poly_stddev_pop f f r r 0    2281    48    2281
 48    _null_ _null_ )); 
! DATA(insert ( 2727    n 0 float4_accum    float8_stddev_pop        float8_combine            -
-                           -                -                -                        f f r r 0    1022    0    0
 0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2728    n 0 float8_accum    float8_stddev_pop        float8_combine            -
-                           -                -                -                        f f r r 0    1022    0    0
 0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2729    n 0 numeric_accum    numeric_stddev_pop        numeric_combine            numeric_serialize
  numeric_deserialize            numeric_accum    numeric_accum_inv numeric_stddev_pop    f f r r 0    2281    128 2281
  128 _null_ _null_ )); 

  /* stddev_samp */
! DATA(insert ( 2712    n 0 int8_accum        numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            int8_accum    int8_accum_inv    numeric_stddev_samp            f
fr r 0    2281    128 2281    128 _null_ _null_ )); 
! DATA(insert ( 2713    n 0 int4_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int4_accum    int4_accum_inv    numeric_poly_stddev_samp    f f r
r0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2714    n 0 int2_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int2_accum    int2_accum_inv    numeric_poly_stddev_samp    f f r
r0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2715    n 0 float4_accum    float8_stddev_samp            float8_combine            -
    -                            -            -                -                            f f r r 0    1022    0    0
      0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2716    n 0 float8_accum    float8_stddev_samp            float8_combine            -
    -                            -            -                -                            f f r r 0    1022    0    0
      0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2717    n 0 numeric_accum    numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            numeric_accum numeric_accum_inv numeric_stddev_samp        f f r
r0    2281    128 2281    128 _null_ _null_ )); 

  /* stddev: historical Postgres syntax for stddev_samp */
! DATA(insert ( 2154    n 0 int8_accum        numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            int8_accum        int8_accum_inv    numeric_stddev_samp
 f f r r 0    2281    128 2281    128 _null_ _null_ )); 
! DATA(insert ( 2155    n 0 int4_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int4_accum        int4_accum_inv    numeric_poly_stddev_samp    f
fr r 0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2156    n 0 int2_accum        numeric_poly_stddev_samp    numeric_poly_combine
numeric_poly_serialize   numeric_poly_deserialize    int2_accum        int2_accum_inv    numeric_poly_stddev_samp    f
fr r 0    2281    48    2281    48    _null_ _null_ )); 
! DATA(insert ( 2157    n 0 float4_accum    float8_stddev_samp            float8_combine            -
    -                            -                -                -                            f f r r 0    1022    0
 0        0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2158    n 0 float8_accum    float8_stddev_samp            float8_combine            -
    -                            -                -                -                            f f r r 0    1022    0
 0        0    "{0,0,0}" _null_ )); 
! DATA(insert ( 2159    n 0 numeric_accum    numeric_stddev_samp            numeric_combine
numeric_serialize       numeric_deserialize            numeric_accum    numeric_accum_inv numeric_stddev_samp        f
fr r 0    2281    128 2281    128 _null_ _null_ )); 

  /* SQL2003 binary regression aggregates */
! DATA(insert ( 2818    n 0 int8inc_float8_float8    -                    int8pl                -    -    -
  -                -            f f r r 0    20        0    0        0    "0" _null_ )); 
! DATA(insert ( 2819    n 0 float8_regr_accum    float8_regr_sxx            float8_regr_combine -    -    -
  -                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2820    n 0 float8_regr_accum    float8_regr_syy            float8_regr_combine -    -    -
  -                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2821    n 0 float8_regr_accum    float8_regr_sxy            float8_regr_combine -    -    -
  -                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2822    n 0 float8_regr_accum    float8_regr_avgx        float8_regr_combine -    -    -
-               -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2823    n 0 float8_regr_accum    float8_regr_avgy        float8_regr_combine -    -    -
-               -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2824    n 0 float8_regr_accum    float8_regr_r2            float8_regr_combine -    -    -
 -                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2825    n 0 float8_regr_accum    float8_regr_slope        float8_regr_combine -    -    -
-                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2826    n 0 float8_regr_accum    float8_regr_intercept    float8_regr_combine -    -    -
-                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2827    n 0 float8_regr_accum    float8_covar_pop        float8_regr_combine -    -    -
-               -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2828    n 0 float8_regr_accum    float8_covar_samp        float8_regr_combine -    -    -
-                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 
! DATA(insert ( 2829    n 0 float8_regr_accum    float8_corr                float8_regr_combine -    -    -
  -                -            f f r r 0    1022    0    0        0    "{0,0,0,0,0,0}" _null_ )); 

  /* boolean-and and boolean-or */
! DATA(insert ( 2517    n 0 booland_statefunc    -    booland_statefunc    -    -    bool_accum    bool_accum_inv
bool_alltrue   f f r r 58    16    0    2281    16    _null_ _null_ )); 
! DATA(insert ( 2518    n 0 boolor_statefunc    -    boolor_statefunc    -    -    bool_accum    bool_accum_inv
bool_anytrue   f f r r 59    16    0    2281    16    _null_ _null_ )); 
! DATA(insert ( 2519    n 0 booland_statefunc    -    booland_statefunc    -    -    bool_accum    bool_accum_inv
bool_alltrue   f f r r 58    16    0    2281    16    _null_ _null_ )); 

  /* bitwise integer */
! DATA(insert ( 2236    n 0 int2and        -                int2and -    -    -                -                -
        f f r r 0    21        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2237    n 0 int2or        -                int2or    -    -    -                -                -
         f f r r 0    21        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2238    n 0 int4and        -                int4and -    -    -                -                -
        f f r r 0    23        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2239    n 0 int4or        -                int4or    -    -    -                -                -
         f f r r 0    23        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2240    n 0 int8and        -                int8and -    -    -                -                -
        f f r r 0    20        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2241    n 0 int8or        -                int8or    -    -    -                -                -
         f f r r 0    20        0    0        0    _null_ _null_ )); 
! DATA(insert ( 2242    n 0 bitand        -                bitand    -    -    -                -                -
         f f r r 0    1560    0    0        0    _null_ _null_ )); 
! DATA(insert ( 2243    n 0 bitor        -                bitor    -    -    -                -                -
       f f r r 0    1560    0    0        0    _null_ _null_ )); 

  /* xml */
! DATA(insert ( 2901    n 0 xmlconcat2    -                -        -    -    -                -                -
        f f r r 0    142        0    0        0    _null_ _null_ )); 

  /* array */
! DATA(insert ( 2335    n 0 array_agg_transfn        array_agg_finalfn        -    -    -    -        -
-               t f r r 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 4053    n 0 array_agg_array_transfn array_agg_array_finalfn -    -    -    -        -                -
             t f r r 0    2281    0    0        0    _null_ _null_ )); 

  /* text */
! DATA(insert ( 3538    n 0 string_agg_transfn    string_agg_finalfn    -    -    -    -                -
-                f f r r 0    2281    0    0        0    _null_ _null_ )); 

  /* bytea */
! DATA(insert ( 3545    n 0 bytea_string_agg_transfn    bytea_string_agg_finalfn    -    -    -    -                -
            -        f f r r 0    2281    0    0        0    _null_ _null_ )); 

  /* json */
! DATA(insert ( 3175    n 0 json_agg_transfn    json_agg_finalfn            -    -    -    -                -
    -                f f r r 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3197    n 0 json_object_agg_transfn json_object_agg_finalfn -    -    -    -                -
    -                f f r r 0    2281    0    0        0    _null_ _null_ )); 

  /* jsonb */
! DATA(insert ( 3267    n 0 jsonb_agg_transfn    jsonb_agg_finalfn                -    -    -    -                -
          -            f f r r 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3270    n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn    -    -    -    -                -
         -            f f r r 0    2281    0    0        0    _null_ _null_ )); 

  /* ordered-set and hypothetical-set aggregates */
! DATA(insert ( 3972    o 1 ordered_set_transition            percentile_disc_final                    -    -    -    -
      -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3974    o 1 ordered_set_transition            percentile_cont_float8_final            -    -    -    -
     -        -        f f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3976    o 1 ordered_set_transition            percentile_cont_interval_final            -    -    -
-       -        -        f f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3978    o 1 ordered_set_transition            percentile_disc_multi_final                -    -    -
-       -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3980    o 1 ordered_set_transition            percentile_cont_float8_multi_final        -    -    -
-       -        -        f f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3982    o 1 ordered_set_transition            percentile_cont_interval_multi_final    -    -    -    -
     -        -        f f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3984    o 0 ordered_set_transition            mode_final                                -    -    -
-       -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3986    h 1 ordered_set_transition_multi    rank_final                                -    -    -    -
     -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3988    h 1 ordered_set_transition_multi    percent_rank_final                        -    -    -    -
     -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3990    h 1 ordered_set_transition_multi    cume_dist_final                            -    -    -    -
      -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 
! DATA(insert ( 3992    h 1 ordered_set_transition_multi    dense_rank_final                        -    -    -    -
   -        -        t f w w 0    2281    0    0        0    _null_ _null_ )); 

  #endif                            /* PG_AGGREGATE_H */
diff --git a/src/include/catalog/pg_aggregate_fn.h b/src/include/catalog/pg_aggregate_fn.h
index ...a323aab .
*** a/src/include/catalog/pg_aggregate_fn.h
--- b/src/include/catalog/pg_aggregate_fn.h
***************
*** 0 ****
--- 1,52 ----
+ /*-------------------------------------------------------------------------
+  *
+  * pg_aggregate_fn.h
+  *      prototypes for functions in catalog/pg_aggregate.c
+  *
+  *
+  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * src/include/catalog/pg_aggregate_fn.h
+  *
+  *-------------------------------------------------------------------------
+  */
+ #ifndef PG_AGGREGATE_FN_H
+ #define PG_AGGREGATE_FN_H
+
+ #include "catalog/objectaddress.h"
+ #include "nodes/pg_list.h"
+
+ extern ObjectAddress AggregateCreate(const char *aggName,
+                 Oid aggNamespace,
+                 char aggKind,
+                 int numArgs,
+                 int numDirectArgs,
+                 oidvector *parameterTypes,
+                 Datum allParameterTypes,
+                 Datum parameterModes,
+                 Datum parameterNames,
+                 List *parameterDefaults,
+                 Oid variadicArgType,
+                 List *aggtransfnName,
+                 List *aggfinalfnName,
+                 List *aggcombinefnName,
+                 List *aggserialfnName,
+                 List *aggdeserialfnName,
+                 List *aggmtransfnName,
+                 List *aggminvtransfnName,
+                 List *aggmfinalfnName,
+                 bool finalfnExtraArgs,
+                 bool mfinalfnExtraArgs,
+                 char finalfnModify,
+                 char mfinalfnModify,
+                 List *aggsortopName,
+                 Oid aggTransType,
+                 int32 aggTransSpace,
+                 Oid aggmTransType,
+                 int32 aggmTransSpace,
+                 const char *agginitval,
+                 const char *aggminitval,
+                 char proparallel);
+
+ #endif                            /* PG_AGGREGATE_FN_H */
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out
index 341ba52..723d0b1 100644
*** a/src/test/regress/expected/create_aggregate.out
--- b/src/test/regress/expected/create_aggregate.out
*************** create aggregate my_percentile_disc(floa
*** 71,77 ****
    stype = internal,
    sfunc = ordered_set_transition,
    finalfunc = percentile_disc_final,
!   finalfunc_extra = true
  );
  create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
    stype = internal,
--- 71,78 ----
    stype = internal,
    sfunc = ordered_set_transition,
    finalfunc = percentile_disc_final,
!   finalfunc_extra = true,
!   finalfunc_modify = read_write
  );
  create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
    stype = internal,
*************** CREATE AGGREGATE myavg (numeric)
*** 146,160 ****
      finalfunc = numeric_avg,
      serialfunc = numeric_avg_serialize,
      deserialfunc = numeric_avg_deserialize,
!     combinefunc = numeric_avg_combine
  );
  -- Ensure all these functions made it into the catalog
! SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn
  FROM pg_aggregate
  WHERE aggfnoid = 'myavg'::REGPROC;
!  aggfnoid |    aggtransfn     |    aggcombinefn     | aggtranstype |      aggserialfn      |      aggdeserialfn
! ----------+-------------------+---------------------+--------------+-----------------------+-------------------------
!  myavg    | numeric_avg_accum | numeric_avg_combine |         2281 | numeric_avg_serialize | numeric_avg_deserialize
  (1 row)

  DROP AGGREGATE myavg (numeric);
--- 147,163 ----
      finalfunc = numeric_avg,
      serialfunc = numeric_avg_serialize,
      deserialfunc = numeric_avg_deserialize,
!     combinefunc = numeric_avg_combine,
!     finalfunc_modify = stop_updates  -- just to test a non-default setting
  );
  -- Ensure all these functions made it into the catalog
! SELECT aggfnoid, aggtransfn, aggcombinefn, aggtranstype::regtype,
!        aggserialfn, aggdeserialfn, aggfinalmodify
  FROM pg_aggregate
  WHERE aggfnoid = 'myavg'::REGPROC;
!  aggfnoid |    aggtransfn     |    aggcombinefn     | aggtranstype |      aggserialfn      |      aggdeserialfn
|aggfinalmodify  
!
----------+-------------------+---------------------+--------------+-----------------------+-------------------------+----------------
!  myavg    | numeric_avg_accum | numeric_avg_combine | internal     | numeric_avg_serialize | numeric_avg_deserialize
|s 
  (1 row)

  DROP AGGREGATE myavg (numeric);
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index fcf8bd7..684f7f2 100644
*** a/src/test/regress/expected/opr_sanity.out
--- b/src/test/regress/expected/opr_sanity.out
*************** WHERE aggfnoid = 0 OR aggtransfn = 0 OR
*** 1275,1280 ****
--- 1275,1282 ----
      aggkind NOT IN ('n', 'o', 'h') OR
      aggnumdirectargs < 0 OR
      (aggkind = 'n' AND aggnumdirectargs > 0) OR
+     aggfinalmodify NOT IN ('r', 's', 'w') OR
+     aggmfinalmodify NOT IN ('r', 's', 'w') OR
      aggtranstype = 0 OR aggtransspace < 0 OR aggmtransspace < 0;
   ctid | aggfnoid
  ------+----------
diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql
index ae3a6c0..6e3651c 100644
*** a/src/test/regress/sql/create_aggregate.sql
--- b/src/test/regress/sql/create_aggregate.sql
*************** create aggregate my_percentile_disc(floa
*** 86,92 ****
    stype = internal,
    sfunc = ordered_set_transition,
    finalfunc = percentile_disc_final,
!   finalfunc_extra = true
  );

  create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
--- 86,93 ----
    stype = internal,
    sfunc = ordered_set_transition,
    finalfunc = percentile_disc_final,
!   finalfunc_extra = true,
!   finalfunc_modify = read_write
  );

  create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
*************** CREATE AGGREGATE myavg (numeric)
*** 161,171 ****
      finalfunc = numeric_avg,
      serialfunc = numeric_avg_serialize,
      deserialfunc = numeric_avg_deserialize,
!     combinefunc = numeric_avg_combine
  );

  -- Ensure all these functions made it into the catalog
! SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn
  FROM pg_aggregate
  WHERE aggfnoid = 'myavg'::REGPROC;

--- 162,174 ----
      finalfunc = numeric_avg,
      serialfunc = numeric_avg_serialize,
      deserialfunc = numeric_avg_deserialize,
!     combinefunc = numeric_avg_combine,
!     finalfunc_modify = stop_updates  -- just to test a non-default setting
  );

  -- Ensure all these functions made it into the catalog
! SELECT aggfnoid, aggtransfn, aggcombinefn, aggtranstype::regtype,
!        aggserialfn, aggdeserialfn, aggfinalmodify
  FROM pg_aggregate
  WHERE aggfnoid = 'myavg'::REGPROC;

diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 2945966..e8fdf84 100644
*** a/src/test/regress/sql/opr_sanity.sql
--- b/src/test/regress/sql/opr_sanity.sql
*************** WHERE aggfnoid = 0 OR aggtransfn = 0 OR
*** 795,800 ****
--- 795,802 ----
      aggkind NOT IN ('n', 'o', 'h') OR
      aggnumdirectargs < 0 OR
      (aggkind = 'n' AND aggnumdirectargs > 0) OR
+     aggfinalmodify NOT IN ('r', 's', 'w') OR
+     aggmfinalmodify NOT IN ('r', 's', 'w') OR
      aggtranstype = 0 OR aggtransspace < 0 OR aggmtransspace < 0;

  -- Make sure the matching pg_proc entry is sensible, too.

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Gourav Kumar
Дата:
Сообщение: Re: [HACKERS] Disable cross products in postgres
Следующее
От: Thomas Munro
Дата:
Сообщение: Re: [HACKERS] Continuous integration on Windows?