]> granicus.if.org Git - postgresql/commitdiff
Allow aggregates to provide estimates of their transition state data size.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 16 Nov 2013 21:03:40 +0000 (16:03 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 16 Nov 2013 21:03:40 +0000 (16:03 -0500)
Formerly the planner had a hard-wired rule of thumb for guessing the amount
of space consumed by an aggregate function's transition state data.  This
estimate is critical to deciding whether it's OK to use hash aggregation,
and in many situations the built-in estimate isn't very good.  This patch
adds a column to pg_aggregate wherein a per-aggregate estimate can be
provided, overriding the planner's default, and infrastructure for setting
the column via CREATE AGGREGATE.

It may be that additional smarts will be required in future, perhaps even
a per-aggregate estimation function.  But this is already a step forward.

This is extracted from a larger patch to improve the performance of numeric
and int8 aggregates.  I (tgl) thought it was worth reviewing and committing
this infrastructure separately.  In this commit, all built-in aggregates
are given aggtransspace = 0, so no behavior should change.

Hadi Moshayedi, reviewed by Pavel Stehule and Tomas Vondra

14 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_aggregate.sgml
src/backend/catalog/pg_aggregate.c
src/backend/commands/aggregatecmds.c
src/backend/commands/define.c
src/backend/optimizer/util/clauses.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.h
src/include/commands/defrem.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 9388df5ac273d32750027618e299f56ad8ba7004..acc261ca516cd91368ad19dd4750c4bbb0294809 100644 (file)
       <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
       <entry>Data type of the aggregate function's internal transition (state) data</entry>
      </row>
+     <row>
+      <entry><structfield>aggtransspace</structfield></entry>
+      <entry><type>int4</type></entry>
+      <entry></entry>
+      <entry>Approximate average size (in bytes) of the transition state
+       data, or zero to use a default estimate</entry>
+     </row>
      <row>
       <entry><structfield>agginitval</structfield></entry>
       <entry><type>text</type></entry>
index 2b35fa4d5226adccfe4d8a6c1e244a56d0ac084f..17819dd1a8edf627df699bdc198ffffdfa2a24e2 100644 (file)
@@ -24,6 +24,7 @@ PostgreSQL documentation
 CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_data_type</replaceable> [ , ... ] ) (
     SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
+    [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
@@ -35,6 +36,7 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
     BASETYPE = <replaceable class="PARAMETER">base_type</replaceable>,
     SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
+    [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
     [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
@@ -264,6 +266,22 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><replaceable class="PARAMETER">state_data_size</replaceable></term>
+    <listitem>
+     <para>
+      The approximate average size (in bytes) of the aggregate's state value.
+      If this parameter is omitted or is zero, a default estimate is used
+      based on the <replaceable>state_data_type</>.
+      The planner uses this value to estimate the memory required for a
+      grouped aggregate query.  The planner will consider using hash
+      aggregation for such a query only if the hash table is estimated to fit
+      in <xref linkend="guc-work-mem">; therefore, large values of this
+      parameter discourage use of hash aggregation.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><replaceable class="PARAMETER">ffunc</replaceable></term>
     <listitem>
index d9e961ebfad668cc56232e8793d230c4044cf70f..9dbec508a0d696863fd01c0d99369efd8ca2bef4 100644 (file)
@@ -55,6 +55,7 @@ AggregateCreate(const char *aggName,
                                List *aggfinalfnName,
                                List *aggsortopName,
                                Oid aggTransType,
+                               int32 aggTransSpace,
                                const char *agginitval)
 {
        Relation        aggdesc;
@@ -273,6 +274,7 @@ AggregateCreate(const char *aggName,
        values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
        values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
        values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
+       values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
        if (agginitval)
                values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
        else
index 78af09246547a7fd091b13509ae1e5ddf1c44102..6fc3e045492d97e0c5f789088e0fad43477902f9 100644 (file)
@@ -60,6 +60,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
        List       *sortoperatorName = NIL;
        TypeName   *baseType = NULL;
        TypeName   *transType = NULL;
+       int32           transSpace = 0;
        char       *initval = NULL;
        int                     numArgs;
        oidvector  *parameterTypes;
@@ -102,6 +103,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                        transType = defGetTypeName(defel);
                else if (pg_strcasecmp(defel->defname, "stype1") == 0)
                        transType = defGetTypeName(defel);
+               else if (pg_strcasecmp(defel->defname, "sspace") == 0)
+                       transSpace = defGetInt32(defel);
                else if (pg_strcasecmp(defel->defname, "initcond") == 0)
                        initval = defGetString(defel);
                else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
@@ -248,5 +251,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
                                                   finalfuncName,               /* final function name */
                                                   sortoperatorName,    /* sort operator name */
                                                   transTypeId, /* transition data type */
+                                                  transSpace,  /* transition space */
                                                   initval);    /* initial condition */
 }
index 9fa222f5fc0f5a4c0766a7e1e840cdf796317995..75f77da2cffefea87c6b118ca62cd6eca5a511b0 100644 (file)
@@ -164,6 +164,30 @@ defGetBoolean(DefElem *def)
        return false;                           /* keep compiler quiet */
 }
 
+/*
+ * Extract an int32 value from a DefElem.
+ */
+int32
+defGetInt32(DefElem *def)
+{
+       if (def->arg == NULL)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("%s requires an integer value",
+                                               def->defname)));
+       switch (nodeTag(def->arg))
+       {
+               case T_Integer:
+                       return (int32) intVal(def->arg);
+               default:
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                        errmsg("%s requires an integer value",
+                                                       def->defname)));
+       }
+       return 0;                                       /* keep compiler quiet */
+}
+
 /*
  * Extract an int64 value from a DefElem.
  */
index add29f54d09e68b30d1985eec7f0cf490be707d8..7ce8a9d8180df60be2d36c0b2e260c9a9f6716f9 100644 (file)
@@ -461,6 +461,7 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
                Oid                     aggtransfn;
                Oid                     aggfinalfn;
                Oid                     aggtranstype;
+               int32           aggtransspace;
                QualCost        argcosts;
                Oid                *inputTypes;
                int                     numArguments;
@@ -478,6 +479,7 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
                aggtransfn = aggform->aggtransfn;
                aggfinalfn = aggform->aggfinalfn;
                aggtranstype = aggform->aggtranstype;
+               aggtransspace = aggform->aggtransspace;
                ReleaseSysCache(aggTuple);
 
                /* count it */
@@ -541,22 +543,30 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
                 */
                if (!get_typbyval(aggtranstype))
                {
-                       int32           aggtranstypmod;
                        int32           avgwidth;
 
-                       /*
-                        * If transition state is of same type as first input, assume it's
-                        * the same typmod (same width) as well.  This works for cases
-                        * like MAX/MIN and is probably somewhat reasonable otherwise.
-                        */
-                       if (numArguments > 0 && aggtranstype == inputTypes[0])
-                               aggtranstypmod = exprTypmod((Node *) linitial(aggref->args));
+                       /* Use average width if aggregate definition gave one */
+                       if (aggtransspace > 0)
+                               avgwidth = aggtransspace;
                        else
-                               aggtranstypmod = -1;
+                       {
+                               /*
+                                * If transition state is of same type as first input, assume
+                                * it's the same typmod (same width) as well.  This works for
+                                * cases like MAX/MIN and is probably somewhat reasonable
+                                * otherwise.
+                                */
+                               int32           aggtranstypmod;
 
-                       avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
-                       avgwidth = MAXALIGN(avgwidth);
+                               if (numArguments > 0 && aggtranstype == inputTypes[0])
+                                       aggtranstypmod = exprTypmod((Node *) linitial(aggref->args));
+                               else
+                                       aggtranstypmod = -1;
+
+                               avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
+                       }
 
+                       avgwidth = MAXALIGN(avgwidth);
                        costs->transitionSpace += avgwidth + 2 * sizeof(void *);
                }
                else if (aggtranstype == INTERNALOID)
@@ -564,12 +574,16 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
                        /*
                         * INTERNAL transition type is a special case: although INTERNAL
                         * is pass-by-value, it's almost certainly being used as a pointer
-                        * to some large data structure.  We assume usage of
+                        * to some large data structure.  The aggregate definition can
+                        * provide an estimate of the size.  If it doesn't, then we assume
                         * ALLOCSET_DEFAULT_INITSIZE, which is a good guess if the data is
                         * being kept in a private memory context, as is done by
                         * array_agg() for instance.
                         */
-                       costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE;
+                       if (aggtransspace > 0)
+                               costs->transitionSpace += aggtransspace;
+                       else
+                               costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE;
                }
 
                /*
index 6c16b3ca49e6ad364117bf4d47c554476cd94cb5..f81094ee7055796916ef81fd77ae93c85383676e 100644 (file)
@@ -11521,12 +11521,14 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        int                     i_aggfinalfn;
        int                     i_aggsortop;
        int                     i_aggtranstype;
+       int                     i_aggtransspace;
        int                     i_agginitval;
        int                     i_convertok;
        const char *aggtransfn;
        const char *aggfinalfn;
        const char *aggsortop;
        const char *aggtranstype;
+       const char *aggtransspace;
        const char *agginitval;
        bool            convertok;
 
@@ -11544,12 +11546,26 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
 
        /* Get aggregate-specific details */
-       if (fout->remoteVersion >= 80400)
+       if (fout->remoteVersion >= 90400)
+       {
+               appendPQExpBuffer(query, "SELECT aggtransfn, "
+                                                 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggtransspace, agginitval, "
+                                                 "'t'::boolean 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 "
+                                                 "WHERE a.aggfnoid = p.oid "
+                                                 "AND p.oid = '%u'::pg_catalog.oid",
+                                                 agginfo->aggfn.dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 80400)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "aggsortop::pg_catalog.regoperator, "
-                                                 "agginitval, "
+                                                 "0 AS aggtransspace, agginitval, "
                                                  "'t'::boolean AS convertok, "
                                                  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
                                                  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
@@ -11563,7 +11579,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "aggsortop::pg_catalog.regoperator, "
-                                                 "agginitval, "
+                                                 "0 AS aggtransspace, agginitval, "
                                                  "'t'::boolean AS convertok "
                                                  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
                                                  "WHERE a.aggfnoid = p.oid "
@@ -11575,7 +11591,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "0 AS aggsortop, "
-                                                 "agginitval, "
+                                                 "0 AS aggtransspace, agginitval, "
                                                  "'t'::boolean AS convertok "
                                          "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
                                                  "WHERE a.aggfnoid = p.oid "
@@ -11587,7 +11603,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
                                                  "format_type(aggtranstype, NULL) AS aggtranstype, "
                                                  "0 AS aggsortop, "
-                                                 "agginitval, "
+                                                 "0 AS aggtransspace, agginitval, "
                                                  "'t'::boolean AS convertok "
                                                  "FROM pg_aggregate "
                                                  "WHERE oid = '%u'::oid",
@@ -11599,7 +11615,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, "
                                                  "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
                                                  "0 AS aggsortop, "
-                                                 "agginitval1 AS agginitval, "
+                                                 "0 AS aggtransspace, agginitval1 AS agginitval, "
                                                  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
                                                  "FROM pg_aggregate "
                                                  "WHERE oid = '%u'::oid",
@@ -11612,6 +11628,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        i_aggfinalfn = PQfnumber(res, "aggfinalfn");
        i_aggsortop = PQfnumber(res, "aggsortop");
        i_aggtranstype = PQfnumber(res, "aggtranstype");
+       i_aggtransspace = PQfnumber(res, "aggtransspace");
        i_agginitval = PQfnumber(res, "agginitval");
        i_convertok = PQfnumber(res, "convertok");
 
@@ -11619,6 +11636,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
        aggsortop = PQgetvalue(res, 0, i_aggsortop);
        aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+       aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
        agginitval = PQgetvalue(res, 0, i_agginitval);
        convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
 
@@ -11672,6 +11690,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  fmtId(aggtranstype));
        }
 
+       if (strcmp(aggtransspace, "0") != 0)
+       {
+               appendPQExpBuffer(details, ",\n    SSPACE = %s",
+                                                 aggtransspace);
+       }
+
        if (!PQgetisnull(res, 0, i_agginitval))
        {
                appendPQExpBuffer(details, ",\n    INITCOND = ");
index 4108f6c16c046af629cad1c525a8b75827b7ef6e..cb9021c525afd7d73c84ecb5dff54114ebe83aef 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201311081
+#define CATALOG_VERSION_NO     201311161
 
 #endif
index 5ad6ea6e3d1a9c89372069bb9334a04b91f7f626..416d651bf0a040dae4e3913de2a7e741a15af41a 100644 (file)
@@ -32,6 +32,7 @@
  *     aggfinalfn                      final function (0 if none)
  *     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)
  *     agginitval                      initial value for transition state (can be NULL)
  * ----------------------------------------------------------------
  */
@@ -44,6 +45,7 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
        regproc         aggfinalfn;
        Oid                     aggsortop;
        Oid                     aggtranstype;
+       int32           aggtransspace;
 
 #ifdef CATALOG_VARLEN                  /* variable-length fields start here */
        text            agginitval;
@@ -62,13 +64,14 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
  * ----------------
  */
 
-#define Natts_pg_aggregate                             6
+#define Natts_pg_aggregate                             7
 #define Anum_pg_aggregate_aggfnoid             1
 #define Anum_pg_aggregate_aggtransfn   2
 #define Anum_pg_aggregate_aggfinalfn   3
 #define Anum_pg_aggregate_aggsortop            4
 #define Anum_pg_aggregate_aggtranstype 5
-#define Anum_pg_aggregate_agginitval   6
+#define Anum_pg_aggregate_aggtransspace 6
+#define Anum_pg_aggregate_agginitval   7
 
 
 /* ----------------
@@ -77,163 +80,163 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
  */
 
 /* avg */
-DATA(insert ( 2100     int8_avg_accum  numeric_avg             0       1231    "{0,0}" ));
-DATA(insert ( 2101     int4_avg_accum  int8_avg                0       1016    "{0,0}" ));
-DATA(insert ( 2102     int2_avg_accum  int8_avg                0       1016    "{0,0}" ));
-DATA(insert ( 2103     numeric_avg_accum       numeric_avg             0       1231    "{0,0}" ));
-DATA(insert ( 2104     float4_accum    float8_avg              0       1022    "{0,0,0}" ));
-DATA(insert ( 2105     float8_accum    float8_avg              0       1022    "{0,0,0}" ));
-DATA(insert ( 2106     interval_accum  interval_avg    0       1187    "{0 second,0 second}" ));
+DATA(insert ( 2100     int8_avg_accum  numeric_avg             0       1231    0       "{0,0}" ));
+DATA(insert ( 2101     int4_avg_accum  int8_avg                0       1016    0       "{0,0}" ));
+DATA(insert ( 2102     int2_avg_accum  int8_avg                0       1016    0       "{0,0}" ));
+DATA(insert ( 2103     numeric_avg_accum       numeric_avg 0   1231    0       "{0,0}" ));
+DATA(insert ( 2104     float4_accum    float8_avg              0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2105     float8_accum    float8_avg              0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2106     interval_accum  interval_avg    0       1187    0       "{0 second,0 second}" ));
 
 /* sum */
-DATA(insert ( 2107     int8_sum                -                               0       1700    _null_ ));
-DATA(insert ( 2108     int4_sum                -                               0       20              _null_ ));
-DATA(insert ( 2109     int2_sum                -                               0       20              _null_ ));
-DATA(insert ( 2110     float4pl                -                               0       700             _null_ ));
-DATA(insert ( 2111     float8pl                -                               0       701             _null_ ));
-DATA(insert ( 2112     cash_pl                 -                               0       790             _null_ ));
-DATA(insert ( 2113     interval_pl             -                               0       1186    _null_ ));
-DATA(insert ( 2114     numeric_add             -                               0       1700    _null_ ));
+DATA(insert ( 2107     int8_sum                -                               0       1700    0       _null_ ));
+DATA(insert ( 2108     int4_sum                -                               0       20              0       _null_ ));
+DATA(insert ( 2109     int2_sum                -                               0       20              0       _null_ ));
+DATA(insert ( 2110     float4pl                -                               0       700             0       _null_ ));
+DATA(insert ( 2111     float8pl                -                               0       701             0       _null_ ));
+DATA(insert ( 2112     cash_pl                 -                               0       790             0       _null_ ));
+DATA(insert ( 2113     interval_pl             -                               0       1186    0       _null_ ));
+DATA(insert ( 2114     numeric_add             -                               0       1700    0       _null_ ));
 
 /* max */
-DATA(insert ( 2115     int8larger              -                               413             20              _null_ ));
-DATA(insert ( 2116     int4larger              -                               521             23              _null_ ));
-DATA(insert ( 2117     int2larger              -                               520             21              _null_ ));
-DATA(insert ( 2118     oidlarger               -                               610             26              _null_ ));
-DATA(insert ( 2119     float4larger    -                               623             700             _null_ ));
-DATA(insert ( 2120     float8larger    -                               674             701             _null_ ));
-DATA(insert ( 2121     int4larger              -                               563             702             _null_ ));
-DATA(insert ( 2122     date_larger             -                               1097    1082    _null_ ));
-DATA(insert ( 2123     time_larger             -                               1112    1083    _null_ ));
-DATA(insert ( 2124     timetz_larger   -                               1554    1266    _null_ ));
-DATA(insert ( 2125     cashlarger              -                               903             790             _null_ ));
-DATA(insert ( 2126     timestamp_larger        -                       2064    1114    _null_ ));
-DATA(insert ( 2127     timestamptz_larger      -                       1324    1184    _null_ ));
-DATA(insert ( 2128     interval_larger -                               1334    1186    _null_ ));
-DATA(insert ( 2129     text_larger             -                               666             25              _null_ ));
-DATA(insert ( 2130     numeric_larger  -                               1756    1700    _null_ ));
-DATA(insert ( 2050     array_larger    -                               1073    2277    _null_ ));
-DATA(insert ( 2244     bpchar_larger   -                               1060    1042    _null_ ));
-DATA(insert ( 2797     tidlarger               -                               2800    27              _null_ ));
-DATA(insert ( 3526     enum_larger             -                               3519    3500    _null_ ));
+DATA(insert ( 2115     int8larger              -                               413             20              0       _null_ ));
+DATA(insert ( 2116     int4larger              -                               521             23              0       _null_ ));
+DATA(insert ( 2117     int2larger              -                               520             21              0       _null_ ));
+DATA(insert ( 2118     oidlarger               -                               610             26              0       _null_ ));
+DATA(insert ( 2119     float4larger    -                               623             700             0       _null_ ));
+DATA(insert ( 2120     float8larger    -                               674             701             0       _null_ ));
+DATA(insert ( 2121     int4larger              -                               563             702             0       _null_ ));
+DATA(insert ( 2122     date_larger             -                               1097    1082    0       _null_ ));
+DATA(insert ( 2123     time_larger             -                               1112    1083    0       _null_ ));
+DATA(insert ( 2124     timetz_larger   -                               1554    1266    0       _null_ ));
+DATA(insert ( 2125     cashlarger              -                               903             790             0       _null_ ));
+DATA(insert ( 2126     timestamp_larger        -                       2064    1114    0       _null_ ));
+DATA(insert ( 2127     timestamptz_larger      -                       1324    1184    0       _null_ ));
+DATA(insert ( 2128     interval_larger -                               1334    1186    0       _null_ ));
+DATA(insert ( 2129     text_larger             -                               666             25              0       _null_ ));
+DATA(insert ( 2130     numeric_larger  -                               1756    1700    0       _null_ ));
+DATA(insert ( 2050     array_larger    -                               1073    2277    0       _null_ ));
+DATA(insert ( 2244     bpchar_larger   -                               1060    1042    0       _null_ ));
+DATA(insert ( 2797     tidlarger               -                               2800    27              0       _null_ ));
+DATA(insert ( 3526     enum_larger             -                               3519    3500    0       _null_ ));
 
 /* min */
-DATA(insert ( 2131     int8smaller             -                               412             20              _null_ ));
-DATA(insert ( 2132     int4smaller             -                               97              23              _null_ ));
-DATA(insert ( 2133     int2smaller             -                               95              21              _null_ ));
-DATA(insert ( 2134     oidsmaller              -                               609             26              _null_ ));
-DATA(insert ( 2135     float4smaller   -                               622             700             _null_ ));
-DATA(insert ( 2136     float8smaller   -                               672             701             _null_ ));
-DATA(insert ( 2137     int4smaller             -                               562             702             _null_ ));
-DATA(insert ( 2138     date_smaller    -                               1095    1082    _null_ ));
-DATA(insert ( 2139     time_smaller    -                               1110    1083    _null_ ));
-DATA(insert ( 2140     timetz_smaller  -                               1552    1266    _null_ ));
-DATA(insert ( 2141     cashsmaller             -                               902             790             _null_ ));
-DATA(insert ( 2142     timestamp_smaller       -                       2062    1114    _null_ ));
-DATA(insert ( 2143     timestamptz_smaller -                   1322    1184    _null_ ));
-DATA(insert ( 2144     interval_smaller        -                       1332    1186    _null_ ));
-DATA(insert ( 2145     text_smaller    -                               664             25              _null_ ));
-DATA(insert ( 2146     numeric_smaller -                               1754    1700    _null_ ));
-DATA(insert ( 2051     array_smaller   -                               1072    2277    _null_ ));
-DATA(insert ( 2245     bpchar_smaller  -                               1058    1042    _null_ ));
-DATA(insert ( 2798     tidsmaller              -                               2799    27              _null_ ));
-DATA(insert ( 3527     enum_smaller    -                               3518    3500    _null_ ));
+DATA(insert ( 2131     int8smaller             -                               412             20              0       _null_ ));
+DATA(insert ( 2132     int4smaller             -                               97              23              0       _null_ ));
+DATA(insert ( 2133     int2smaller             -                               95              21              0       _null_ ));
+DATA(insert ( 2134     oidsmaller              -                               609             26              0       _null_ ));
+DATA(insert ( 2135     float4smaller   -                               622             700             0       _null_ ));
+DATA(insert ( 2136     float8smaller   -                               672             701             0       _null_ ));
+DATA(insert ( 2137     int4smaller             -                               562             702             0       _null_ ));
+DATA(insert ( 2138     date_smaller    -                               1095    1082    0       _null_ ));
+DATA(insert ( 2139     time_smaller    -                               1110    1083    0       _null_ ));
+DATA(insert ( 2140     timetz_smaller  -                               1552    1266    0       _null_ ));
+DATA(insert ( 2141     cashsmaller             -                               902             790             0       _null_ ));
+DATA(insert ( 2142     timestamp_smaller       -                       2062    1114    0       _null_ ));
+DATA(insert ( 2143     timestamptz_smaller -                   1322    1184    0       _null_ ));
+DATA(insert ( 2144     interval_smaller        -                       1332    1186    0       _null_ ));
+DATA(insert ( 2145     text_smaller    -                               664             25              0       _null_ ));
+DATA(insert ( 2146     numeric_smaller -                               1754    1700    0       _null_ ));
+DATA(insert ( 2051     array_smaller   -                               1072    2277    0       _null_ ));
+DATA(insert ( 2245     bpchar_smaller  -                               1058    1042    0       _null_ ));
+DATA(insert ( 2798     tidsmaller              -                               2799    27              0       _null_ ));
+DATA(insert ( 3527     enum_smaller    -                               3518    3500    0       _null_ ));
 
 /* count */
-DATA(insert ( 2147     int8inc_any             -                               0               20              "0" ));
-DATA(insert ( 2803     int8inc                 -                               0               20              "0" ));
+DATA(insert ( 2147     int8inc_any             -                               0               20              0       "0" ));
+DATA(insert ( 2803     int8inc                 -                               0               20              0       "0" ));
 
 /* var_pop */
-DATA(insert ( 2718     int8_accum      numeric_var_pop 0       1231    "{0,0,0}" ));
-DATA(insert ( 2719     int4_accum      numeric_var_pop 0       1231    "{0,0,0}" ));
-DATA(insert ( 2720     int2_accum      numeric_var_pop 0       1231    "{0,0,0}" ));
-DATA(insert ( 2721     float4_accum    float8_var_pop 0        1022    "{0,0,0}" ));
-DATA(insert ( 2722     float8_accum    float8_var_pop 0        1022    "{0,0,0}" ));
-DATA(insert ( 2723     numeric_accum  numeric_var_pop 0        1231    "{0,0,0}" ));
+DATA(insert ( 2718     int8_accum      numeric_var_pop 0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2719     int4_accum      numeric_var_pop 0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2720     int2_accum      numeric_var_pop 0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2721     float4_accum    float8_var_pop 0        1022    0       "{0,0,0}" ));
+DATA(insert ( 2722     float8_accum    float8_var_pop 0        1022    0       "{0,0,0}" ));
+DATA(insert ( 2723     numeric_accum  numeric_var_pop 0        1231    0       "{0,0,0}" ));
 
 /* var_samp */
-DATA(insert ( 2641     int8_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2642     int4_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2643     int2_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2644     float4_accum    float8_var_samp 0       1022    "{0,0,0}" ));
-DATA(insert ( 2645     float8_accum    float8_var_samp 0       1022    "{0,0,0}" ));
-DATA(insert ( 2646     numeric_accum  numeric_var_samp 0       1231    "{0,0,0}" ));
+DATA(insert ( 2641     int8_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2642     int4_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2643     int2_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2644     float4_accum    float8_var_samp 0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2645     float8_accum    float8_var_samp 0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2646     numeric_accum  numeric_var_samp 0       1231    0       "{0,0,0}" ));
 
 /* variance: historical Postgres syntax for var_samp */
-DATA(insert ( 2148     int8_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2149     int4_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2150     int2_accum      numeric_var_samp        0       1231    "{0,0,0}" ));
-DATA(insert ( 2151     float4_accum    float8_var_samp 0       1022    "{0,0,0}" ));
-DATA(insert ( 2152     float8_accum    float8_var_samp 0       1022    "{0,0,0}" ));
-DATA(insert ( 2153     numeric_accum  numeric_var_samp 0       1231    "{0,0,0}" ));
+DATA(insert ( 2148     int8_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2149     int4_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2150     int2_accum      numeric_var_samp        0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2151     float4_accum    float8_var_samp 0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2152     float8_accum    float8_var_samp 0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2153     numeric_accum  numeric_var_samp 0       1231    0       "{0,0,0}" ));
 
 /* stddev_pop */
-DATA(insert ( 2724     int8_accum      numeric_stddev_pop              0       1231    "{0,0,0}" ));
-DATA(insert ( 2725     int4_accum      numeric_stddev_pop              0       1231    "{0,0,0}" ));
-DATA(insert ( 2726     int2_accum      numeric_stddev_pop              0       1231    "{0,0,0}" ));
-DATA(insert ( 2727     float4_accum    float8_stddev_pop       0       1022    "{0,0,0}" ));
-DATA(insert ( 2728     float8_accum    float8_stddev_pop       0       1022    "{0,0,0}" ));
-DATA(insert ( 2729     numeric_accum   numeric_stddev_pop      0       1231    "{0,0,0}" ));
+DATA(insert ( 2724     int8_accum      numeric_stddev_pop              0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2725     int4_accum      numeric_stddev_pop              0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2726     int2_accum      numeric_stddev_pop              0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2727     float4_accum    float8_stddev_pop       0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2728     float8_accum    float8_stddev_pop       0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2729     numeric_accum   numeric_stddev_pop      0       1231    0       "{0,0,0}" ));
 
 /* stddev_samp */
-DATA(insert ( 2712     int8_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2713     int4_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2714     int2_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2715     float4_accum    float8_stddev_samp      0       1022    "{0,0,0}" ));
-DATA(insert ( 2716     float8_accum    float8_stddev_samp      0       1022    "{0,0,0}" ));
-DATA(insert ( 2717     numeric_accum   numeric_stddev_samp 0   1231    "{0,0,0}" ));
+DATA(insert ( 2712     int8_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2713     int4_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2714     int2_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2715     float4_accum    float8_stddev_samp      0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2716     float8_accum    float8_stddev_samp      0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2717     numeric_accum   numeric_stddev_samp 0   1231    0       "{0,0,0}" ));
 
 /* stddev: historical Postgres syntax for stddev_samp */
-DATA(insert ( 2154     int8_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2155     int4_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2156     int2_accum      numeric_stddev_samp             0       1231    "{0,0,0}" ));
-DATA(insert ( 2157     float4_accum    float8_stddev_samp      0       1022    "{0,0,0}" ));
-DATA(insert ( 2158     float8_accum    float8_stddev_samp      0       1022    "{0,0,0}" ));
-DATA(insert ( 2159     numeric_accum   numeric_stddev_samp 0   1231    "{0,0,0}" ));
+DATA(insert ( 2154     int8_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2155     int4_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2156     int2_accum      numeric_stddev_samp             0       1231    0       "{0,0,0}" ));
+DATA(insert ( 2157     float4_accum    float8_stddev_samp      0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2158     float8_accum    float8_stddev_samp      0       1022    0       "{0,0,0}" ));
+DATA(insert ( 2159     numeric_accum   numeric_stddev_samp 0   1231    0       "{0,0,0}" ));
 
 /* SQL2003 binary regression aggregates */
-DATA(insert ( 2818     int8inc_float8_float8           -                               0       20              "0" ));
-DATA(insert ( 2819     float8_regr_accum       float8_regr_sxx                 0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2820     float8_regr_accum       float8_regr_syy                 0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2821     float8_regr_accum       float8_regr_sxy                 0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2822     float8_regr_accum       float8_regr_avgx                0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2823     float8_regr_accum       float8_regr_avgy                0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2824     float8_regr_accum       float8_regr_r2                  0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2825     float8_regr_accum       float8_regr_slope               0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2826     float8_regr_accum       float8_regr_intercept   0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2827     float8_regr_accum       float8_covar_pop                0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2828     float8_regr_accum       float8_covar_samp               0       1022    "{0,0,0,0,0,0}" ));
-DATA(insert ( 2829     float8_regr_accum       float8_corr                             0       1022    "{0,0,0,0,0,0}" ));
+DATA(insert ( 2818     int8inc_float8_float8           -                               0       20              0       "0" ));
+DATA(insert ( 2819     float8_regr_accum       float8_regr_sxx                 0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2820     float8_regr_accum       float8_regr_syy                 0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2821     float8_regr_accum       float8_regr_sxy                 0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2822     float8_regr_accum       float8_regr_avgx                0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2823     float8_regr_accum       float8_regr_avgy                0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2824     float8_regr_accum       float8_regr_r2                  0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2825     float8_regr_accum       float8_regr_slope               0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2826     float8_regr_accum       float8_regr_intercept   0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2827     float8_regr_accum       float8_covar_pop                0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2828     float8_regr_accum       float8_covar_samp               0       1022    0       "{0,0,0,0,0,0}" ));
+DATA(insert ( 2829     float8_regr_accum       float8_corr                             0       1022    0       "{0,0,0,0,0,0}" ));
 
 /* boolean-and and boolean-or */
-DATA(insert ( 2517     booland_statefunc       -                       58      16              _null_ ));
-DATA(insert ( 2518     boolor_statefunc        -                       59      16              _null_ ));
-DATA(insert ( 2519     booland_statefunc       -                       58      16              _null_ ));
+DATA(insert ( 2517     booland_statefunc       -                       58      16              0       _null_ ));
+DATA(insert ( 2518     boolor_statefunc        -                       59      16              0       _null_ ));
+DATA(insert ( 2519     booland_statefunc       -                       58      16              0       _null_ ));
 
 /* bitwise integer */
-DATA(insert ( 2236 int2and               -                                     0       21              _null_ ));
-DATA(insert ( 2237 int2or                -                                     0       21              _null_ ));
-DATA(insert ( 2238 int4and               -                                     0       23              _null_ ));
-DATA(insert ( 2239 int4or                -                                     0       23              _null_ ));
-DATA(insert ( 2240 int8and               -                                     0       20              _null_ ));
-DATA(insert ( 2241 int8or                -                                     0       20              _null_ ));
-DATA(insert ( 2242 bitand                -                                     0       1560    _null_ ));
-DATA(insert ( 2243 bitor                 -                                     0       1560    _null_ ));
+DATA(insert ( 2236 int2and               -                                     0       21              0       _null_ ));
+DATA(insert ( 2237 int2or                -                                     0       21              0       _null_ ));
+DATA(insert ( 2238 int4and               -                                     0       23              0       _null_ ));
+DATA(insert ( 2239 int4or                -                                     0       23              0       _null_ ));
+DATA(insert ( 2240 int8and               -                                     0       20              0       _null_ ));
+DATA(insert ( 2241 int8or                -                                     0       20              0       _null_ ));
+DATA(insert ( 2242 bitand                -                                     0       1560    0       _null_ ));
+DATA(insert ( 2243 bitor                 -                                     0       1560    0       _null_ ));
 
 /* xml */
-DATA(insert ( 2901 xmlconcat2    -                                     0       142             _null_ ));
+DATA(insert ( 2901 xmlconcat2    -                                     0       142             0       _null_ ));
 
 /* array */
-DATA(insert ( 2335     array_agg_transfn       array_agg_finalfn               0       2281    _null_ ));
+DATA(insert ( 2335     array_agg_transfn       array_agg_finalfn       0       2281    0       _null_ ));
 
 /* text */
-DATA(insert ( 3538     string_agg_transfn      string_agg_finalfn              0       2281    _null_ ));
+DATA(insert ( 3538     string_agg_transfn      string_agg_finalfn      0       2281    0       _null_ ));
 
 /* bytea */
-DATA(insert ( 3545     bytea_string_agg_transfn        bytea_string_agg_finalfn                0       2281    _null_ ));
+DATA(insert ( 3545     bytea_string_agg_transfn        bytea_string_agg_finalfn        0       2281    0       _null_ ));
 
 /* json */
-DATA(insert ( 3175     json_agg_transfn        json_agg_finalfn                0       2281    _null_ ));
+DATA(insert ( 3175     json_agg_transfn        json_agg_finalfn        0       2281    0       _null_ ));
 
 /*
  * prototypes for functions in pg_aggregate.c
@@ -250,6 +253,7 @@ extern Oid AggregateCreate(const char *aggName,
                                List *aggfinalfnName,
                                List *aggsortopName,
                                Oid aggTransType,
+                               int32 aggTransSpace,
                                const char *agginitval);
 
 #endif   /* PG_AGGREGATE_H */
index 836c99e97ea5127131491bfe77a2a0dbdf87c8de..f8ceb5da2eb6d7a43469f955ce0dcd46b4d1d350 100644 (file)
@@ -133,6 +133,7 @@ extern Datum transformGenericOptions(Oid catalogId,
 extern char *defGetString(DefElem *def);
 extern double defGetNumeric(DefElem *def);
 extern bool defGetBoolean(DefElem *def);
+extern int32 defGetInt32(DefElem *def);
 extern int64 defGetInt64(DefElem *def);
 extern List *defGetQualifiedName(DefElem *def);
 extern TypeName *defGetTypeName(DefElem *def);
index 6c7566f1728fed6a2547870ba608be64a320bc45..9ecaea149927c04667185f908317b7bf0268e33d 100644 (file)
@@ -56,7 +56,7 @@ create aggregate aggfstr(integer,integer,text) (
    initcond = '{}'
 );
 create aggregate aggfns(integer,integer,text) (
-   sfunc = aggfns_trans, stype = aggtype[],
+   sfunc = aggfns_trans, stype = aggtype[], sspace = 10000,
    initcond = '{}'
 );
 -- variadic aggregate
index 57d614f651702f08e5d9592d422ed2984674aa1d..10d65c0b28720470252b47d6c6b3fae33f50fc7a 100644 (file)
@@ -702,7 +702,7 @@ SELECT * FROM funcdescs
 -- Look for illegal values in pg_aggregate fields.
 SELECT ctid, aggfnoid::oid
 FROM pg_aggregate as p1
-WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0;
+WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0 OR aggtransspace < 0;
  ctid | aggfnoid 
 ------+----------
 (0 rows)
index 3c7d330960ff5f6723e8f1c82c79f61791c7a49c..7ea23de0b6af29ec5803bde2daa07f7cceaa436a 100644 (file)
@@ -68,7 +68,7 @@ create aggregate aggfstr(integer,integer,text) (
 );
 
 create aggregate aggfns(integer,integer,text) (
-   sfunc = aggfns_trans, stype = aggtype[],
+   sfunc = aggfns_trans, stype = aggtype[], sspace = 10000,
    initcond = '{}'
 );
 
index efcd70f03be89a9a49210e722ee3d807a8cc3e1b..1c71c964a5b7e0ce5821d1fa90e8a9545fc83c25 100644 (file)
@@ -567,7 +567,7 @@ SELECT * FROM funcdescs
 
 SELECT ctid, aggfnoid::oid
 FROM pg_aggregate as p1
-WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0;
+WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0 OR aggtransspace < 0;
 
 -- Make sure the matching pg_proc entry is sensible, too.