]> granicus.if.org Git - postgresql/commitdiff
Allow polymorphic aggregates to have non-polymorphic state data types.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 23 Apr 2014 23:17:31 +0000 (19:17 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 23 Apr 2014 23:17:41 +0000 (19:17 -0400)
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject.  The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments.  However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature.  So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations.  We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.

The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column.  I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.

While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency.  I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.

17 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_aggregate.sgml
doc/src/sgml/xaggr.sgml
src/backend/catalog/pg_aggregate.c
src/backend/commands/aggregatecmds.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeWindowAgg.c
src/backend/parser/parse_agg.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.h
src/include/catalog/pg_proc.h
src/include/parser/parse_agg.h
src/test/regress/expected/create_aggregate.out
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/create_aggregate.sql
src/test/regress/sql/opr_sanity.sql

index e8f21d54194386a529b337976c8a02820d5d4d67..415a3bcf2e84ad7e5164ffb8cf24bbff97c0c535 100644 (file)
       <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
       <entry>Final function for moving-aggregate mode (zero if none)</entry>
      </row>
+     <row>
+      <entry><structfield>aggfinalextra</structfield></entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>True to pass extra dummy arguments to aggfinalfn</entry>
+     </row>
+     <row>
+      <entry><structfield>aggmfinalextra</structfield></entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>True to pass extra dummy arguments to aggmfinalfn</entry>
+     </row>
      <row>
       <entry><structfield>aggsortop</structfield></entry>
       <entry><type>oid</type></entry>
index 268acf3e84d13317476e69308df8dfbaa52bd17c..ef1eaf85be5a9670d4335c576d73461e681d3686 100644 (file)
@@ -26,12 +26,14 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
     [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
+    [ , FINALFUNC_EXTRA ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ]
     [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ]
     [ , MSTYPE = <replaceable class="PARAMETER">mstate_data_type</replaceable> ]
     [ , MSSPACE = <replaceable class="PARAMETER">mstate_data_size</replaceable> ]
     [ , MFINALFUNC = <replaceable class="PARAMETER">mffunc</replaceable> ]
+    [ , MFINALFUNC_EXTRA ]
     [ , MINITCOND = <replaceable class="PARAMETER">minitial_condition</replaceable> ]
     [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
 )
@@ -42,6 +44,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
     [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
+    [ , FINALFUNC_EXTRA ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , HYPOTHETICAL ]
 )
@@ -54,12 +57,14 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
     [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
+    [ , FINALFUNC_EXTRA ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , MSFUNC = <replaceable class="PARAMETER">sfunc</replaceable> ]
     [ , MINVFUNC = <replaceable class="PARAMETER">invfunc</replaceable> ]
     [ , MSTYPE = <replaceable class="PARAMETER">state_data_type</replaceable> ]
     [ , MSSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , MFINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
+    [ , MFINALFUNC_EXTRA ]
     [ , MINITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
 )
@@ -166,12 +171,25 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
    input rows.
   </para>
 
+  <para>
+   Sometimes it is useful to declare the final function as taking not just
+   the state value, but extra parameters corresponding to the aggregate's
+   input values.  The main reason for doing this is if the final function
+   is polymorphic and the state value's data type would be inadequate to
+   pin down the result type.  These extra parameters are always passed as
+   NULL (and so the final function must not be strict when
+   the <literal>FINALFUNC_EXTRA</> option is used), but nonetheless they
+   are valid parameters.  The final function could for example make use
+   of <function>get_fn_expr_argtype</> to identify the actual argument type
+   in the current call.
+  </para>
+
   <para>
    An aggregate can optionally support <firstterm>moving-aggregate mode</>,
    as described in <xref linkend="xaggr-moving-aggregates">.  This requires
    specifying the <literal>MSFUNC</>, <literal>MINVFUNC</>,
    and <literal>MSTYPE</> parameters, and optionally
-   the <literal>MSPACE</>, <literal>MFINALFUNC</>,
+   the <literal>MSPACE</>, <literal>MFINALFUNC</>, <literal>MFINALFUNC_EXTRA</>,
    and <literal>MINITCOND</> parameters.  Except for <literal>MINVFUNC</>,
    these parameters work like the corresponding simple-aggregate parameters
    without <literal>M</>; they define a separate implementation of the
@@ -361,12 +379,16 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
      <para>
       For ordered-set (including hypothetical-set) aggregates, the
       final function receives not only the final state value,
-      but also the values of all the direct arguments, followed by
-      null values corresponding to each aggregated argument.
-      (The reason for including the aggregated arguments in the function
-      signature is that this may be necessary to allow correct resolution
-      of the aggregate result type, when a polymorphic aggregate is
-      being defined.)
+      but also the values of all the direct arguments.
+     </para>
+
+     <para>
+      If <literal>FINALFUNC_EXTRA</> is specified, then in addition to the
+      final state value and any direct arguments, the final function
+      receives extra NULL values corresponding to the aggregate's regular
+      (aggregated) arguments.  This is mainly useful to allow correct
+      resolution of the aggregate result type when a polymorphic aggregate
+      is being defined.
      </para>
     </listitem>
    </varlistentry>
@@ -438,9 +460,11 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
       The name of the final function called to compute the aggregate's
       result after all input rows have been traversed, when using
       moving-aggregate mode.  This works the same as <replaceable>ffunc</>,
-      except that its input type is <replaceable>mstate_data_type</>.
+      except that its first argument's type
+      is <replaceable>mstate_data_type</> and extra dummy arguments are
+      specified by writing <literal>MFINALFUNC_EXTRA</>.
       The aggregate result type determined by <replaceable>mffunc</>
-      and <replaceable>mstate_data_type</> must match that determined by the
+      or <replaceable>mstate_data_type</> must match that determined by the
       aggregate's regular implementation.
      </para>
     </listitem>
@@ -494,6 +518,13 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
  <refsect1>
   <title>Notes</title>
 
+   <para>
+    In parameters that specify support function names, you can write
+    a schema name if needed, for example <literal>SFUNC = public.sum</>.
+    Do not write argument types there, however &mdash; the argument types
+    of the support functions are determined from other parameters.
+   </para>
+
    <para>
     If an aggregate supports moving-aggregate mode, it will improve
     calculation efficiency when the aggregate is used as a window function
index cbbb051911545e2f128885df8b688a4420a4d584..bf3fba84922e29f8c00f74c7125d816b8e473fa9 100644 (file)
@@ -127,7 +127,7 @@ CREATE AGGREGATE avg (float8)
    <function>float8_accum</> requires a three-element array, not just
    two elements, because it accumulates the sum of squares as well as
    the sum and count of the inputs.  This is so that it can be used for
-   some other aggregates besides <function>avg</>.
+   some other aggregates as well as <function>avg</>.
    </para>
   </note>
 
@@ -182,7 +182,7 @@ CREATE AGGREGATE avg (float8)
    The inverse transition function is passed the current state value and the
    aggregate input value(s) for the earliest row included in the current
    state.  It must reconstruct what the state value would have been if the
-   given input value had never been aggregated, but only the rows following
+   given input row had never been aggregated, but only the rows following
    it.  This sometimes requires that the forward transition function keep
    more state than is needed for plain aggregation mode.  Therefore, the
    moving-aggregate mode uses a completely separate implementation from the
@@ -339,6 +339,47 @@ SELECT attrelid::regclass, array_accum(atttypid::regtype)
 </programlisting>
   </para>
 
+  <para>
+   Ordinarily, an aggregate function with a polymorphic result type has a
+   polymorphic state type, as in the above example.  This is necessary
+   because otherwise the final function cannot be declared sensibly: it
+   would need to have a polymorphic result type but no polymorphic argument
+   type, which <command>CREATE FUNCTION</> will reject on the grounds that
+   the result type cannot be deduced from a call.  But sometimes it is
+   inconvenient to use a polymorphic state type.  The most common case is
+   where the aggregate support functions are to be written in C and the
+   state type should be declared as <type>internal</> because there is
+   no SQL-level equivalent for it.  To address this case, it is possible to
+   declare the final function as taking extra <quote>dummy</> arguments
+   that match the input arguments of the aggregate.  Such dummy arguments
+   are always passed as NULLs since no specific value is available when the
+   final function is called.  Their only use is to allow a polymorphic
+   final function's result type to be connected to the aggregate's input
+   type(s).  For example, the definition of the built-in
+   aggregate <function>array_agg</> is equivalent to
+
+<programlisting>
+CREATE FUNCTION array_agg_transfn(internal, anyelement)
+  RETURNS internal ...;
+CREATE FUNCTION array_agg_finalfn(internal, anyelement)
+  RETURNS anyarray ...;
+
+CREATE AGGREGATE array_agg (anyelement)
+(
+    sfunc = array_agg_transfn,
+    stype = internal,
+    finalfunc = array_agg_finalfn,
+    finalfunc_extra
+);
+</programlisting>
+
+   Here, the <literal>finalfunc_extra</> option specifies that the final
+   function receives, in addition to the state value, extra dummy
+   argument(s) corresponding to the aggregate's input argument(s).
+   The extra <type>anyelement</> argument allows the declaration
+   of <function>array_agg_finalfn</> to be valid.
+  </para>
+
   <para>
    An aggregate function can be made to accept a varying number of arguments
    by declaring its last argument as a <literal>VARIADIC</> array, in much
@@ -401,15 +442,23 @@ SELECT myaggregate(a, b, c ORDER BY a) FROM ...
    definition of <function>percentile_disc</> is equivalent to:
 
 <programlisting>
+CREATE FUNCTION ordered_set_transition(internal, anyelement)
+  RETURNS internal ...;
+CREATE FUNCTION percentile_disc_final(internal, float8, anyelement)
+  RETURNS anyelement ...;
+
 CREATE AGGREGATE percentile_disc (float8 ORDER BY anyelement)
 (
     sfunc = ordered_set_transition,
     stype = internal,
-    finalfunc = percentile_disc_final
+    finalfunc = percentile_disc_final,
+    finalfunc_extra
 );
 </programlisting>
 
-   which could be used to obtain a median household income like this:
+   This aggregate takes a <type>float8</> direct argument (the percentile
+   fraction) and an aggregated input that can be of any sortable data type.
+   It could be used to obtain a median household income like this:
 
 <programlisting>
 SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY income) FROM households;
@@ -447,25 +496,12 @@ SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY income) FROM households;
    same definition as for normal aggregates, but note that the direct
    arguments (if any) are not provided.  The final function receives
    the last state value, the values of the direct arguments if any,
-   and null values corresponding to the aggregated input(s).  While the
-   null values seem useless at first sight, they are important because
-   they make it possible to include the data types of the aggregated
-   input(s) in the final function's signature, which may be necessary
-   to resolve the output type of a polymorphic aggregate.  For example,
-   the built-in <function>mode()</> ordered-set aggregate takes a
-   single aggregated column of any sortable data type and returns a
-   value of that same type.  This is possible because the final function
-   is declared as <literal>mode_final(internal, anyelement) returns
-   anyelement</>, with the <type>anyelement</> parameter corresponding
-   to the dummy null argument that represents the aggregated column.
-   The actual data is conveyed in the <type>internal</>-type state
-   value, but type resolution needs a parse-time indication of what the
-   result data type will be, and the dummy argument provides that.
-   In the example of <function>percentile_disc</>, the support functions
-   are respectively declared as
-   <literal>ordered_set_transition(internal, "any") returns internal</>
-   and <literal>percentile_disc_final(internal, float8, anyelement)
-   returns anyelement</>.
+   and (if <literal>finalfunc_extra</> is specified) NULL values
+   corresponding to the aggregated input(s).  As with normal
+   aggregates, <literal>finalfunc_extra</> is only really useful if the
+   aggregate is polymorphic; then the extra dummy argument(s) are needed
+   to connect the final function's result type to the aggregate's input
+   type(s).
   </para>
 
   <para>
index 633b8f1d6ac79e64fb1dabaeb039c1ff02ac5bbc..d99c2e5edaee0e8443e3aff9514bbb6d043dc76e 100644 (file)
@@ -60,6 +60,8 @@ AggregateCreate(const char *aggName,
                                List *aggmtransfnName,
                                List *aggminvtransfnName,
                                List *aggmfinalfnName,
+                               bool finalfnExtraArgs,
+                               bool mfinalfnExtraArgs,
                                List *aggsortopName,
                                Oid aggTransType,
                                int32 aggTransSpace,
@@ -344,48 +346,46 @@ AggregateCreate(const char *aggName,
                ReleaseSysCache(tup);
        }
 
-       /*
-        * Set up fnArgs for looking up finalfn(s)
-        *
-        * For ordinary aggs, the finalfn just takes the transtype.  For
-        * ordered-set aggs, it takes the transtype plus all args.      (The
-        * aggregated args are useless at runtime, and are actually passed as
-        * NULLs, but we may need them in the function signature to allow
-        * resolution of a polymorphic agg's result type.)
-        */
-       fnArgs[0] = aggTransType;
-       if (AGGKIND_IS_ORDERED_SET(aggKind))
-       {
-               nargs_finalfn = numArgs + 1;
-               memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
-       }
-       else
-       {
-               nargs_finalfn = 1;
-               /* variadic-ness of the aggregate doesn't affect finalfn */
-               variadicArgType = InvalidOid;
-       }
-
        /* handle finalfn, if supplied */
        if (aggfinalfnName)
        {
+               /*
+                * If finalfnExtraArgs is specified, the transfn takes the transtype
+                * plus all args; otherwise, it just takes the transtype plus any
+                * direct args.  (Non-direct args are useless at runtime, and are
+                * actually passed as NULLs, but we may need them in the function
+                * signature to allow resolution of a polymorphic agg's result type.)
+                */
+               Oid                     ffnVariadicArgType = variadicArgType;
+
+               fnArgs[0] = aggTransType;
+               memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
+               if (finalfnExtraArgs)
+                       nargs_finalfn = numArgs + 1;
+               else
+               {
+                       nargs_finalfn = numDirectArgs + 1;
+                       if (numDirectArgs < numArgs)
+                       {
+                               /* variadic argument doesn't affect finalfn */
+                               ffnVariadicArgType = InvalidOid;
+                       }
+               }
+
                finalfn = lookup_agg_function(aggfinalfnName, nargs_finalfn,
-                                                                         fnArgs, variadicArgType,
+                                                                         fnArgs, ffnVariadicArgType,
                                                                          &finaltype);
 
                /*
-                * The finalfn of an ordered-set agg will certainly be passed at least
-                * one null argument, so complain if it's strict.  Nothing bad would
-                * happen at runtime (you'd just get a null result), but it's surely
-                * not what the user wants, so let's complain now.
-                *
-                * Note: it's likely that a strict transfn would also be a mistake,
-                * but the case isn't quite so airtight, so we let that pass.
+                * When finalfnExtraArgs is specified, the finalfn will certainly be
+                * passed at least one null argument, so complain if it's strict.
+                * Nothing bad would happen at runtime (you'd just get a null result),
+                * but it's surely not what the user wants, so let's complain now.
                 */
-               if (AGGKIND_IS_ORDERED_SET(aggKind) && func_strict(finalfn))
+               if (finalfnExtraArgs && func_strict(finalfn))
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                                        errmsg("final function of an ordered-set aggregate must not be declared STRICT")));
+                                        errmsg("final function with extra arguments must not be declared STRICT")));
        }
        else
        {
@@ -434,21 +434,34 @@ AggregateCreate(const char *aggName,
                if (aggmfinalfnName)
                {
                        /*
-                        * The arguments are the same as for the regular finalfn, except
-                        * that the transition data type might be different.  So re-use
-                        * the fnArgs values set up above, except for that one.
+                        * The arguments are figured the same way as for the regular
+                        * finalfn, but using aggmTransType and mfinalfnExtraArgs.
                         */
+                       Oid                     ffnVariadicArgType = variadicArgType;
+
                        fnArgs[0] = aggmTransType;
+                       memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
+                       if (mfinalfnExtraArgs)
+                               nargs_finalfn = numArgs + 1;
+                       else
+                       {
+                               nargs_finalfn = numDirectArgs + 1;
+                               if (numDirectArgs < numArgs)
+                               {
+                                       /* variadic argument doesn't affect finalfn */
+                                       ffnVariadicArgType = InvalidOid;
+                               }
+                       }
 
                        mfinalfn = lookup_agg_function(aggmfinalfnName, nargs_finalfn,
-                                                                                  fnArgs, variadicArgType,
+                                                                                  fnArgs, ffnVariadicArgType,
                                                                                   &rettype);
 
-                       /* As above, check strictness if it's an ordered-set agg */
-                       if (AGGKIND_IS_ORDERED_SET(aggKind) && func_strict(mfinalfn))
+                       /* As above, check strictness if mfinalfnExtraArgs is given */
+                       if (mfinalfnExtraArgs && func_strict(mfinalfn))
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                                                errmsg("final function of an ordered-set aggregate must not be declared STRICT")));
+                                                errmsg("final function with extra arguments must not be declared STRICT")));
                }
                else
                {
@@ -554,6 +567,8 @@ AggregateCreate(const char *aggName,
        values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
        values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
        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_aggsortop - 1] = ObjectIdGetDatum(sortop);
        values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
        values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
index 9714112f6d498d3da1b0645310bf457e61475047..a73d7094376fc60262f87b0afb4d9af0f58a1a0f 100644 (file)
@@ -64,6 +64,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
        List       *mtransfuncName = NIL;
        List       *minvtransfuncName = NIL;
        List       *mfinalfuncName = NIL;
+       bool            finalfuncExtraArgs = false;
+       bool            mfinalfuncExtraArgs = false;
        List       *sortoperatorName = NIL;
        TypeName   *baseType = NULL;
        TypeName   *transType = NULL;
@@ -128,6 +130,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                        minvtransfuncName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "mfinalfunc") == 0)
                        mfinalfuncName = defGetQualifiedName(defel);
+               else if (pg_strcasecmp(defel->defname, "finalfunc_extra") == 0)
+                       finalfuncExtraArgs = defGetBoolean(defel);
+               else if (pg_strcasecmp(defel->defname, "mfinalfunc_extra") == 0)
+                       mfinalfuncExtraArgs = defGetBoolean(defel);
                else if (pg_strcasecmp(defel->defname, "sortop") == 0)
                        sortoperatorName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "basetype") == 0)
@@ -380,6 +386,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                                                   mtransfuncName,              /* fwd trans function name */
                                                   minvtransfuncName,   /* inv trans function name */
                                                   mfinalfuncName,              /* final function name */
+                                                  finalfuncExtraArgs,
+                                                  mfinalfuncExtraArgs,
                                                   sortoperatorName,    /* sort operator name */
                                                   transTypeId, /* transition data type */
                                                   transSpace,  /* transition space */
index d60845bcd341e40cc3cd331d16927a964ca176da..186c319a3a268004bd74401edaf0e01a080cab15 100644 (file)
  *
  *       Ordered-set aggregates are treated specially in one other way: we
  *       evaluate any "direct" arguments and pass them to the finalfunc along
- *       with the transition value.  In addition, NULL placeholders are
- *       provided to match the remaining finalfunc arguments, which correspond
- *       to the aggregated expressions.  (These arguments have no use at
- *       runtime, but may be needed to allow resolution of a polymorphic
- *       aggregate's result type.)
+ *       with the transition value.
+ *
+ *       A finalfunc can have additional arguments beyond the transvalue and
+ *       any "direct" arguments, corresponding to the input arguments of the
+ *       aggregate.  These are always just passed as NULL.  Such arguments may be
+ *       needed to allow resolution of a polymorphic aggregate's result type.
  *
  *       We compute aggregate input expressions and run the transition functions
  *       in a temporary econtext (aggstate->tmpcontext).  This is reset at
@@ -151,6 +152,14 @@ typedef struct AggStatePerAggData
         */
        int                     numTransInputs;
 
+       /*
+        * Number of arguments to pass to the finalfn.  This is always at least 1
+        * (the transition state value) plus any ordered-set direct args. If the
+        * finalfn wants extra args then we pass nulls corresponding to the
+        * aggregated input columns.
+        */
+       int                     numFinalArgs;
+
        /* Oids of transfer functions */
        Oid                     transfn_oid;
        Oid                     finalfn_oid;    /* may be InvalidOid */
@@ -797,6 +806,8 @@ finalize_aggregate(AggState *aggstate,
        /*
         * Evaluate any direct arguments.  We do this even if there's no finalfn
         * (which is unlikely anyway), so that side-effects happen as expected.
+        * The direct arguments go into arg positions 1 and up, leaving position 0
+        * for the transition state value.
         */
        i = 1;
        foreach(lc, peraggstate->aggrefstate->aggdirectargs)
@@ -816,19 +827,7 @@ finalize_aggregate(AggState *aggstate,
         */
        if (OidIsValid(peraggstate->finalfn_oid))
        {
-               int                     numFinalArgs;
-
-               /*
-                * Identify number of arguments being passed to the finalfn.  For a
-                * plain agg it's just one (the transition state value).  For
-                * ordered-set aggs we also pass the direct argument(s), plus nulls
-                * corresponding to the aggregate-input columns.
-                */
-               if (AGGKIND_IS_ORDERED_SET(peraggstate->aggref->aggkind))
-                       numFinalArgs = peraggstate->numArguments + 1;
-               else
-                       numFinalArgs = 1;
-               Assert(i <= numFinalArgs);
+               int                     numFinalArgs = peraggstate->numFinalArgs;
 
                /* set up aggstate->curperagg for AggGetAggref() */
                aggstate->curperagg = peraggstate;
@@ -844,12 +843,11 @@ finalize_aggregate(AggState *aggstate,
                anynull |= pergroupstate->transValueIsNull;
 
                /* Fill any remaining argument positions with nulls */
-               while (i < numFinalArgs)
+               for (; i < numFinalArgs; i++)
                {
                        fcinfo.arg[i] = (Datum) 0;
                        fcinfo.argnull[i] = true;
                        anynull = true;
-                       i++;
                }
 
                if (fcinfo.flinfo->fn_strict && anynull)
@@ -1776,12 +1774,18 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                numInputs = list_length(aggref->args);
                peraggstate->numInputs = numInputs;
 
-               /* Detect how many columns to pass to the transfn */
+               /* Detect how many arguments to pass to the transfn */
                if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
                        peraggstate->numTransInputs = numInputs;
                else
                        peraggstate->numTransInputs = numArguments;
 
+               /* Detect how many arguments to pass to the finalfn */
+               if (aggform->aggfinalextra)
+                       peraggstate->numFinalArgs = numArguments + 1;
+               else
+                       peraggstate->numFinalArgs = numDirectArgs + 1;
+
                /* resolve actual type of transition state, if polymorphic */
                aggtranstype = resolve_aggregate_transtype(aggref->aggfnoid,
                                                                                                   aggform->aggtranstype,
@@ -1792,7 +1796,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
                build_aggregate_fnexprs(inputTypes,
                                                                numArguments,
                                                                numDirectArgs,
-                                                               AGGKIND_IS_ORDERED_SET(aggref->aggkind),
+                                                               peraggstate->numFinalArgs,
                                                                aggref->aggvariadic,
                                                                aggtranstype,
                                                                aggref->aggtype,
index 2fcc630a92549088a132411916604dab9713435b..40a925331c980008a16fe52c126cbad9debd9011 100644 (file)
@@ -116,6 +116,8 @@ typedef struct WindowStatePerAggData
        FmgrInfo        invtransfn;
        FmgrInfo        finalfn;
 
+       int                     numFinalArgs;   /* number of arguments to pass to finalfn */
+
        /*
         * initial value from pg_aggregate entry
         */
@@ -557,14 +559,28 @@ finalize_windowaggregate(WindowAggState *winstate,
         */
        if (OidIsValid(peraggstate->finalfn_oid))
        {
+               int                     numFinalArgs = peraggstate->numFinalArgs;
                FunctionCallInfoData fcinfo;
+               bool            anynull;
+               int                     i;
 
-               InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+               InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn),
+                                                                numFinalArgs,
                                                                 perfuncstate->winCollation,
                                                                 (void *) winstate, NULL);
                fcinfo.arg[0] = peraggstate->transValue;
                fcinfo.argnull[0] = peraggstate->transValueIsNull;
-               if (fcinfo.flinfo->fn_strict && peraggstate->transValueIsNull)
+               anynull = peraggstate->transValueIsNull;
+
+               /* Fill any remaining argument positions with nulls */
+               for (i = 1; i < numFinalArgs; i++)
+               {
+                       fcinfo.arg[i] = (Datum) 0;
+                       fcinfo.argnull[i] = true;
+                       anynull = true;
+               }
+
+               if (fcinfo.flinfo->fn_strict && anynull)
                {
                        /* don't call a strict function with NULL inputs */
                        *result = (Datum) 0;
@@ -2089,6 +2105,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
        Oid                     transfn_oid,
                                invtransfn_oid,
                                finalfn_oid;
+       bool            finalextra;
        Expr       *transfnexpr,
                           *invtransfnexpr,
                           *finalfnexpr;
@@ -2127,6 +2144,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
                peraggstate->transfn_oid = transfn_oid = aggform->aggmtransfn;
                peraggstate->invtransfn_oid = invtransfn_oid = aggform->aggminvtransfn;
                peraggstate->finalfn_oid = finalfn_oid = aggform->aggmfinalfn;
+               finalextra = aggform->aggmfinalextra;
                aggtranstype = aggform->aggmtranstype;
                initvalAttNo = Anum_pg_aggregate_aggminitval;
        }
@@ -2135,6 +2153,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
                peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
                peraggstate->invtransfn_oid = invtransfn_oid = InvalidOid;
                peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
+               finalextra = aggform->aggfinalextra;
                aggtranstype = aggform->aggtranstype;
                initvalAttNo = Anum_pg_aggregate_agginitval;
        }
@@ -2185,6 +2204,12 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
                }
        }
 
+       /* Detect how many arguments to pass to the finalfn */
+       if (finalextra)
+               peraggstate->numFinalArgs = numArguments + 1;
+       else
+               peraggstate->numFinalArgs = 1;
+
        /* resolve actual type of transition state, if polymorphic */
        aggtranstype = resolve_aggregate_transtype(wfunc->winfnoid,
                                                                                           aggtranstype,
@@ -2195,7 +2220,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
        build_aggregate_fnexprs(inputTypes,
                                                        numArguments,
                                                        0,      /* no ordered-set window functions yet */
-                                                       false,
+                                                       peraggstate->numFinalArgs,
                                                        false,          /* no variadic window functions yet */
                                                        aggtranstype,
                                                        wfunc->wintype,
@@ -2207,6 +2232,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
                                                        &invtransfnexpr,
                                                        &finalfnexpr);
 
+       /* set up infrastructure for calling the transfn(s) and finalfn */
        fmgr_info(transfn_oid, &peraggstate->transfn);
        fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
 
@@ -2222,6 +2248,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
                fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
        }
 
+       /* get info about relevant datatypes */
        get_typlenbyval(wfunc->wintype,
                                        &peraggstate->resulttypeLen,
                                        &peraggstate->resulttypeByVal);
index 272d27f919e193e43c22aba576d2061ea5413765..9af43d2a3288862370330be3bf439c196228dc29 100644 (file)
@@ -1199,7 +1199,7 @@ void
 build_aggregate_fnexprs(Oid *agg_input_types,
                                                int agg_num_inputs,
                                                int agg_num_direct_inputs,
-                                               bool agg_ordered_set,
+                                               int num_finalfn_inputs,
                                                bool agg_variadic,
                                                Oid agg_state_type,
                                                Oid agg_result_type,
@@ -1292,19 +1292,17 @@ build_aggregate_fnexprs(Oid *agg_input_types,
        argp->location = -1;
        args = list_make1(argp);
 
-       if (agg_ordered_set)
+       /* finalfn may take additional args, which match agg's input types */
+       for (i = 0; i < num_finalfn_inputs - 1; i++)
        {
-               for (i = 0; i < agg_num_inputs; i++)
-               {
-                       argp = makeNode(Param);
-                       argp->paramkind = PARAM_EXEC;
-                       argp->paramid = -1;
-                       argp->paramtype = agg_input_types[i];
-                       argp->paramtypmod = -1;
-                       argp->paramcollid = agg_input_collation;
-                       argp->location = -1;
-                       args = lappend(args, argp);
-               }
+               argp = makeNode(Param);
+               argp->paramkind = PARAM_EXEC;
+               argp->paramid = -1;
+               argp->paramtype = agg_input_types[i];
+               argp->paramtypmod = -1;
+               argp->paramcollid = agg_input_collation;
+               argp->location = -1;
+               args = lappend(args, argp);
        }
 
        *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
index a6c04285018f533cd080dff2cb4c0eedeffbfd6f..c2bb6161b214811d38af43f480e5bb517d4db0c1 100644 (file)
@@ -11551,6 +11551,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        int                     i_aggmtransfn;
        int                     i_aggminvtransfn;
        int                     i_aggmfinalfn;
+       int                     i_aggfinalextra;
+       int                     i_aggmfinalextra;
        int                     i_aggsortop;
        int                     i_hypothetical;
        int                     i_aggtranstype;
@@ -11565,6 +11567,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        const char *aggmtransfn;
        const char *aggminvtransfn;
        const char *aggmfinalfn;
+       bool            aggfinalextra;
+       bool            aggmfinalextra;
        const char *aggsortop;
        char       *aggsortconvop;
        bool            hypothetical;
@@ -11596,11 +11600,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "aggmtransfn, aggminvtransfn, aggmfinalfn, "
                                                  "aggmtranstype::pg_catalog.regtype, "
+                                                 "aggfinalextra, aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
-                                                 "(aggkind = 'h') as hypothetical, "
+                                                 "(aggkind = 'h') AS hypothetical, "
                                                  "aggtransspace, agginitval, "
                                                  "aggmtransspace, aggminitval, "
-                                                 "'t'::boolean AS convertok, "
+                                                 "true AS convertok, "
                                                  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
                                                  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
                                          "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
@@ -11614,11 +11619,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
                                                  "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+                                                 "false AS aggfinalextra, false AS aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
-                                                 "false as hypothetical, "
+                                                 "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
-                                                 "'t'::boolean AS convertok, "
+                                                 "true AS convertok, "
                                                  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
                                                  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
                                          "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
@@ -11632,11 +11638,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
                                                  "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+                                                 "false AS aggfinalextra, false AS aggmfinalextra, "
                                                  "aggsortop::pg_catalog.regoperator, "
-                                                 "false as hypothetical, "
+                                                 "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
-                                                 "'t'::boolean AS convertok "
+                                                 "true AS convertok "
                                                  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
                                                  "WHERE a.aggfnoid = p.oid "
                                                  "AND p.oid = '%u'::pg_catalog.oid",
@@ -11648,11 +11655,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
                                                  "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+                                                 "false AS aggfinalextra, false AS aggmfinalextra, "
                                                  "0 AS aggsortop, "
-                                                 "'f'::boolean as hypothetical, "
+                                                 "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
-                                                 "'t'::boolean AS convertok "
+                                                 "true AS convertok "
                                          "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
                                                  "WHERE a.aggfnoid = p.oid "
                                                  "AND p.oid = '%u'::pg_catalog.oid",
@@ -11664,11 +11672,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "format_type(aggtranstype, NULL) AS aggtranstype, "
                                                  "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
                                                  "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+                                                 "false AS aggfinalextra, false AS aggmfinalextra, "
                                                  "0 AS aggsortop, "
-                                                 "'f'::boolean as hypothetical, "
+                                                 "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
-                                                 "'t'::boolean AS convertok "
+                                                 "true AS convertok "
                                                  "FROM pg_aggregate "
                                                  "WHERE oid = '%u'::oid",
                                                  agginfo->aggfn.dobj.catId.oid);
@@ -11680,8 +11689,9 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
                                                  "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
                                                  "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+                                                 "false AS aggfinalextra, false AS aggmfinalextra, "
                                                  "0 AS aggsortop, "
-                                                 "'f'::boolean as hypothetical, "
+                                                 "false AS hypothetical, "
                                                  "0 AS aggtransspace, agginitval1 AS agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
                                                  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
@@ -11697,6 +11707,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        i_aggmtransfn = PQfnumber(res, "aggmtransfn");
        i_aggminvtransfn = PQfnumber(res, "aggminvtransfn");
        i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
+       i_aggfinalextra = PQfnumber(res, "aggfinalextra");
+       i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
        i_aggsortop = PQfnumber(res, "aggsortop");
        i_hypothetical = PQfnumber(res, "hypothetical");
        i_aggtranstype = PQfnumber(res, "aggtranstype");
@@ -11712,6 +11724,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn);
        aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn);
        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);
@@ -11791,6 +11805,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(details, ",\n    FINALFUNC = %s",
                                                  aggfinalfn);
+               if (aggfinalextra)
+                       appendPQExpBufferStr(details, ",\n    FINALFUNC_EXTRA");
        }
 
        if (strcmp(aggmtransfn, "-") != 0)
@@ -11817,6 +11833,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        {
                appendPQExpBuffer(details, ",\n    MFINALFUNC = %s",
                                                  aggmfinalfn);
+               if (aggmfinalextra)
+                       appendPQExpBufferStr(details, ",\n    MFINALFUNC_EXTRA");
        }
 
        aggsortconvop = convertOperatorReference(fout, aggsortop);
index c96fb61ec5d60f111f0ef5a65c6fa21b35d73941..645682bb01cbe0115b5349b5170ae5503fc7f5a0 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201404161
+#define CATALOG_VERSION_NO     201404231
 
 #endif
index 89a56d5b8e2bc93620b6134caebe75da94600485..0f9c11f64e9fcc98d8fe136ccd3880a9f3517aff 100644 (file)
@@ -35,6 +35,8 @@
  *     aggmtransfn                     forward function for moving-aggregate mode (0 if none)
  *     aggminvtransfn          inverse function for moving-aggregate mode (0 if none)
  *     aggmfinalfn                     final function for moving-aggregate mode (0 if none)
+ *     aggfinalextra           true to pass extra dummy arguments to aggfinalfn
+ *     aggmfinalextra          true to pass extra dummy arguments to aggmfinalfn
  *     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)
@@ -56,6 +58,8 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
        regproc         aggmtransfn;
        regproc         aggminvtransfn;
        regproc         aggmfinalfn;
+       bool            aggfinalextra;
+       bool            aggmfinalextra;
        Oid                     aggsortop;
        Oid                     aggtranstype;
        int32           aggtransspace;
@@ -80,7 +84,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
  * ----------------
  */
 
-#define Natts_pg_aggregate                                     15
+#define Natts_pg_aggregate                                     17
 #define Anum_pg_aggregate_aggfnoid                     1
 #define Anum_pg_aggregate_aggkind                      2
 #define Anum_pg_aggregate_aggnumdirectargs     3
@@ -89,13 +93,15 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 #define Anum_pg_aggregate_aggmtransfn          6
 #define Anum_pg_aggregate_aggminvtransfn       7
 #define Anum_pg_aggregate_aggmfinalfn          8
-#define Anum_pg_aggregate_aggsortop                    9
-#define Anum_pg_aggregate_aggtranstype         10
-#define Anum_pg_aggregate_aggtransspace                11
-#define Anum_pg_aggregate_aggmtranstype                12
-#define Anum_pg_aggregate_aggmtransspace       13
-#define Anum_pg_aggregate_agginitval           14
-#define Anum_pg_aggregate_aggminitval          15
+#define Anum_pg_aggregate_aggfinalextra                9
+#define Anum_pg_aggregate_aggmfinalextra       10
+#define Anum_pg_aggregate_aggsortop                    11
+#define Anum_pg_aggregate_aggtranstype         12
+#define Anum_pg_aggregate_aggtransspace                13
+#define Anum_pg_aggregate_aggmtranstype                14
+#define Anum_pg_aggregate_aggmtransspace       15
+#define Anum_pg_aggregate_agginitval           16
+#define Anum_pg_aggregate_aggminitval          17
 
 /*
  * Symbolic values for aggkind column. We distinguish normal aggregates
@@ -119,177 +125,177 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
  */
 
 /* avg */
-DATA(insert ( 2100     n 0 int8_avg_accum      numeric_avg             int8_avg_accum  int8_accum_inv  numeric_avg             0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2101     n 0 int4_avg_accum      int8_avg                int4_avg_accum  int4_avg_accum_inv      int8_avg        0       1016    0       1016    0       "{0,0}" "{0,0}" ));
-DATA(insert ( 2102     n 0 int2_avg_accum      int8_avg                int2_avg_accum  int2_avg_accum_inv      int8_avg        0       1016    0       1016    0       "{0,0}" "{0,0}" ));
-DATA(insert ( 2103     n 0 numeric_avg_accum numeric_avg       numeric_avg_accum numeric_accum_inv numeric_avg 0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2104     n 0 float4_accum        float8_avg              -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2105     n 0 float8_accum        float8_avg              -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2106     n 0 interval_accum      interval_avg    interval_accum  interval_accum_inv interval_avg 0       1187    0       1187    0       "{0 second,0 second}" "{0 second,0 second}" ));
+DATA(insert ( 2100     n 0 int8_avg_accum      numeric_avg             int8_avg_accum  int8_accum_inv  numeric_avg             f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2101     n 0 int4_avg_accum      int8_avg                int4_avg_accum  int4_avg_accum_inv      int8_avg        f f 0   1016    0       1016    0       "{0,0}" "{0,0}" ));
+DATA(insert ( 2102     n 0 int2_avg_accum      int8_avg                int2_avg_accum  int2_avg_accum_inv      int8_avg        f f 0   1016    0       1016    0       "{0,0}" "{0,0}" ));
+DATA(insert ( 2103     n 0 numeric_avg_accum numeric_avg       numeric_avg_accum numeric_accum_inv numeric_avg f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2104     n 0 float4_accum        float8_avg              -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2105     n 0 float8_accum        float8_avg              -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2106     n 0 interval_accum      interval_avg    interval_accum  interval_accum_inv interval_avg f f 0   1187    0       1187    0       "{0 second,0 second}" "{0 second,0 second}" ));
 
 /* sum */
-DATA(insert ( 2107     n 0 int8_avg_accum      numeric_sum             int8_avg_accum  int8_accum_inv  numeric_sum             0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2108     n 0 int4_sum            -                               int4_avg_accum  int4_avg_accum_inv int2int4_sum 0       20              0       1016    0       _null_ "{0,0}" ));
-DATA(insert ( 2109     n 0 int2_sum            -                               int2_avg_accum  int2_avg_accum_inv int2int4_sum 0       20              0       1016    0       _null_ "{0,0}" ));
-DATA(insert ( 2110     n 0 float4pl            -                               -                               -                               -                               0       700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2111     n 0 float8pl            -                               -                               -                               -                               0       701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2112     n 0 cash_pl                     -                               cash_pl                 cash_mi                 -                               0       790             0       790             0       _null_ _null_ ));
-DATA(insert ( 2113     n 0 interval_pl         -                               interval_pl             interval_mi             -                               0       1186    0       1186    0       _null_ _null_ ));
-DATA(insert ( 2114     n 0 numeric_avg_accum   numeric_sum numeric_avg_accum numeric_accum_inv numeric_sum 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2107     n 0 int8_avg_accum      numeric_sum             int8_avg_accum  int8_accum_inv  numeric_sum             f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2108     n 0 int4_sum            -                               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            -                               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            -                               -                               -                               -                               f f 0   700             0       0               0       _null_ _null_ ));
+DATA(insert ( 2111     n 0 float8pl            -                               -                               -                               -                               f f 0   701             0       0               0       _null_ _null_ ));
+DATA(insert ( 2112     n 0 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_mi             -                               f f 0   1186    0       1186    0       _null_ _null_ ));
+DATA(insert ( 2114     n 0 numeric_avg_accum   numeric_sum numeric_avg_accum numeric_accum_inv numeric_sum f f 0       2281    128 2281        128 _null_ _null_ ));
 
 /* max */
-DATA(insert ( 2115     n 0 int8larger          -                               -                               -                               -                               413             20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2116     n 0 int4larger          -                               -                               -                               -                               521             23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2117     n 0 int2larger          -                               -                               -                               -                               520             21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2118     n 0 oidlarger           -                               -                               -                               -                               610             26              0       0               0       _null_ _null_ ));
-DATA(insert ( 2119     n 0 float4larger        -                               -                               -                               -                               623             700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2120     n 0 float8larger        -                               -                               -                               -                               674             701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2121     n 0 int4larger          -                               -                               -                               -                               563             702             0       0               0       _null_ _null_ ));
-DATA(insert ( 2122     n 0 date_larger         -                               -                               -                               -                               1097    1082    0       0               0       _null_ _null_ ));
-DATA(insert ( 2123     n 0 time_larger         -                               -                               -                               -                               1112    1083    0       0               0       _null_ _null_ ));
-DATA(insert ( 2124     n 0 timetz_larger       -                               -                               -                               -                               1554    1266    0       0               0       _null_ _null_ ));
-DATA(insert ( 2125     n 0 cashlarger          -                               -                               -                               -                               903             790             0       0               0       _null_ _null_ ));
-DATA(insert ( 2126     n 0 timestamp_larger    -                       -                               -                               -                               2064    1114    0       0               0       _null_ _null_ ));
-DATA(insert ( 2127     n 0 timestamptz_larger  -                       -                               -                               -                               1324    1184    0       0               0       _null_ _null_ ));
-DATA(insert ( 2128     n 0 interval_larger -                           -                               -                               -                               1334    1186    0       0               0       _null_ _null_ ));
-DATA(insert ( 2129     n 0 text_larger         -                               -                               -                               -                               666             25              0       0               0       _null_ _null_ ));
-DATA(insert ( 2130     n 0 numeric_larger      -                               -                               -                               -                               1756    1700    0       0               0       _null_ _null_ ));
-DATA(insert ( 2050     n 0 array_larger        -                               -                               -                               -                               1073    2277    0       0               0       _null_ _null_ ));
-DATA(insert ( 2244     n 0 bpchar_larger       -                               -                               -                               -                               1060    1042    0       0               0       _null_ _null_ ));
-DATA(insert ( 2797     n 0 tidlarger           -                               -                               -                               -                               2800    27              0       0               0       _null_ _null_ ));
-DATA(insert ( 3526     n 0 enum_larger         -                               -                               -                               -                               3519    3500    0       0               0       _null_ _null_ ));
+DATA(insert ( 2115     n 0 int8larger          -                               -                               -                               -                               f f 413         20              0       0               0       _null_ _null_ ));
+DATA(insert ( 2116     n 0 int4larger          -                               -                               -                               -                               f f 521         23              0       0               0       _null_ _null_ ));
+DATA(insert ( 2117     n 0 int2larger          -                               -                               -                               -                               f f 520         21              0       0               0       _null_ _null_ ));
+DATA(insert ( 2118     n 0 oidlarger           -                               -                               -                               -                               f f 610         26              0       0               0       _null_ _null_ ));
+DATA(insert ( 2119     n 0 float4larger        -                               -                               -                               -                               f f 623         700             0       0               0       _null_ _null_ ));
+DATA(insert ( 2120     n 0 float8larger        -                               -                               -                               -                               f f 674         701             0       0               0       _null_ _null_ ));
+DATA(insert ( 2121     n 0 int4larger          -                               -                               -                               -                               f f 563         702             0       0               0       _null_ _null_ ));
+DATA(insert ( 2122     n 0 date_larger         -                               -                               -                               -                               f f 1097        1082    0       0               0       _null_ _null_ ));
+DATA(insert ( 2123     n 0 time_larger         -                               -                               -                               -                               f f 1112        1083    0       0               0       _null_ _null_ ));
+DATA(insert ( 2124     n 0 timetz_larger       -                               -                               -                               -                               f f 1554        1266    0       0               0       _null_ _null_ ));
+DATA(insert ( 2125     n 0 cashlarger          -                               -                               -                               -                               f f 903         790             0       0               0       _null_ _null_ ));
+DATA(insert ( 2126     n 0 timestamp_larger    -                       -                               -                               -                               f f 2064        1114    0       0               0       _null_ _null_ ));
+DATA(insert ( 2127     n 0 timestamptz_larger  -                       -                               -                               -                               f f 1324        1184    0       0               0       _null_ _null_ ));
+DATA(insert ( 2128     n 0 interval_larger -                           -                               -                               -                               f f 1334        1186    0       0               0       _null_ _null_ ));
+DATA(insert ( 2129     n 0 text_larger         -                               -                               -                               -                               f f 666         25              0       0               0       _null_ _null_ ));
+DATA(insert ( 2130     n 0 numeric_larger      -                               -                               -                               -                               f f 1756        1700    0       0               0       _null_ _null_ ));
+DATA(insert ( 2050     n 0 array_larger        -                               -                               -                               -                               f f 1073        2277    0       0               0       _null_ _null_ ));
+DATA(insert ( 2244     n 0 bpchar_larger       -                               -                               -                               -                               f f 1060        1042    0       0               0       _null_ _null_ ));
+DATA(insert ( 2797     n 0 tidlarger           -                               -                               -                               -                               f f 2800        27              0       0               0       _null_ _null_ ));
+DATA(insert ( 3526     n 0 enum_larger         -                               -                               -                               -                               f f 3519        3500    0       0               0       _null_ _null_ ));
 
 /* min */
-DATA(insert ( 2131     n 0 int8smaller         -                               -                               -                               -                               412             20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2132     n 0 int4smaller         -                               -                               -                               -                               97              23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2133     n 0 int2smaller         -                               -                               -                               -                               95              21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2134     n 0 oidsmaller          -                               -                               -                               -                               609             26              0       0               0       _null_ _null_ ));
-DATA(insert ( 2135     n 0 float4smaller       -                               -                               -                               -                               622             700             0       0               0       _null_ _null_ ));
-DATA(insert ( 2136     n 0 float8smaller       -                               -                               -                               -                               672             701             0       0               0       _null_ _null_ ));
-DATA(insert ( 2137     n 0 int4smaller         -                               -                               -                               -                               562             702             0       0               0       _null_ _null_ ));
-DATA(insert ( 2138     n 0 date_smaller        -                               -                               -                               -                               1095    1082    0       0               0       _null_ _null_ ));
-DATA(insert ( 2139     n 0 time_smaller        -                               -                               -                               -                               1110    1083    0       0               0       _null_ _null_ ));
-DATA(insert ( 2140     n 0 timetz_smaller      -                               -                               -                               -                               1552    1266    0       0               0       _null_ _null_ ));
-DATA(insert ( 2141     n 0 cashsmaller         -                               -                               -                               -                               902             790             0       0               0       _null_ _null_ ));
-DATA(insert ( 2142     n 0 timestamp_smaller   -                       -                               -                               -                               2062    1114    0       0               0       _null_ _null_ ));
-DATA(insert ( 2143     n 0 timestamptz_smaller -                       -                               -                               -                               1322    1184    0       0               0       _null_ _null_ ));
-DATA(insert ( 2144     n 0 interval_smaller    -                       -                               -                               -                               1332    1186    0       0               0       _null_ _null_ ));
-DATA(insert ( 2145     n 0 text_smaller        -                               -                               -                               -                               664             25              0       0               0       _null_ _null_ ));
-DATA(insert ( 2146     n 0 numeric_smaller -                           -                               -                               -                               1754    1700    0       0               0       _null_ _null_ ));
-DATA(insert ( 2051     n 0 array_smaller       -                               -                               -                               -                               1072    2277    0       0               0       _null_ _null_ ));
-DATA(insert ( 2245     n 0 bpchar_smaller      -                               -                               -                               -                               1058    1042    0       0               0       _null_ _null_ ));
-DATA(insert ( 2798     n 0 tidsmaller          -                               -                               -                               -                               2799    27              0       0               0       _null_ _null_ ));
-DATA(insert ( 3527     n 0 enum_smaller        -                               -                               -                               -                               3518    3500    0       0               0       _null_ _null_ ));
+DATA(insert ( 2131     n 0 int8smaller         -                               -                               -                               -                               f f 412         20              0       0               0       _null_ _null_ ));
+DATA(insert ( 2132     n 0 int4smaller         -                               -                               -                               -                               f f 97          23              0       0               0       _null_ _null_ ));
+DATA(insert ( 2133     n 0 int2smaller         -                               -                               -                               -                               f f 95          21              0       0               0       _null_ _null_ ));
+DATA(insert ( 2134     n 0 oidsmaller          -                               -                               -                               -                               f f 609         26              0       0               0       _null_ _null_ ));
+DATA(insert ( 2135     n 0 float4smaller       -                               -                               -                               -                               f f 622         700             0       0               0       _null_ _null_ ));
+DATA(insert ( 2136     n 0 float8smaller       -                               -                               -                               -                               f f 672         701             0       0               0       _null_ _null_ ));
+DATA(insert ( 2137     n 0 int4smaller         -                               -                               -                               -                               f f 562         702             0       0               0       _null_ _null_ ));
+DATA(insert ( 2138     n 0 date_smaller        -                               -                               -                               -                               f f 1095        1082    0       0               0       _null_ _null_ ));
+DATA(insert ( 2139     n 0 time_smaller        -                               -                               -                               -                               f f 1110        1083    0       0               0       _null_ _null_ ));
+DATA(insert ( 2140     n 0 timetz_smaller      -                               -                               -                               -                               f f 1552        1266    0       0               0       _null_ _null_ ));
+DATA(insert ( 2141     n 0 cashsmaller         -                               -                               -                               -                               f f 902         790             0       0               0       _null_ _null_ ));
+DATA(insert ( 2142     n 0 timestamp_smaller   -                       -                               -                               -                               f f 2062        1114    0       0               0       _null_ _null_ ));
+DATA(insert ( 2143     n 0 timestamptz_smaller -                       -                               -                               -                               f f 1322        1184    0       0               0       _null_ _null_ ));
+DATA(insert ( 2144     n 0 interval_smaller    -                       -                               -                               -                               f f 1332        1186    0       0               0       _null_ _null_ ));
+DATA(insert ( 2145     n 0 text_smaller        -                               -                               -                               -                               f f 664         25              0       0               0       _null_ _null_ ));
+DATA(insert ( 2146     n 0 numeric_smaller -                           -                               -                               -                               f f 1754        1700    0       0               0       _null_ _null_ ));
+DATA(insert ( 2051     n 0 array_smaller       -                               -                               -                               -                               f f 1072        2277    0       0               0       _null_ _null_ ));
+DATA(insert ( 2245     n 0 bpchar_smaller      -                               -                               -                               -                               f f 1058        1042    0       0               0       _null_ _null_ ));
+DATA(insert ( 2798     n 0 tidsmaller          -                               -                               -                               -                               f f 2799        27              0       0               0       _null_ _null_ ));
+DATA(insert ( 3527     n 0 enum_smaller        -                               -                               -                               -                               f f 3518        3500    0       0               0       _null_ _null_ ));
 
 /* count */
-DATA(insert ( 2147     n 0 int8inc_any         -                               int8inc_any             int8dec_any             -                               0               20              0       20              0       "0" "0" ));
-DATA(insert ( 2803     n 0 int8inc                     -                               int8inc                 int8dec                 -                               0               20              0       20              0       "0" "0" ));
+DATA(insert ( 2147     n 0 int8inc_any         -                               int8inc_any             int8dec_any             -                               f f 0           20              0       20              0       "0" "0" ));
+DATA(insert ( 2803     n 0 int8inc                     -                               int8inc                 int8dec                 -                               f f 0           20              0       20              0       "0" "0" ));
 
 /* var_pop */
-DATA(insert ( 2718     n 0 int8_accum  numeric_var_pop         int8_accum              int8_accum_inv  numeric_var_pop 0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2719     n 0 int4_accum  numeric_var_pop         int4_accum              int4_accum_inv  numeric_var_pop 0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2720     n 0 int2_accum  numeric_var_pop         int2_accum              int2_accum_inv  numeric_var_pop 0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2721     n 0 float4_accum        float8_var_pop  -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2722     n 0 float8_accum        float8_var_pop  -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2723     n 0 numeric_accum       numeric_var_pop numeric_accum numeric_accum_inv numeric_var_pop 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2718     n 0 int8_accum  numeric_var_pop         int8_accum              int8_accum_inv  numeric_var_pop f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2719     n 0 int4_accum  numeric_var_pop         int4_accum              int4_accum_inv  numeric_var_pop f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2720     n 0 int2_accum  numeric_var_pop         int2_accum              int2_accum_inv  numeric_var_pop f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2721     n 0 float4_accum        float8_var_pop  -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2722     n 0 float8_accum        float8_var_pop  -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2723     n 0 numeric_accum       numeric_var_pop numeric_accum numeric_accum_inv numeric_var_pop f f 0   2281    128 2281        128 _null_ _null_ ));
 
 /* var_samp */
-DATA(insert ( 2641     n 0 int8_accum  numeric_var_samp        int8_accum              int8_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2642     n 0 int4_accum  numeric_var_samp        int4_accum              int4_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2643     n 0 int2_accum  numeric_var_samp        int2_accum              int2_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2644     n 0 float4_accum        float8_var_samp -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2645     n 0 float8_accum        float8_var_samp -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2646     n 0 numeric_accum       numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp 0 2281        128 2281        128 _null_ _null_ ));
+DATA(insert ( 2641     n 0 int8_accum  numeric_var_samp        int8_accum              int8_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2642     n 0 int4_accum  numeric_var_samp        int4_accum              int4_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2643     n 0 int2_accum  numeric_var_samp        int2_accum              int2_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2644     n 0 float4_accum        float8_var_samp -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2645     n 0 float8_accum        float8_var_samp -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2646     n 0 numeric_accum       numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281    128 2281        128 _null_ _null_ ));
 
 /* variance: historical Postgres syntax for var_samp */
-DATA(insert ( 2148     n 0 int8_accum  numeric_var_samp        int8_accum              int8_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2149     n 0 int4_accum  numeric_var_samp        int4_accum              int4_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2150     n 0 int2_accum  numeric_var_samp        int2_accum              int2_accum_inv  numeric_var_samp 0      2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2151     n 0 float4_accum        float8_var_samp -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2152     n 0 float8_accum        float8_var_samp -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2153     n 0 numeric_accum       numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp 0 2281        128 2281        128 _null_ _null_ ));
+DATA(insert ( 2148     n 0 int8_accum  numeric_var_samp        int8_accum              int8_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2149     n 0 int4_accum  numeric_var_samp        int4_accum              int4_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2150     n 0 int2_accum  numeric_var_samp        int2_accum              int2_accum_inv  numeric_var_samp f f 0  2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2151     n 0 float4_accum        float8_var_samp -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2152     n 0 float8_accum        float8_var_samp -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2153     n 0 numeric_accum       numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281    128 2281        128 _null_ _null_ ));
 
 /* stddev_pop */
-DATA(insert ( 2724     n 0 int8_accum  numeric_stddev_pop              int8_accum      int8_accum_inv  numeric_stddev_pop      0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2725     n 0 int4_accum  numeric_stddev_pop              int4_accum      int4_accum_inv  numeric_stddev_pop      0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2726     n 0 int2_accum  numeric_stddev_pop              int2_accum      int2_accum_inv  numeric_stddev_pop      0       2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2727     n 0 float4_accum        float8_stddev_pop       -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2728     n 0 float8_accum        float8_stddev_pop       -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2729     n 0 numeric_accum       numeric_stddev_pop numeric_accum numeric_accum_inv numeric_stddev_pop 0 2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2724     n 0 int8_accum  numeric_stddev_pop              int8_accum      int8_accum_inv  numeric_stddev_pop      f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2725     n 0 int4_accum  numeric_stddev_pop              int4_accum      int4_accum_inv  numeric_stddev_pop      f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2726     n 0 int2_accum  numeric_stddev_pop              int2_accum      int2_accum_inv  numeric_stddev_pop      f f 0   2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2727     n 0 float4_accum        float8_stddev_pop       -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2728     n 0 float8_accum        float8_stddev_pop       -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2729     n 0 numeric_accum       numeric_stddev_pop numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281        128 2281        128 _null_ _null_ ));
 
 /* stddev_samp */
-DATA(insert ( 2712     n 0 int8_accum  numeric_stddev_samp             int8_accum      int8_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2713     n 0 int4_accum  numeric_stddev_samp             int4_accum      int4_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2714     n 0 int2_accum  numeric_stddev_samp             int2_accum      int2_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2715     n 0 float4_accum        float8_stddev_samp      -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2716     n 0 float8_accum        float8_stddev_samp      -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2717     n 0 numeric_accum       numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp 0 2281  128 2281        128 _null_ _null_ ));
+DATA(insert ( 2712     n 0 int8_accum  numeric_stddev_samp             int8_accum      int8_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2713     n 0 int4_accum  numeric_stddev_samp             int4_accum      int4_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2714     n 0 int2_accum  numeric_stddev_samp             int2_accum      int2_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2715     n 0 float4_accum        float8_stddev_samp      -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2716     n 0 float8_accum        float8_stddev_samp      -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2717     n 0 numeric_accum       numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281      128 2281        128 _null_ _null_ ));
 
 /* stddev: historical Postgres syntax for stddev_samp */
-DATA(insert ( 2154     n 0 int8_accum  numeric_stddev_samp             int8_accum      int8_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2155     n 0 int4_accum  numeric_stddev_samp             int4_accum      int4_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2156     n 0 int2_accum  numeric_stddev_samp             int2_accum      int2_accum_inv  numeric_stddev_samp 0   2281    128 2281        128 _null_ _null_ ));
-DATA(insert ( 2157     n 0 float4_accum        float8_stddev_samp      -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2158     n 0 float8_accum        float8_stddev_samp      -                               -                               -                               0       1022    0       0               0       "{0,0,0}" _null_ ));
-DATA(insert ( 2159     n 0 numeric_accum       numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp 0 2281  128 2281        128 _null_ _null_ ));
+DATA(insert ( 2154     n 0 int8_accum  numeric_stddev_samp             int8_accum      int8_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2155     n 0 int4_accum  numeric_stddev_samp             int4_accum      int4_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2156     n 0 int2_accum  numeric_stddev_samp             int2_accum      int2_accum_inv  numeric_stddev_samp f f 0       2281    128 2281        128 _null_ _null_ ));
+DATA(insert ( 2157     n 0 float4_accum        float8_stddev_samp      -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2158     n 0 float8_accum        float8_stddev_samp      -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0}" _null_ ));
+DATA(insert ( 2159     n 0 numeric_accum       numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281      128 2281        128 _null_ _null_ ));
 
 /* SQL2003 binary regression aggregates */
-DATA(insert ( 2818     n 0 int8inc_float8_float8       -                                       -                               -                               -                               0       20              0       0               0       "0" _null_ ));
-DATA(insert ( 2819     n 0 float8_regr_accum   float8_regr_sxx                 -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2820     n 0 float8_regr_accum   float8_regr_syy                 -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2821     n 0 float8_regr_accum   float8_regr_sxy                 -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2822     n 0 float8_regr_accum   float8_regr_avgx                -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2823     n 0 float8_regr_accum   float8_regr_avgy                -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2824     n 0 float8_regr_accum   float8_regr_r2                  -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2825     n 0 float8_regr_accum   float8_regr_slope               -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2826     n 0 float8_regr_accum   float8_regr_intercept   -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2827     n 0 float8_regr_accum   float8_covar_pop                -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2828     n 0 float8_regr_accum   float8_covar_samp               -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
-DATA(insert ( 2829     n 0 float8_regr_accum   float8_corr                             -                               -                               -                               0       1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2818     n 0 int8inc_float8_float8       -                                       -                               -                               -                               f f 0   20              0       0               0       "0" _null_ ));
+DATA(insert ( 2819     n 0 float8_regr_accum   float8_regr_sxx                 -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2820     n 0 float8_regr_accum   float8_regr_syy                 -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2821     n 0 float8_regr_accum   float8_regr_sxy                 -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2822     n 0 float8_regr_accum   float8_regr_avgx                -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2823     n 0 float8_regr_accum   float8_regr_avgy                -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2824     n 0 float8_regr_accum   float8_regr_r2                  -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2825     n 0 float8_regr_accum   float8_regr_slope               -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2826     n 0 float8_regr_accum   float8_regr_intercept   -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2827     n 0 float8_regr_accum   float8_covar_pop                -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2828     n 0 float8_regr_accum   float8_covar_samp               -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
+DATA(insert ( 2829     n 0 float8_regr_accum   float8_corr                             -                               -                               -                               f f 0   1022    0       0               0       "{0,0,0,0,0,0}" _null_ ));
 
 /* boolean-and and boolean-or */
-DATA(insert ( 2517     n 0 booland_statefunc   -                       bool_accum              bool_accum_inv  bool_alltrue    58      16              0       2281    16      _null_ _null_ ));
-DATA(insert ( 2518     n 0 boolor_statefunc    -                       bool_accum              bool_accum_inv  bool_anytrue    59      16              0       2281    16      _null_ _null_ ));
-DATA(insert ( 2519     n 0 booland_statefunc   -                       bool_accum              bool_accum_inv  bool_alltrue    58      16              0       2281    16      _null_ _null_ ));
+DATA(insert ( 2517     n 0 booland_statefunc   -                       bool_accum              bool_accum_inv  bool_alltrue    f f 58  16              0       2281    16      _null_ _null_ ));
+DATA(insert ( 2518     n 0 boolor_statefunc    -                       bool_accum              bool_accum_inv  bool_anytrue    f f 59  16              0       2281    16      _null_ _null_ ));
+DATA(insert ( 2519     n 0 booland_statefunc   -                       bool_accum              bool_accum_inv  bool_alltrue    f f 58  16              0       2281    16      _null_ _null_ ));
 
 /* bitwise integer */
-DATA(insert ( 2236     n 0 int2and             -                                       -                               -                               -                               0       21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2237     n 0 int2or              -                                       -                               -                               -                               0       21              0       0               0       _null_ _null_ ));
-DATA(insert ( 2238     n 0 int4and             -                                       -                               -                               -                               0       23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2239     n 0 int4or              -                                       -                               -                               -                               0       23              0       0               0       _null_ _null_ ));
-DATA(insert ( 2240     n 0 int8and             -                                       -                               -                               -                               0       20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2241     n 0 int8or              -                                       -                               -                               -                               0       20              0       0               0       _null_ _null_ ));
-DATA(insert ( 2242     n 0 bitand              -                                       -                               -                               -                               0       1560    0       0               0       _null_ _null_ ));
-DATA(insert ( 2243     n 0 bitor               -                                       -                               -                               -                               0       1560    0       0               0       _null_ _null_ ));
+DATA(insert ( 2236     n 0 int2and             -                                       -                               -                               -                               f f 0   21              0       0               0       _null_ _null_ ));
+DATA(insert ( 2237     n 0 int2or              -                                       -                               -                               -                               f f 0   21              0       0               0       _null_ _null_ ));
+DATA(insert ( 2238     n 0 int4and             -                                       -                               -                               -                               f f 0   23              0       0               0       _null_ _null_ ));
+DATA(insert ( 2239     n 0 int4or              -                                       -                               -                               -                               f f 0   23              0       0               0       _null_ _null_ ));
+DATA(insert ( 2240     n 0 int8and             -                                       -                               -                               -                               f f 0   20              0       0               0       _null_ _null_ ));
+DATA(insert ( 2241     n 0 int8or              -                                       -                               -                               -                               f f 0   20              0       0               0       _null_ _null_ ));
+DATA(insert ( 2242     n 0 bitand              -                                       -                               -                               -                               f f 0   1560    0       0               0       _null_ _null_ ));
+DATA(insert ( 2243     n 0 bitor               -                                       -                               -                               -                               f f 0   1560    0       0               0       _null_ _null_ ));
 
 /* xml */
-DATA(insert ( 2901     n 0 xmlconcat2  -                                       -                               -                               -                               0       142             0       0               0       _null_ _null_ ));
+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       -                               -                               -                               0       2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 2335     n 0 array_agg_transfn   array_agg_finalfn       -                               -                               -                               t f 0   2281    0       0               0       _null_ _null_ ));
 
 /* text */
-DATA(insert ( 3538     n 0 string_agg_transfn  string_agg_finalfn      -                               -                               -                               0       2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 3538     n 0 string_agg_transfn  string_agg_finalfn      -                               -                               -                               f f 0   2281    0       0               0       _null_ _null_ ));
 
 /* bytea */
-DATA(insert ( 3545     n 0 bytea_string_agg_transfn    bytea_string_agg_finalfn        -                               -                               -               0       2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 3545     n 0 bytea_string_agg_transfn    bytea_string_agg_finalfn        -                               -                               -               f f 0   2281    0       0               0       _null_ _null_ ));
 
 /* json */
-DATA(insert ( 3175     n 0 json_agg_transfn    json_agg_finalfn                        -                               -                               -                               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3197     n 0 json_object_agg_transfn json_object_agg_finalfn -                           -                               -                               0       2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 3175     n 0 json_agg_transfn    json_agg_finalfn                        -                               -                               -                               f f 0   2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 3197     n 0 json_object_agg_transfn json_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                                   -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3974     o 1 ordered_set_transition                      percentile_cont_float8_final                    -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3976     o 1 ordered_set_transition                      percentile_cont_interval_final                  -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3978     o 1 ordered_set_transition                      percentile_disc_multi_final                             -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3980     o 1 ordered_set_transition                      percentile_cont_float8_multi_final              -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3982     o 1 ordered_set_transition                      percentile_cont_interval_multi_final    -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3984     o 0 ordered_set_transition                      mode_final                                                              -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3986     h 1 ordered_set_transition_multi        rank_final                                                              -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3988     h 1 ordered_set_transition_multi        percent_rank_final                                              -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3990     h 1 ordered_set_transition_multi        cume_dist_final                                                 -               -               -               0       2281    0       0               0       _null_ _null_ ));
-DATA(insert ( 3992     h 1 ordered_set_transition_multi        dense_rank_final                                                -               -               -               0       2281    0       0               0       _null_ _null_ ));
+DATA(insert ( 3972     o 1 ordered_set_transition                      percentile_disc_final                                   -               -               -               t f 0   2281    0       0               0       _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_ ));
 
 
 /*
@@ -311,6 +317,8 @@ extern Oid AggregateCreate(const char *aggName,
                                List *aggmtransfnName,
                                List *aggminvtransfnName,
                                List *aggmfinalfnName,
+                               bool finalfnExtraArgs,
+                               bool mfinalfnExtraArgs,
                                List *aggsortopName,
                                Oid aggTransType,
                                int32 aggTransSpace,
index c77c03615f10bdb189732bcb3dba211f71d12775..65c7dc8cdd5dfbbf9e0bf58f556594e54aed6d77 100644 (file)
@@ -879,7 +879,7 @@ DATA(insert OID = 3168 (  array_replace    PGNSP PGUID 12 1 0 0 0 f f f f f f i
 DESCR("replace any occurrences of an element in an array");
 DATA(insert OID = 2333 (  array_agg_transfn   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 2283" _null_ _null_ _null_ _null_ array_agg_transfn _null_ _null_ _null_ ));
 DESCR("aggregate transition function");
-DATA(insert OID = 2334 (  array_agg_finalfn   PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 2277 "2281" _null_ _null_ _null_ _null_ array_agg_finalfn _null_ _null_ _null_ ));
+DATA(insert OID = 2334 (  array_agg_finalfn   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2277 "2281 2283" _null_ _null_ _null_ _null_ array_agg_finalfn _null_ _null_ _null_ ));
 DESCR("aggregate final function");
 DATA(insert OID = 2335 (  array_agg               PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 2277 "2283" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("concatenate aggregate input into an array");
@@ -4990,11 +4990,11 @@ DATA(insert OID = 3973 ( percentile_disc_final  PGNSP PGUID 12 1 0 0 0 f f f f f
 DESCR("aggregate final function");
 DATA(insert OID = 3974 ( percentile_cont               PGNSP PGUID 12 1 0 0 0 t f f f f f i 2 0 701 "701 701" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("continuous distribution percentile");
-DATA(insert OID = 3975 ( percentile_cont_float8_final  PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 701 "2281 701 701" _null_ _null_ _null_ _null_ percentile_cont_float8_final _null_ _null_ _null_ ));
+DATA(insert OID = 3975 ( percentile_cont_float8_final  PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 701 "2281 701" _null_ _null_ _null_ _null_ percentile_cont_float8_final _null_ _null_ _null_ ));
 DESCR("aggregate final function");
 DATA(insert OID = 3976 ( percentile_cont               PGNSP PGUID 12 1 0 0 0 t f f f f f i 2 0 1186 "701 1186" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("continuous distribution percentile");
-DATA(insert OID = 3977 ( percentile_cont_interval_final PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 1186 "2281 701 1186" _null_ _null_ _null_ _null_ percentile_cont_interval_final _null_ _null_ _null_ ));
+DATA(insert OID = 3977 ( percentile_cont_interval_final PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1186 "2281 701" _null_ _null_ _null_ _null_ percentile_cont_interval_final _null_ _null_ _null_ ));
 DESCR("aggregate final function");
 DATA(insert OID = 3978 ( percentile_disc               PGNSP PGUID 12 1 0 0 0 t f f f f f i 2 0 2277 "1022 2283" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("multiple discrete percentiles");
@@ -5002,11 +5002,11 @@ DATA(insert OID = 3979 ( percentile_disc_multi_final    PGNSP PGUID 12 1 0 0 0 f f
 DESCR("aggregate final function");
 DATA(insert OID = 3980 ( percentile_cont               PGNSP PGUID 12 1 0 0 0 t f f f f f i 2 0 1022 "1022 701" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("multiple continuous percentiles");
-DATA(insert OID = 3981 ( percentile_cont_float8_multi_final PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 1022 "2281 1022 701" _null_ _null_ _null_ _null_ percentile_cont_float8_multi_final _null_ _null_ _null_ ));
+DATA(insert OID = 3981 ( percentile_cont_float8_multi_final PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1022 "2281 1022" _null_ _null_ _null_ _null_ percentile_cont_float8_multi_final _null_ _null_ _null_ ));
 DESCR("aggregate final function");
 DATA(insert OID = 3982 ( percentile_cont               PGNSP PGUID 12 1 0 0 0 t f f f f f i 2 0 1187 "1022 1186" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
 DESCR("multiple continuous percentiles");
-DATA(insert OID = 3983 ( percentile_cont_interval_multi_final  PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 1187 "2281 1022 1186" _null_ _null_ _null_ _null_ percentile_cont_interval_multi_final _null_ _null_ _null_ ));
+DATA(insert OID = 3983 ( percentile_cont_interval_multi_final  PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1187 "2281 1022" _null_ _null_ _null_ _null_ percentile_cont_interval_multi_final _null_ _null_ _null_ ));
 DESCR("aggregate final function");
 DATA(insert OID = 3984 ( mode                                  PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 2283 "2283" _null_ _null_ _null_ _null_        aggregate_dummy _null_ _null_ _null_ ));
 DESCR("most common value");
index 938d408bb701a3c1881d893074136de2312a52b7..3f55ec7cdd7429988e50e273e566741f8ba5c970 100644 (file)
@@ -33,7 +33,7 @@ extern Oid resolve_aggregate_transtype(Oid aggfuncid,
 extern void build_aggregate_fnexprs(Oid *agg_input_types,
                                                int agg_num_inputs,
                                                int agg_num_direct_inputs,
-                                               bool agg_ordered_set,
+                                               int num_finalfn_inputs,
                                                bool agg_variadic,
                                                Oid agg_state_type,
                                                Oid agg_result_type,
index a547ca535fb792040086710232f37b2fca73a1be..82a34fbcd47b4bf9e43af3a3971adbdf1925b00a 100644 (file)
@@ -70,12 +70,14 @@ create aggregate least_agg(variadic items anyarray) (
 create aggregate my_percentile_disc(float8 ORDER BY anyelement) (
   stype = internal,
   sfunc = ordered_set_transition,
-  finalfunc = percentile_disc_final
+  finalfunc = percentile_disc_final,
+  finalfunc_extra = true
 );
 create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
   stype = internal,
   sfunc = ordered_set_transition_multi,
   finalfunc = rank_final,
+  finalfunc_extra = true,
   hypothetical
 );
 alter aggregate my_percentile_disc(float8 ORDER BY anyelement)
index b2d671a08c605f35b0190b49e0399fdfa2fdf1be..42f712790ba02aa3a4b2feedf7373736d6af1650 100644 (file)
@@ -283,6 +283,38 @@ WHERE p1.prorettype = 'internal'::regtype AND NOT
  2304 | internal_in
 (1 row)
 
+-- Look for functions that return a polymorphic type and do not have any
+-- polymorphic argument.  Calls of such functions would be unresolvable
+-- at parse time.  As of 9.4 this query should find only some input functions
+-- associated with these pseudotypes.
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype IN
+    ('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
+     'anyenum'::regtype, 'anyrange'::regtype)
+  AND NOT
+    ('anyelement'::regtype = ANY (p1.proargtypes) OR
+     'anyarray'::regtype = ANY (p1.proargtypes) OR
+     'anynonarray'::regtype = ANY (p1.proargtypes) OR
+     'anyenum'::regtype = ANY (p1.proargtypes) OR
+     'anyrange'::regtype = ANY (p1.proargtypes))
+ORDER BY 2;
+ oid  |    proname     
+------+----------------
+ 2296 | anyarray_in
+ 2502 | anyarray_recv
+ 2312 | anyelement_in
+ 3504 | anyenum_in
+ 2777 | anynonarray_in
+ 3832 | anyrange_in
+  750 | array_in
+ 2400 | array_recv
+ 3506 | enum_in
+ 3532 | enum_recv
+ 3834 | range_in
+ 3836 | range_recv
+(12 rows)
+
 -- Check for length inconsistencies between the various argument-info arrays.
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
@@ -800,16 +832,16 @@ WHERE a.aggfnoid = p.oid AND
     (pfn.proretset OR
      NOT binary_coercible(pfn.prorettype, p.prorettype) OR
      NOT binary_coercible(a.aggtranstype, pfn.proargtypes[0]) OR
-     CASE WHEN a.aggkind = 'n' THEN pfn.pronargs != 1
-     ELSE pfn.pronargs != p.pronargs + 1
-       OR (p.pronargs > 0 AND
+     CASE WHEN a.aggfinalextra THEN pfn.pronargs != p.pronargs + 1
+          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
+     OR (pfn.pronargs > 1 AND
          NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
-       OR (p.pronargs > 1 AND
+     OR (pfn.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
-       OR (p.pronargs > 2 AND
+     OR (pfn.pronargs > 3 AND
          NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
-       -- we could carry the check further, but 3 args is enough for now
-     END);
+     -- we could carry the check further, but 3 args is enough for now
+    );
  aggfnoid | proname | oid | proname 
 ----------+---------+-----+---------
 (0 rows)
@@ -909,16 +941,16 @@ WHERE a.aggfnoid = p.oid AND
     (pfn.proretset OR
      NOT binary_coercible(pfn.prorettype, p.prorettype) OR
      NOT binary_coercible(a.aggmtranstype, pfn.proargtypes[0]) OR
-     CASE WHEN a.aggkind = 'n' THEN pfn.pronargs != 1
-     ELSE pfn.pronargs != p.pronargs + 1
-       OR (p.pronargs > 0 AND
+     CASE WHEN a.aggmfinalextra THEN pfn.pronargs != p.pronargs + 1
+          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
+     OR (pfn.pronargs > 1 AND
          NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
-       OR (p.pronargs > 1 AND
+     OR (pfn.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
-       OR (p.pronargs > 2 AND
+     OR (pfn.pronargs > 3 AND
          NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
-       -- we could carry the check further, but 3 args is enough for now
-     END);
+     -- we could carry the check further, but 3 args is enough for now
+    );
  aggfnoid | proname | oid | proname 
 ----------+---------+-----+---------
 (0 rows)
index 2b502aca3e7833ec7af2e311e711041a9dc5b027..0ec1572dff609454bd03434fa821094c8e0bf156 100644 (file)
@@ -85,13 +85,15 @@ create aggregate least_agg(variadic items anyarray) (
 create aggregate my_percentile_disc(float8 ORDER BY anyelement) (
   stype = internal,
   sfunc = ordered_set_transition,
-  finalfunc = percentile_disc_final
+  finalfunc = percentile_disc_final,
+  finalfunc_extra = true
 );
 
 create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
   stype = internal,
   sfunc = ordered_set_transition_multi,
   finalfunc = rank_final,
+  finalfunc_extra = true,
   hypothetical
 );
 
index dc1acb9eaace45e7522cc2069d0866049243bcc4..2cf6fc8ac32838d3742535622d6eba24e3e1d827 100644 (file)
@@ -226,6 +226,24 @@ FROM pg_proc as p1
 WHERE p1.prorettype = 'internal'::regtype AND NOT
     'internal'::regtype = ANY (p1.proargtypes);
 
+-- Look for functions that return a polymorphic type and do not have any
+-- polymorphic argument.  Calls of such functions would be unresolvable
+-- at parse time.  As of 9.4 this query should find only some input functions
+-- associated with these pseudotypes.
+
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype IN
+    ('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
+     'anyenum'::regtype, 'anyrange'::regtype)
+  AND NOT
+    ('anyelement'::regtype = ANY (p1.proargtypes) OR
+     'anyarray'::regtype = ANY (p1.proargtypes) OR
+     'anynonarray'::regtype = ANY (p1.proargtypes) OR
+     'anyenum'::regtype = ANY (p1.proargtypes) OR
+     'anyrange'::regtype = ANY (p1.proargtypes))
+ORDER BY 2;
+
 -- Check for length inconsistencies between the various argument-info arrays.
 
 SELECT p1.oid, p1.proname
@@ -646,16 +664,16 @@ WHERE a.aggfnoid = p.oid AND
     (pfn.proretset OR
      NOT binary_coercible(pfn.prorettype, p.prorettype) OR
      NOT binary_coercible(a.aggtranstype, pfn.proargtypes[0]) OR
-     CASE WHEN a.aggkind = 'n' THEN pfn.pronargs != 1
-     ELSE pfn.pronargs != p.pronargs + 1
-       OR (p.pronargs > 0 AND
+     CASE WHEN a.aggfinalextra THEN pfn.pronargs != p.pronargs + 1
+          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
+     OR (pfn.pronargs > 1 AND
          NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
-       OR (p.pronargs > 1 AND
+     OR (pfn.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
-       OR (p.pronargs > 2 AND
+     OR (pfn.pronargs > 3 AND
          NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
-       -- we could carry the check further, but 3 args is enough for now
-     END);
+     -- we could carry the check further, but 3 args is enough for now
+    );
 
 -- If transfn is strict then either initval should be non-NULL, or
 -- input type should match transtype so that the first non-null input
@@ -738,16 +756,16 @@ WHERE a.aggfnoid = p.oid AND
     (pfn.proretset OR
      NOT binary_coercible(pfn.prorettype, p.prorettype) OR
      NOT binary_coercible(a.aggmtranstype, pfn.proargtypes[0]) OR
-     CASE WHEN a.aggkind = 'n' THEN pfn.pronargs != 1
-     ELSE pfn.pronargs != p.pronargs + 1
-       OR (p.pronargs > 0 AND
+     CASE WHEN a.aggmfinalextra THEN pfn.pronargs != p.pronargs + 1
+          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
+     OR (pfn.pronargs > 1 AND
          NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
-       OR (p.pronargs > 1 AND
+     OR (pfn.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
-       OR (p.pronargs > 2 AND
+     OR (pfn.pronargs > 3 AND
          NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
-       -- we could carry the check further, but 3 args is enough for now
-     END);
+     -- we could carry the check further, but 3 args is enough for now
+    );
 
 -- If mtransfn is strict then either minitval should be non-NULL, or
 -- input type should match mtranstype so that the first non-null input