diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 9388df5ac27..acc261ca516 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -372,6 +372,13 @@
pg_type.oid
Data type of the aggregate function's internal transition (state) data
+
+ aggtransspace
+ int4
+
+ Approximate average size (in bytes) of the transition state
+ data, or zero to use a default estimate
+
agginitval
text
diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml
index 2b35fa4d522..17819dd1a8e 100644
--- a/doc/src/sgml/ref/create_aggregate.sgml
+++ b/doc/src/sgml/ref/create_aggregate.sgml
@@ -24,6 +24,7 @@ PostgreSQL documentation
CREATE AGGREGATE name ( [ argmode ] [ arg_name ] arg_data_type [ , ... ] ) (
SFUNC = sfunc,
STYPE = state_data_type
+ [ , SSPACE = state_data_size ]
[ , FINALFUNC = ffunc ]
[ , INITCOND = initial_condition ]
[ , SORTOP = sort_operator ]
@@ -35,6 +36,7 @@ CREATE AGGREGATE name (
BASETYPE = base_type,
SFUNC = sfunc,
STYPE = state_data_type
+ [ , SSPACE = state_data_size ]
[ , FINALFUNC = ffunc ]
[ , INITCOND = initial_condition ]
[ , SORTOP = sort_operator ]
@@ -264,6 +266,22 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
+
+ state_data_size
+
+
+ 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 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 ; therefore, large values of this
+ parameter discourage use of hash aggregation.
+
+
+
+
ffunc
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index d9e961ebfad..9dbec508a0d 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -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
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 78af0924654..6fc3e045492 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -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 */
}
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 9fa222f5fc0..75f77da2cff 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -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.
*/
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index add29f54d09..7ce8a9d8180 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -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;
+
+ if (numArguments > 0 && aggtranstype == inputTypes[0])
+ aggtranstypmod = exprTypmod((Node *) linitial(aggref->args));
+ else
+ aggtranstypmod = -1;
+
+ avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
+ }
- 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;
}
/*
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 6c16b3ca49e..f81094ee705 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -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, "
- "agginitval, "
+ "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, "
+ "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 = ");
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 4108f6c16c0..cb9021c525a 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201311081
+#define CATALOG_VERSION_NO 201311161
#endif
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 5ad6ea6e3d1..416d651bf0a 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -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 */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 836c99e97ea..f8ceb5da2eb 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -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);
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out
index 6c7566f1728..9ecaea14992 100644
--- a/src/test/regress/expected/create_aggregate.out
+++ b/src/test/regress/expected/create_aggregate.out
@@ -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
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 57d614f6517..10d65c0b287 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -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)
diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql
index 3c7d330960f..7ea23de0b6a 100644
--- a/src/test/regress/sql/create_aggregate.sql
+++ b/src/test/regress/sql/create_aggregate.sql
@@ -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 = '{}'
);
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index efcd70f03be..1c71c964a5b 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -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.