diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 2420c94bc19cdf004fa4cdb2cc718453f5781233..18e5faef5748c763ec022c9d7c128b7717f8fcb3 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -463,12 +463,6 @@ <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry>Data type of the aggregate function's internal transition (state) data</entry> </row> - <row> - <entry><structfield>aggserialtype</structfield></entry> - <entry><type>oid</type></entry> - <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> - <entry>Return data type of the aggregate function's serialization function (zero if none)</entry> - </row> <row> <entry><structfield>aggtransspace</structfield></entry> <entry><type>int4</type></entry> diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml index 3df330393dec93b65e1036545edab4b4beb42532..6dc193199793d5322a951cdb7647dc67b3a50a0e 100644 --- a/doc/src/sgml/ref/create_aggregate.sgml +++ b/doc/src/sgml/ref/create_aggregate.sgml @@ -30,7 +30,6 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ] [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ] - [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] @@ -50,10 +49,6 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC_EXTRA ] - [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] - [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ] - [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ] - [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , HYPOTHETICAL ] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] @@ -72,7 +67,6 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( [ , COMBINEFUNC = <replaceable class="PARAMETER">combinefunc</replaceable> ] [ , SERIALFUNC = <replaceable class="PARAMETER">serialfunc</replaceable> ] [ , DESERIALFUNC = <replaceable class="PARAMETER">deserialfunc</replaceable> ] - [ , SERIALTYPE = <replaceable class="PARAMETER">serialtype</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , MSFUNC = <replaceable class="PARAMETER">msfunc</replaceable> ] [ , MINVFUNC = <replaceable class="PARAMETER">minvfunc</replaceable> ] @@ -255,7 +249,7 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; To be able to create an aggregate function, you must have <literal>USAGE</literal> privilege on the argument types, the state type(s), and the return type, as well as <literal>EXECUTE</literal> - privilege on the transition and final functions. + privilege on the supporting functions. </para> </refsect1> @@ -412,38 +406,51 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; <term><replaceable class="PARAMETER">combinefunc</replaceable></term> <listitem> <para> - The <replaceable class="PARAMETER">combinefunc</replaceable> may - optionally be specified in order to allow the aggregate function to - support partial aggregation. This is a prerequisite to allow the - aggregate to participate in certain optimizations such as parallel - aggregation. + The <replaceable class="PARAMETER">combinefunc</replaceable> function + may optionally be specified to allow the aggregate function to support + partial aggregation. This is a prerequisite to allow the aggregate to + participate in certain optimizations such as parallel aggregation. </para> <para> - This function can be thought of as an <replaceable class="PARAMETER"> - sfunc</replaceable>, where instead of acting upon individual input rows - and adding these to the aggregate state, it adds other aggregate states - to the aggregate state. + If provided, + the <replaceable class="PARAMETER">combinefunc</replaceable> must + combine two <replaceable class="PARAMETER">state_data_type</replaceable> + values, each containing the result of aggregation over some subset of + the input values, to produce a + new <replaceable class="PARAMETER">state_data_type</replaceable> that + represents the result of aggregating over both sets of inputs. This + function can be thought of as + an <replaceable class="PARAMETER">sfunc</replaceable>, where instead of + acting upon individual input rows and adding these to the aggregate + state, it adds another aggregate state to the aggregate state. + Typically, it is not possible to define + a <replaceable class="PARAMETER">combinefunc</replaceable> for aggregate + functions that are sensitive to the order of the input values, since the + relative ordering of the inputs that went into the subset states is + indeterminate. </para> <para> The <replaceable class="PARAMETER">combinefunc</replaceable> must accept - two arguments of <replaceable class="PARAMETER">state_data_type - </replaceable> and return <replaceable class="PARAMETER">state_data_type - </replaceable>. Optionally this function may be <quote>strict</quote>. In - this case the function will not be called when either of the input states - are null. + two arguments of + the <replaceable class="PARAMETER">state_data_type</replaceable> and + return a value of + the <replaceable class="PARAMETER">state_data_type</replaceable>. + Optionally this function may be <quote>strict</quote>. In this case the + function will not be called when either of the input states are null; + the other state will be taken as the correct result. </para> - + <para> - For aggregate functions with an <literal>INTERNAL</literal> - <replaceable class="PARAMETER">state_data_type</replaceable> the - <replaceable class="PARAMETER">combinefunc</replaceable> must not be - <quote>strict</quote>. In this scenario the - <replaceable class="PARAMETER">combinefunc</replaceable> must take charge - and ensure that the null states are handled correctly and that the state - being returned is a pointer to memory which belongs in the aggregate - memory context. + For aggregate functions + whose <replaceable class="PARAMETER">state_data_type</replaceable> + is <type>internal</type>, + the <replaceable class="PARAMETER">combinefunc</replaceable> must not be + strict. In this scenario + the <replaceable class="PARAMETER">combinefunc</replaceable> must ensure + that null states are handled correctly and that the state being returned + is properly stored in the aggregate memory context. </para> </listitem> </varlistentry> @@ -452,14 +459,13 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; <term><replaceable class="PARAMETER">serialfunc</replaceable></term> <listitem> <para> - In order to allow aggregate functions with an <literal>INTERNAL</> - <replaceable class="PARAMETER">state_data_type</replaceable> to - participate in parallel aggregation, the aggregate must have a valid - <replaceable class="PARAMETER">serialfunc</replaceable>, which must - serialize the aggregate state into <replaceable class="PARAMETER"> - serialtype</replaceable>. This function must take a single argument of - <replaceable class="PARAMETER">state_data_type</replaceable> and return - <replaceable class="PARAMETER">serialtype</replaceable>. A + An aggregate function + whose <replaceable class="PARAMETER">state_data_type</replaceable> + is <type>internal</> can participate in parallel aggregation only if it + has a <replaceable class="PARAMETER">serialfunc</replaceable> function, + which must serialize the aggregate state into a <type>bytea</> value for + transmission to another process. This function must take a single + argument of type <type>internal</> and return type <type>bytea</>. A corresponding <replaceable class="PARAMETER">deserialfunc</replaceable> is also required. </para> @@ -470,21 +476,12 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; <term><replaceable class="PARAMETER">deserialfunc</replaceable></term> <listitem> <para> - Deserializes a previously serialized aggregate state back into + Deserialize a previously serialized aggregate state back into <replaceable class="PARAMETER">state_data_type</replaceable>. This - function must take a single argument of <replaceable class="PARAMETER"> - serialtype</replaceable> and return <replaceable class="PARAMETER"> - state_data_type</replaceable>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><replaceable class="PARAMETER">serialtype</replaceable></term> - <listitem> - <para> - The data type to into which an <literal>INTERNAL</literal> aggregate - state should be serialized. + function must take two arguments of types <type>bytea</> + and <type>internal</>, and produce a result of type <type>internal</>. + (Note: the second, <type>internal</> argument is unused, but is required + for type safety reasons.) </para> </listitem> </varlistentry> diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 73d19ec3947ae330d64c0d29f1f94f08a294ffe6..959d3845df217455815c6c0e4c4f85b06ada486f 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -67,7 +67,6 @@ AggregateCreate(const char *aggName, bool mfinalfnExtraArgs, List *aggsortopName, Oid aggTransType, - Oid aggSerialType, int32 aggTransSpace, Oid aggmTransType, int32 aggmTransSpace, @@ -440,44 +439,42 @@ AggregateCreate(const char *aggName, } /* - * Validate the serialization function, if present. We must ensure that - * the return type of this function is the same as the specified - * serialType. + * Validate the serialization function, if present. */ if (aggserialfnName) { - fnArgs[0] = aggTransType; + fnArgs[0] = INTERNALOID; serialfn = lookup_agg_function(aggserialfnName, 1, fnArgs, variadicArgType, &rettype); - if (rettype != aggSerialType) + if (rettype != BYTEAOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("return type of serialization function %s is not %s", NameListToString(aggserialfnName), - format_type_be(aggSerialType)))); + format_type_be(BYTEAOID)))); } /* - * Validate the deserialization function, if present. We must ensure that - * the return type of this function is the same as the transType. + * Validate the deserialization function, if present. */ if (aggdeserialfnName) { - fnArgs[0] = aggSerialType; + fnArgs[0] = BYTEAOID; + fnArgs[1] = INTERNALOID; /* dummy argument for type safety */ - deserialfn = lookup_agg_function(aggdeserialfnName, 1, + deserialfn = lookup_agg_function(aggdeserialfnName, 2, fnArgs, variadicArgType, &rettype); - if (rettype != aggTransType) + if (rettype != INTERNALOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("return type of deserialization function %s is not %s", NameListToString(aggdeserialfnName), - format_type_be(aggTransType)))); + format_type_be(INTERNALOID)))); } /* @@ -661,7 +658,6 @@ AggregateCreate(const char *aggName, values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs); values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop); values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType); - values[Anum_pg_aggregate_aggserialtype - 1] = ObjectIdGetDatum(aggSerialType); values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace); values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType); values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace); @@ -688,8 +684,7 @@ AggregateCreate(const char *aggName, * Create dependencies for the aggregate (above and beyond those already * made by ProcedureCreate). Note: we don't need an explicit dependency * on aggTransType since we depend on it indirectly through transfn. - * Likewise for aggmTransType using the mtransfunc, and also for - * aggSerialType using the serialfn, if they exist. + * Likewise for aggmTransType using the mtransfunc, if it exists. */ /* Depends on transition function */ diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index f1fdc1a36037247eeaa546bdff25a9f17bb45502..d34c82c5baf7134d9f991dc64ff2bd838fc7eb92 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -72,7 +72,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, List *sortoperatorName = NIL; TypeName *baseType = NULL; TypeName *transType = NULL; - TypeName *serialType = NULL; TypeName *mtransType = NULL; int32 transSpace = 0; int32 mtransSpace = 0; @@ -88,7 +87,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, List *parameterDefaults; Oid variadicArgType; Oid transTypeId; - Oid serialTypeId = InvalidOid; Oid mtransTypeId = InvalidOid; char transTypeType; char mtransTypeType = 0; @@ -164,8 +162,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, } else if (pg_strcasecmp(defel->defname, "stype") == 0) transType = defGetTypeName(defel); - else if (pg_strcasecmp(defel->defname, "serialtype") == 0) - serialType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "stype1") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "sspace") == 0) @@ -333,73 +329,25 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, format_type_be(transTypeId)))); } - if (serialType) + if (serialfuncName && deserialfuncName) { /* - * There's little point in having a serialization/deserialization - * function on aggregates that don't have an internal state, so let's - * just disallow this as it may help clear up any confusion or - * needless authoring of these functions. + * Serialization is only needed/allowed for transtype INTERNAL. */ if (transTypeId != INTERNALOID) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("a serialization type must only be specified when the aggregate transition data type is %s", + errmsg("serialization functions may be specified only when the aggregate transition data type is %s", format_type_be(INTERNALOID)))); - - serialTypeId = typenameTypeId(NULL, serialType); - - if (get_typtype(mtransTypeId) == TYPTYPE_PSEUDO && - !IsPolymorphicType(serialTypeId)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate serialization data type cannot be %s", - format_type_be(serialTypeId)))); - - /* - * We disallow INTERNAL serialType as the whole point of the - * serialized types is to allow the aggregate state to be output, and - * we cannot output INTERNAL. This check, combined with the one above - * ensures that the trans type and serialization type are not the - * same. - */ - if (serialTypeId == INTERNALOID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate serialization data type cannot be %s", - format_type_be(serialTypeId)))); - - /* - * If serialType is specified then serialfuncName and deserialfuncName - * must be present; if not, then none of the serialization options - * should have been specified. - */ - if (serialfuncName == NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate serialization function must be specified when serialization type is specified"))); - - if (deserialfuncName == NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate deserialization function must be specified when serialization type is specified"))); } - else + else if (serialfuncName || deserialfuncName) { /* - * If serialization type was not specified then there shouldn't be a - * serialization function. + * Cannot specify one function without the other. */ - if (serialfuncName != NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("must specify serialization type when specifying serialization function"))); - - /* likewise for the deserialization function */ - if (deserialfuncName != NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("must specify serialization type when specifying deserialization function"))); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("must specify both or neither of serialization and deserialization functions"))); } /* @@ -493,7 +441,6 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, mfinalfuncExtraArgs, sortoperatorName, /* sort operator name */ transTypeId, /* transition data type */ - serialTypeId, /* serialization data type */ transSpace, /* transition space */ mtransTypeId, /* transition data type */ mtransSpace, /* transition space */ diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 7b282dec7dae9ff489e45d4b6ea32a1322fda92e..a44796461299856b99817a62ef8fff4206ee1c78 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -514,10 +514,9 @@ static Datum GetAggInitVal(Datum textInitVal, Oid transtype); static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggsate, EState *estate, Aggref *aggref, Oid aggtransfn, Oid aggtranstype, - Oid aggserialtype, Oid aggserialfn, - Oid aggdeserialfn, Datum initValue, - bool initValueIsNull, Oid *inputTypes, - int numArguments); + Oid aggserialfn, Oid aggdeserialfn, + Datum initValue, bool initValueIsNull, + Oid *inputTypes, int numArguments); static int find_compatible_peragg(Aggref *newagg, AggState *aggstate, int lastaggno, List **same_input_transnos); static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, @@ -996,6 +995,9 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup) dsinfo->arg[0] = slot->tts_values[0]; dsinfo->argnull[0] = slot->tts_isnull[0]; + /* Dummy second argument for type-safety reasons */ + dsinfo->arg[1] = PointerGetDatum(NULL); + dsinfo->argnull[1] = false; /* * We run the deserialization functions in per-input-tuple @@ -2669,8 +2671,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) AclResult aclresult; Oid transfn_oid, finalfn_oid; - Oid serialtype_oid, - serialfn_oid, + Oid serialfn_oid, deserialfn_oid; Expr *finalfnexpr; Oid aggtranstype; @@ -2740,7 +2741,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) else peragg->finalfn_oid = finalfn_oid = InvalidOid; - serialtype_oid = InvalidOid; serialfn_oid = InvalidOid; deserialfn_oid = InvalidOid; @@ -2753,13 +2753,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) { /* * The planner should only have generated an agg node with - * serialStates if every aggregate with an INTERNAL state has a - * serialization type, serialization function and deserialization - * function. Let's ensure it didn't mess that up. + * serialStates if every aggregate with an INTERNAL state has + * serialization/deserialization functions. Verify that. */ - if (!OidIsValid(aggform->aggserialtype)) - elog(ERROR, "serialtype not set during serialStates aggregation step"); - if (!OidIsValid(aggform->aggserialfn)) elog(ERROR, "serialfunc not set during serialStates aggregation step"); @@ -2768,17 +2764,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) /* serialization func only required when not finalizing aggs */ if (!aggstate->finalizeAggs) - { serialfn_oid = aggform->aggserialfn; - serialtype_oid = aggform->aggserialtype; - } /* deserialization func only required when combining states */ if (aggstate->combineStates) - { deserialfn_oid = aggform->aggdeserialfn; - serialtype_oid = aggform->aggserialtype; - } } /* Check that aggregate owner has permission to call component fns */ @@ -2906,10 +2896,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) pertrans = &pertransstates[++transno]; build_pertrans_for_aggref(pertrans, aggstate, estate, aggref, transfn_oid, aggtranstype, - serialtype_oid, serialfn_oid, - deserialfn_oid, initValue, - initValueIsNull, inputTypes, - numArguments); + serialfn_oid, deserialfn_oid, + initValue, initValueIsNull, + inputTypes, numArguments); peragg->transno = transno; } ReleaseSysCache(aggTuple); @@ -2937,7 +2926,7 @@ static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggstate, EState *estate, Aggref *aggref, - Oid aggtransfn, Oid aggtranstype, Oid aggserialtype, + Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments) @@ -3065,10 +3054,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, if (OidIsValid(aggserialfn)) { - build_aggregate_serialfn_expr(aggtranstype, - aggserialtype, - aggref->inputcollid, - aggserialfn, + build_aggregate_serialfn_expr(aggserialfn, &serialfnexpr); fmgr_info(aggserialfn, &pertrans->serialfn); fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn); @@ -3076,24 +3062,21 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, InitFunctionCallInfoData(pertrans->serialfn_fcinfo, &pertrans->serialfn, 1, - pertrans->aggCollation, + InvalidOid, (void *) aggstate, NULL); } if (OidIsValid(aggdeserialfn)) { - build_aggregate_serialfn_expr(aggserialtype, - aggtranstype, - aggref->inputcollid, - aggdeserialfn, - &deserialfnexpr); + build_aggregate_deserialfn_expr(aggdeserialfn, + &deserialfnexpr); fmgr_info(aggdeserialfn, &pertrans->deserialfn); fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn); InitFunctionCallInfoData(pertrans->deserialfn_fcinfo, &pertrans->deserialfn, - 1, - pertrans->aggCollation, + 2, + InvalidOid, (void *) aggstate, NULL); } diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 0e738c1ccc098c0b7b1fa387c5b7c288cf6049fc..7138cad31d82452dc0b7aed9b9414919b258008c 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -465,13 +465,11 @@ aggregates_allow_partial_walker(Node *node, partial_agg_context *context) /* * If we find any aggs with an internal transtype then we must check - * that these have a serialization type, serialization func and - * deserialization func; otherwise, we set the maximum allowed type to - * PAT_INTERNAL_ONLY. + * whether these have serialization/deserialization functions; + * otherwise, we set the maximum allowed type to PAT_INTERNAL_ONLY. */ if (aggform->aggtranstype == INTERNALOID && - (!OidIsValid(aggform->aggserialtype) || - !OidIsValid(aggform->aggserialfn) || + (!OidIsValid(aggform->aggserialfn) || !OidIsValid(aggform->aggdeserialfn))) context->allowedtype = PAT_INTERNAL_ONLY; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index de0a8c7b57fff1f9d96d44919ce0db5b4fbbfb5c..5fa80ac51be7dce19f5e3011ee74c82f9b2b4de6 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -15,7 +15,7 @@ #include "postgres.h" #include "access/htup_details.h" -#include "catalog/pg_aggregate.h" +#include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/tlist.h" @@ -766,8 +766,8 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target) /* * apply_partialaggref_adjustment * Convert PathTarget to be suitable for a partial aggregate node. We simply - * adjust any Aggref nodes found in the target and set the aggoutputtype to - * the aggtranstype or aggserialtype. This allows exprType() to return the + * adjust any Aggref nodes found in the target and set the aggoutputtype + * appropriately. This allows exprType() to return the * actual type that will be produced. * * Note: We expect 'target' to be a flat target list and not have Aggrefs buried @@ -784,40 +784,29 @@ apply_partialaggref_adjustment(PathTarget *target) if (IsA(aggref, Aggref)) { - HeapTuple aggTuple; - Form_pg_aggregate aggform; Aggref *newaggref; - aggTuple = SearchSysCache1(AGGFNOID, - ObjectIdGetDatum(aggref->aggfnoid)); - if (!HeapTupleIsValid(aggTuple)) - elog(ERROR, "cache lookup failed for aggregate %u", - aggref->aggfnoid); - aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); - newaggref = (Aggref *) copyObject(aggref); /* - * Use the serialization type, if one exists. Note that we don't - * support it being a polymorphic type. (XXX really we ought to - * hardwire this as INTERNAL -> BYTEA, and avoid a catalog lookup - * here altogether?) + * Normally, a partial aggregate returns the aggregate's + * transition type, but if that's INTERNAL, it returns BYTEA + * instead. (XXX this assumes we're doing parallel aggregate with + * serialization; later we might need an argument to tell this + * function whether we're doing parallel or just local partial + * aggregation.) */ - if (OidIsValid(aggform->aggserialtype)) - newaggref->aggoutputtype = aggform->aggserialtype; + Assert(OidIsValid(newaggref->aggtranstype)); + + if (newaggref->aggtranstype == INTERNALOID) + newaggref->aggoutputtype = BYTEAOID; else - { - /* Otherwise, we return the aggregate's transition type */ - Assert(OidIsValid(newaggref->aggtranstype)); newaggref->aggoutputtype = newaggref->aggtranstype; - } /* flag it as partial */ newaggref->aggpartial = true; lfirst(lc) = newaggref; - - ReleaseSysCache(aggTuple); } } } diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index b9ca066698ef916058d47c054e56cac12384d7f5..481a4ddc4847d49d73bef4181a891210248e7721 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -71,6 +71,8 @@ static bool finalize_grouping_exprs_walker(Node *node, check_ungrouped_columns_context *context); static void check_agglevels_and_constraints(ParseState *pstate, Node *expr); static List *expand_groupingset_node(GroupingSet *gs); +static Node *make_agg_arg(Oid argtype, Oid argcollation); + /* * transformAggregateCall - @@ -1863,37 +1865,19 @@ build_aggregate_transfn_expr(Oid *agg_input_types, Expr **transfnexpr, Expr **invtransfnexpr) { - Param *argp; List *args; FuncExpr *fexpr; int i; /* - * Build arg list to use in the transfn FuncExpr node. We really only care - * that transfn can discover the actual argument types at runtime using - * get_fn_expr_argtype(), so it's okay to use Param nodes that don't - * correspond to any real Param. + * Build arg list to use in the transfn FuncExpr node. */ - argp = makeNode(Param); - argp->paramkind = PARAM_EXEC; - argp->paramid = -1; - argp->paramtype = agg_state_type; - argp->paramtypmod = -1; - argp->paramcollid = agg_input_collation; - argp->location = -1; - - args = list_make1(argp); + args = list_make1(make_agg_arg(agg_state_type, agg_input_collation)); for (i = agg_num_direct_inputs; 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); + args = lappend(args, + make_agg_arg(agg_input_types[i], agg_input_collation)); } fexpr = makeFuncExpr(transfn_oid, @@ -1936,20 +1920,13 @@ build_aggregate_combinefn_expr(Oid agg_state_type, Oid combinefn_oid, Expr **combinefnexpr) { - Param *argp; + Node *argp; List *args; FuncExpr *fexpr; - /* Build arg list to use in the combinefn FuncExpr node. */ - argp = makeNode(Param); - argp->paramkind = PARAM_EXEC; - argp->paramid = -1; - argp->paramtype = agg_state_type; - argp->paramtypmod = -1; - argp->paramcollid = agg_input_collation; - argp->location = -1; + /* combinefn takes two arguments of the aggregate state type */ + argp = make_agg_arg(agg_state_type, agg_input_collation); - /* transition state type is arg 1 and 2 */ args = list_make2(argp, argp); fexpr = makeFuncExpr(combinefn_oid, @@ -1958,49 +1935,57 @@ build_aggregate_combinefn_expr(Oid agg_state_type, InvalidOid, agg_input_collation, COERCE_EXPLICIT_CALL); - fexpr->funcvariadic = false; + /* combinefn is currently never treated as variadic */ *combinefnexpr = (Expr *) fexpr; } /* * Like build_aggregate_transfn_expr, but creates an expression tree for the - * serialization or deserialization function of an aggregate, rather than the - * transition function. This may be used for either the serialization or - * deserialization function by swapping the first two parameters over. + * serialization function of an aggregate. */ void -build_aggregate_serialfn_expr(Oid agg_input_type, - Oid agg_output_type, - Oid agg_input_collation, - Oid serialfn_oid, +build_aggregate_serialfn_expr(Oid serialfn_oid, Expr **serialfnexpr) { - Param *argp; List *args; FuncExpr *fexpr; - /* Build arg list to use in the FuncExpr node. */ - argp = makeNode(Param); - argp->paramkind = PARAM_EXEC; - argp->paramid = -1; - argp->paramtype = agg_input_type; - argp->paramtypmod = -1; - argp->paramcollid = agg_input_collation; - argp->location = -1; - - /* takes a single arg of the agg_input_type */ - args = list_make1(argp); + /* serialfn always takes INTERNAL and returns BYTEA */ + args = list_make1(make_agg_arg(INTERNALOID, InvalidOid)); fexpr = makeFuncExpr(serialfn_oid, - agg_output_type, + BYTEAOID, args, InvalidOid, - agg_input_collation, + InvalidOid, COERCE_EXPLICIT_CALL); - fexpr->funcvariadic = false; *serialfnexpr = (Expr *) fexpr; } +/* + * Like build_aggregate_transfn_expr, but creates an expression tree for the + * deserialization function of an aggregate. + */ +void +build_aggregate_deserialfn_expr(Oid deserialfn_oid, + Expr **deserialfnexpr) +{ + List *args; + FuncExpr *fexpr; + + /* deserialfn always takes BYTEA, INTERNAL and returns INTERNAL */ + args = list_make2(make_agg_arg(BYTEAOID, InvalidOid), + make_agg_arg(INTERNALOID, InvalidOid)); + + fexpr = makeFuncExpr(deserialfn_oid, + INTERNALOID, + args, + InvalidOid, + InvalidOid, + COERCE_EXPLICIT_CALL); + *deserialfnexpr = (Expr *) fexpr; +} + /* * Like build_aggregate_transfn_expr, but creates an expression tree for the * final function of an aggregate, rather than the transition function. @@ -2014,33 +1999,19 @@ build_aggregate_finalfn_expr(Oid *agg_input_types, Oid finalfn_oid, Expr **finalfnexpr) { - Param *argp; List *args; int i; /* * Build expr tree for final function */ - argp = makeNode(Param); - argp->paramkind = PARAM_EXEC; - argp->paramid = -1; - argp->paramtype = agg_state_type; - argp->paramtypmod = -1; - argp->paramcollid = agg_input_collation; - argp->location = -1; - args = list_make1(argp); + args = list_make1(make_agg_arg(agg_state_type, agg_input_collation)); /* finalfn may take additional args, which match agg's input types */ for (i = 0; i < num_finalfn_inputs - 1; 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); + args = lappend(args, + make_agg_arg(agg_input_types[i], agg_input_collation)); } *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid, @@ -2051,3 +2022,24 @@ build_aggregate_finalfn_expr(Oid *agg_input_types, COERCE_EXPLICIT_CALL); /* finalfn is currently never treated as variadic */ } + +/* + * Convenience function to build dummy argument expressions for aggregates. + * + * We really only care that an aggregate support function can discover its + * actual argument types at runtime using get_fn_expr_argtype(), so it's okay + * to use Param nodes that don't correspond to any real Param. + */ +static Node * +make_agg_arg(Oid argtype, Oid argcollation) +{ + Param *argp = makeNode(Param); + + argp->paramkind = PARAM_EXEC; + argp->paramid = -1; + argp->paramtype = argtype; + argp->paramtypmod = -1; + argp->paramcollid = argcollation; + argp->location = -1; + return (Node *) argp; +} diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 6592ef4d2d93cf478bff2202609f8c04776327f5..f0b3b87f4c341c64c16121f810625e0cba6db990 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -3510,10 +3510,7 @@ numeric_avg_combine(PG_FUNCTION_ARGS) /* * numeric_avg_serialize * Serialize NumericAggState for numeric aggregates that don't require - * sumX2. Serializes NumericAggState into bytea using the standard pq API. - * - * numeric_avg_deserialize(numeric_avg_serialize(state)) must result in a state - * which matches the original input state. + * sumX2. */ Datum numeric_avg_serialize(PG_FUNCTION_ARGS) @@ -3564,17 +3561,13 @@ numeric_avg_serialize(PG_FUNCTION_ARGS) /* * numeric_avg_deserialize - * Deserialize bytea into NumericAggState for numeric aggregates that - * don't require sumX2. Deserializes bytea into NumericAggState using the - * standard pq API. - * - * numeric_avg_serialize(numeric_avg_deserialize(bytea)) must result in a value - * which matches the original bytea value. + * Deserialize bytea into NumericAggState for numeric aggregates that + * don't require sumX2. */ Datum numeric_avg_deserialize(PG_FUNCTION_ARGS) { - bytea *sstate = PG_GETARG_BYTEA_P(0); + bytea *sstate; NumericAggState *result; Datum temp; StringInfoData buf; @@ -3582,6 +3575,8 @@ numeric_avg_deserialize(PG_FUNCTION_ARGS) if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); + sstate = PG_GETARG_BYTEA_P(0); + /* * Copy the bytea into a StringInfo so that we can "receive" it using the * standard pq API. @@ -3619,11 +3614,7 @@ numeric_avg_deserialize(PG_FUNCTION_ARGS) /* * numeric_serialize * Serialization function for NumericAggState for numeric aggregates that - * require sumX2. Serializes NumericAggState into bytea using the standard - * pq API. - * - * numeric_deserialize(numeric_serialize(state)) must result in a state which - * matches the original input state. + * require sumX2. */ Datum numeric_serialize(PG_FUNCTION_ARGS) @@ -3683,16 +3674,12 @@ numeric_serialize(PG_FUNCTION_ARGS) /* * numeric_deserialize * Deserialization function for NumericAggState for numeric aggregates that - * require sumX2. Deserializes bytea into into NumericAggState using the - * standard pq API. - * - * numeric_serialize(numeric_deserialize(bytea)) must result in a value which - * matches the original bytea value. + * require sumX2. */ Datum numeric_deserialize(PG_FUNCTION_ARGS) { - bytea *sstate = PG_GETARG_BYTEA_P(0); + bytea *sstate; NumericAggState *result; Datum temp; StringInfoData buf; @@ -3700,6 +3687,8 @@ numeric_deserialize(PG_FUNCTION_ARGS) if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); + sstate = PG_GETARG_BYTEA_P(0); + /* * Copy the bytea into a StringInfo so that we can "receive" it using the * standard pq API. @@ -3992,11 +3981,8 @@ numeric_poly_combine(PG_FUNCTION_ARGS) /* * numeric_poly_serialize - * Serialize PolyNumAggState into bytea using the standard pq API for - * aggregate functions which require sumX2. - * - * numeric_poly_deserialize(numeric_poly_serialize(state)) must result in a - * state which matches the original input state. + * Serialize PolyNumAggState into bytea for aggregate functions which + * require sumX2. */ Datum numeric_poly_serialize(PG_FUNCTION_ARGS) @@ -4067,16 +4053,13 @@ numeric_poly_serialize(PG_FUNCTION_ARGS) /* * numeric_poly_deserialize - * Deserialize PolyNumAggState from bytea using the standard pq API for - * aggregate functions which require sumX2. - * - * numeric_poly_serialize(numeric_poly_deserialize(bytea)) must result in a - * state which matches the original input state. + * Deserialize PolyNumAggState from bytea for aggregate functions which + * require sumX2. */ Datum numeric_poly_deserialize(PG_FUNCTION_ARGS) { - bytea *sstate = PG_GETARG_BYTEA_P(0); + bytea *sstate; PolyNumAggState *result; Datum sumX; Datum sumX2; @@ -4085,6 +4068,8 @@ numeric_poly_deserialize(PG_FUNCTION_ARGS) if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); + sstate = PG_GETARG_BYTEA_P(0); + /* * Copy the bytea into a StringInfo so that we can "receive" it using the * standard pq API. @@ -4226,9 +4211,6 @@ int8_avg_combine(PG_FUNCTION_ARGS) /* * int8_avg_serialize * Serialize PolyNumAggState into bytea using the standard pq API. - * - * int8_avg_deserialize(int8_avg_serialize(state)) must result in a state which - * matches the original input state. */ Datum int8_avg_serialize(PG_FUNCTION_ARGS) @@ -4286,14 +4268,11 @@ int8_avg_serialize(PG_FUNCTION_ARGS) /* * int8_avg_deserialize * Deserialize bytea back into PolyNumAggState. - * - * int8_avg_serialize(int8_avg_deserialize(bytea)) must result in a value which - * matches the original bytea value. */ Datum int8_avg_deserialize(PG_FUNCTION_ARGS) { - bytea *sstate = PG_GETARG_BYTEA_P(0); + bytea *sstate; PolyNumAggState *result; StringInfoData buf; Datum temp; @@ -4301,6 +4280,8 @@ int8_avg_deserialize(PG_FUNCTION_ARGS) if (!AggCheckCallContext(fcinfo, NULL)) elog(ERROR, "aggregate function called in non-aggregate context"); + sstate = PG_GETARG_BYTEA_P(0); + /* * Copy the bytea into a StringInfo so that we can "receive" it using the * standard pq API. diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 13bfd2cfb934cdf0d769147e7b9657168c768752..08c2b0c7a302961c9548c31bb91445a676938e47 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -13412,7 +13412,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) int i_aggsortop; int i_hypothetical; int i_aggtranstype; - int i_aggserialtype; int i_aggtransspace; int i_aggmtranstype; int i_aggmtransspace; @@ -13434,7 +13433,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) char *aggsortconvop; bool hypothetical; const char *aggtranstype; - const char *aggserialtype; const char *aggtransspace; const char *aggmtranstype; const char *aggmtransspace; @@ -13465,7 +13463,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggfinalextra, aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " - "aggserialtype::pg_catalog.regtype, " "(aggkind = 'h') AS hypothetical, " "aggtransspace, agginitval, " "aggmtransspace, aggminitval, " @@ -13487,7 +13484,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggfinalextra, aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " - "0 AS aggserialtype, " "(aggkind = 'h') AS hypothetical, " "aggtransspace, agginitval, " "aggmtransspace, aggminitval, " @@ -13509,7 +13505,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "0 AS aggmtranstype, false AS aggfinalextra, " "false AS aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " - "0 AS aggserialtype, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -13531,7 +13526,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "0 AS aggmtranstype, false AS aggfinalextra, " "false AS aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " - "0 AS aggserialtype, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -13550,7 +13544,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "0 AS aggmtranstype, false AS aggfinalextra, " "false AS aggmfinalextra, 0 AS aggsortop, " - "0 AS aggserialtype, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -13569,7 +13562,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "0 AS aggmtranstype, false AS aggfinalextra, " "false AS aggmfinalextra, 0 AS aggsortop, " - "0 AS aggserialtype, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -13588,7 +13580,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "0 AS aggmtranstype, false AS aggfinalextra, " "false AS aggmfinalextra, 0 AS aggsortop, " - "0 AS aggserialtype, " "false AS hypothetical, " "0 AS aggtransspace, agginitval1 AS agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -13611,7 +13602,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) i_aggfinalextra = PQfnumber(res, "aggfinalextra"); i_aggmfinalextra = PQfnumber(res, "aggmfinalextra"); i_aggsortop = PQfnumber(res, "aggsortop"); - i_aggserialtype = PQfnumber(res, "aggserialtype"); i_hypothetical = PQfnumber(res, "hypothetical"); i_aggtranstype = PQfnumber(res, "aggtranstype"); i_aggtransspace = PQfnumber(res, "aggtransspace"); @@ -13635,7 +13625,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) aggsortop = PQgetvalue(res, 0, i_aggsortop); hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't'); aggtranstype = PQgetvalue(res, 0, i_aggtranstype); - aggserialtype = PQgetvalue(res, 0, i_aggserialtype); aggtransspace = PQgetvalue(res, 0, i_aggtransspace); aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype); aggmtransspace = PQgetvalue(res, 0, i_aggmtransspace); @@ -13722,20 +13711,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) } if (strcmp(aggcombinefn, "-") != 0) - { appendPQExpBuffer(details, ",\n COMBINEFUNC = %s", aggcombinefn); - } - /* - * CREATE AGGREGATE should ensure we either have all of these, or none of - * them. - */ if (strcmp(aggserialfn, "-") != 0) - { appendPQExpBuffer(details, ",\n SERIALFUNC = %s", aggserialfn); + + if (strcmp(aggdeserialfn, "-") != 0) appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn); - appendPQExpBuffer(details, ",\n SERIALTYPE = %s", aggserialtype); - } if (strcmp(aggmtransfn, "-") != 0) { diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 90bcd1bc254f7b99952f88815a58ed962be19a5a..9c404523d7d75c5b9ad4de83c526d7551297ea61 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201606171 +#define CATALOG_VERSION_NO 201606221 #endif diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 057c88c077e616997571d1929107cf152faca90c..8865bba0103f00e3661a84e0dd79f09dd8b26a98 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -34,8 +34,8 @@ * aggtransfn transition function * aggfinalfn final function (0 if none) * aggcombinefn combine function (0 if none) - * aggserialfn function to convert transtype to serialtype (0 if none) - * aggdeserialfn function to convert serialtype to transtype (0 if none) + * aggserialfn function to convert transtype to bytea (0 if none) + * aggdeserialfn function to convert bytea to transtype (0 if none) * aggmtransfn forward function for moving-aggregate mode (0 if none) * aggminvtransfn inverse function for moving-aggregate mode (0 if none) * aggmfinalfn final function for moving-aggregate mode (0 if none) @@ -45,7 +45,6 @@ * aggtranstype type of aggregate's transition (state) data * aggtransspace estimated size of state data (0 for default estimate) * aggmtranstype type of moving-aggregate state data (0 if none) - * aggserialtype datatype to serialize state to. (0 if none) * aggmtransspace estimated size of moving-agg state (0 for default est) * agginitval initial value for transition state (can be NULL) * aggminitval initial value for moving-agg state (can be NULL) @@ -70,7 +69,6 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS bool aggmfinalextra; Oid aggsortop; Oid aggtranstype; - Oid aggserialtype; int32 aggtransspace; Oid aggmtranstype; int32 aggmtransspace; @@ -93,7 +91,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; * ---------------- */ -#define Natts_pg_aggregate 21 +#define Natts_pg_aggregate 20 #define Anum_pg_aggregate_aggfnoid 1 #define Anum_pg_aggregate_aggkind 2 #define Anum_pg_aggregate_aggnumdirectargs 3 @@ -109,12 +107,11 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; #define Anum_pg_aggregate_aggmfinalextra 13 #define Anum_pg_aggregate_aggsortop 14 #define Anum_pg_aggregate_aggtranstype 15 -#define Anum_pg_aggregate_aggserialtype 16 -#define Anum_pg_aggregate_aggtransspace 17 -#define Anum_pg_aggregate_aggmtranstype 18 -#define Anum_pg_aggregate_aggmtransspace 19 -#define Anum_pg_aggregate_agginitval 20 -#define Anum_pg_aggregate_aggminitval 21 +#define Anum_pg_aggregate_aggtransspace 16 +#define Anum_pg_aggregate_aggmtranstype 17 +#define Anum_pg_aggregate_aggmtransspace 18 +#define Anum_pg_aggregate_agginitval 19 +#define Anum_pg_aggregate_aggminitval 20 /* * Symbolic values for aggkind column. We distinguish normal aggregates @@ -138,184 +135,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; */ /* avg */ -DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_combine - - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int4_avg_combine - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2104 n 0 float4_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2105 n 0 float8_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2106 n 0 interval_accum interval_avg interval_combine - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); +DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_combine - - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int4_avg_combine - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize 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 float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2105 n 0 float8_accum float8_avg float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2106 n 0 interval_accum interval_avg interval_combine - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); /* sum */ -DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2108 n 0 int4_sum - int8pl - - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 0 1016 0 _null_ "{0,0}" )); -DATA(insert ( 2109 n 0 int2_sum - int8pl - - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 0 1016 0 _null_ "{0,0}" )); -DATA(insert ( 2110 n 0 float4pl - float4pl - - - - - f f 0 700 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2111 n 0 float8pl - float8pl - - - - - f f 0 701 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2112 n 0 cash_pl - cash_pl - - cash_pl cash_mi - f f 0 790 0 0 790 0 _null_ _null_ )); -DATA(insert ( 2113 n 0 interval_pl - interval_pl - - interval_pl interval_mi - f f 0 1186 0 0 1186 0 _null_ _null_ )); -DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum int8_avg_combine int8_avg_serialize int8_avg_deserialize int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2108 n 0 int4_sum - int8pl - - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); +DATA(insert ( 2109 n 0 int2_sum - int8pl - - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); +DATA(insert ( 2110 n 0 float4pl - float4pl - - - - - f f 0 700 0 0 0 _null_ _null_ )); +DATA(insert ( 2111 n 0 float8pl - float8pl - - - - - f f 0 701 0 0 0 _null_ _null_ )); +DATA(insert ( 2112 n 0 cash_pl - cash_pl - - cash_pl cash_mi - f f 0 790 0 790 0 _null_ _null_ )); +DATA(insert ( 2113 n 0 interval_pl - interval_pl - - interval_pl interval_mi - f f 0 1186 0 1186 0 _null_ _null_ )); +DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_combine numeric_avg_serialize numeric_avg_deserialize numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); /* max */ -DATA(insert ( 2115 n 0 int8larger - int8larger - - - - - f f 413 20 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2116 n 0 int4larger - int4larger - - - - - f f 521 23 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2117 n 0 int2larger - int2larger - - - - - f f 520 21 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - - - f f 610 26 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2119 n 0 float4larger - float4larger - - - - - f f 623 700 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2120 n 0 float8larger - float8larger - - - - - f f 674 701 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2121 n 0 int4larger - int4larger - - - - - f f 563 702 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2122 n 0 date_larger - date_larger - - - - - f f 1097 1082 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2123 n 0 time_larger - time_larger - - - - - f f 1112 1083 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2124 n 0 timetz_larger - timetz_larger - - - - - f f 1554 1266 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - - - f f 903 790 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2126 n 0 timestamp_larger - timestamp_larger - - - - - f f 2064 1114 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - - - f f 1324 1184 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2128 n 0 interval_larger - interval_larger - - - - - f f 1334 1186 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2129 n 0 text_larger - text_larger - - - - - f f 666 25 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2130 n 0 numeric_larger - numeric_larger - - - - - f f 1756 1700 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2050 n 0 array_larger - array_larger - - - - - f f 1073 2277 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2244 n 0 bpchar_larger - bpchar_larger - - - - - f f 1060 1042 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - - - f f 2800 27 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3526 n 0 enum_larger - enum_larger - - - - - f f 3519 3500 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3564 n 0 network_larger - network_larger - - - - - f f 1205 869 0 0 0 0 _null_ _null_ )); +DATA(insert ( 2115 n 0 int8larger - int8larger - - - - - f f 413 20 0 0 0 _null_ _null_ )); +DATA(insert ( 2116 n 0 int4larger - int4larger - - - - - f f 521 23 0 0 0 _null_ _null_ )); +DATA(insert ( 2117 n 0 int2larger - int2larger - - - - - f f 520 21 0 0 0 _null_ _null_ )); +DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - - - f f 610 26 0 0 0 _null_ _null_ )); +DATA(insert ( 2119 n 0 float4larger - float4larger - - - - - f f 623 700 0 0 0 _null_ _null_ )); +DATA(insert ( 2120 n 0 float8larger - float8larger - - - - - f f 674 701 0 0 0 _null_ _null_ )); +DATA(insert ( 2121 n 0 int4larger - int4larger - - - - - f f 563 702 0 0 0 _null_ _null_ )); +DATA(insert ( 2122 n 0 date_larger - date_larger - - - - - f f 1097 1082 0 0 0 _null_ _null_ )); +DATA(insert ( 2123 n 0 time_larger - time_larger - - - - - f f 1112 1083 0 0 0 _null_ _null_ )); +DATA(insert ( 2124 n 0 timetz_larger - timetz_larger - - - - - f f 1554 1266 0 0 0 _null_ _null_ )); +DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - - - f f 903 790 0 0 0 _null_ _null_ )); +DATA(insert ( 2126 n 0 timestamp_larger - timestamp_larger - - - - - f f 2064 1114 0 0 0 _null_ _null_ )); +DATA(insert ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - - - f f 1324 1184 0 0 0 _null_ _null_ )); +DATA(insert ( 2128 n 0 interval_larger - interval_larger - - - - - f f 1334 1186 0 0 0 _null_ _null_ )); +DATA(insert ( 2129 n 0 text_larger - text_larger - - - - - f f 666 25 0 0 0 _null_ _null_ )); +DATA(insert ( 2130 n 0 numeric_larger - numeric_larger - - - - - f f 1756 1700 0 0 0 _null_ _null_ )); +DATA(insert ( 2050 n 0 array_larger - array_larger - - - - - f f 1073 2277 0 0 0 _null_ _null_ )); +DATA(insert ( 2244 n 0 bpchar_larger - bpchar_larger - - - - - f f 1060 1042 0 0 0 _null_ _null_ )); +DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - - - f f 2800 27 0 0 0 _null_ _null_ )); +DATA(insert ( 3526 n 0 enum_larger - enum_larger - - - - - f f 3519 3500 0 0 0 _null_ _null_ )); +DATA(insert ( 3564 n 0 network_larger - network_larger - - - - - f f 1205 869 0 0 0 _null_ _null_ )); /* min */ -DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - - - f f 412 20 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - - - f f 97 23 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - - - f f 95 21 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - - - f f 609 26 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - - - f f 622 700 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - - - f f 672 701 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - - - f f 562 702 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2138 n 0 date_smaller - date_smaller - - - - - f f 1095 1082 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2139 n 0 time_smaller - time_smaller - - - - - f f 1110 1083 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2140 n 0 timetz_smaller - timetz_smaller - - - - - f f 1552 1266 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - - - f f 902 790 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - - - f f 2062 1114 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - - - f f 1322 1184 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2144 n 0 interval_smaller - interval_smaller - - - - - f f 1332 1186 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2145 n 0 text_smaller - text_smaller - - - - - f f 664 25 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2146 n 0 numeric_smaller - numeric_smaller - - - - - f f 1754 1700 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2051 n 0 array_smaller - array_smaller - - - - - f f 1072 2277 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - - - f f 1058 1042 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - - - f f 2799 27 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3527 n 0 enum_smaller - enum_smaller - - - - - f f 3518 3500 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - - - f f 1203 869 0 0 0 0 _null_ _null_ )); +DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - - - f f 412 20 0 0 0 _null_ _null_ )); +DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - - - f f 97 23 0 0 0 _null_ _null_ )); +DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - - - f f 95 21 0 0 0 _null_ _null_ )); +DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - - - f f 609 26 0 0 0 _null_ _null_ )); +DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - - - f f 622 700 0 0 0 _null_ _null_ )); +DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - - - f f 672 701 0 0 0 _null_ _null_ )); +DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - - - f f 562 702 0 0 0 _null_ _null_ )); +DATA(insert ( 2138 n 0 date_smaller - date_smaller - - - - - f f 1095 1082 0 0 0 _null_ _null_ )); +DATA(insert ( 2139 n 0 time_smaller - time_smaller - - - - - f f 1110 1083 0 0 0 _null_ _null_ )); +DATA(insert ( 2140 n 0 timetz_smaller - timetz_smaller - - - - - f f 1552 1266 0 0 0 _null_ _null_ )); +DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - - - f f 902 790 0 0 0 _null_ _null_ )); +DATA(insert ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - - - f f 2062 1114 0 0 0 _null_ _null_ )); +DATA(insert ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - - - f f 1322 1184 0 0 0 _null_ _null_ )); +DATA(insert ( 2144 n 0 interval_smaller - interval_smaller - - - - - f f 1332 1186 0 0 0 _null_ _null_ )); +DATA(insert ( 2145 n 0 text_smaller - text_smaller - - - - - f f 664 25 0 0 0 _null_ _null_ )); +DATA(insert ( 2146 n 0 numeric_smaller - numeric_smaller - - - - - f f 1754 1700 0 0 0 _null_ _null_ )); +DATA(insert ( 2051 n 0 array_smaller - array_smaller - - - - - f f 1072 2277 0 0 0 _null_ _null_ )); +DATA(insert ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - - - f f 1058 1042 0 0 0 _null_ _null_ )); +DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - - - f f 2799 27 0 0 0 _null_ _null_ )); +DATA(insert ( 3527 n 0 enum_smaller - enum_smaller - - - - - f f 3518 3500 0 0 0 _null_ _null_ )); +DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - - - f f 1203 869 0 0 0 _null_ _null_ )); /* count */ -DATA(insert ( 2147 n 0 int8inc_any - int8pl - - int8inc_any int8dec_any - f f 0 20 0 0 20 0 "0" "0" )); -DATA(insert ( 2803 n 0 int8inc - int8pl - - int8inc int8dec - f f 0 20 0 0 20 0 "0" "0" )); +DATA(insert ( 2147 n 0 int8inc_any - int8pl - - int8inc_any int8dec_any - f f 0 20 0 20 0 "0" "0" )); +DATA(insert ( 2803 n 0 int8inc - int8pl - - int8inc int8dec - f f 0 20 0 20 0 "0" "0" )); /* var_pop */ -DATA(insert ( 2718 n 0 int8_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2721 n 0 float4_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2722 n 0 float8_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2718 n 0 int8_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2721 n 0 float4_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2722 n 0 float8_accum float8_var_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); /* var_samp */ -DATA(insert ( 2641 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2644 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2645 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2641 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2644 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2645 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* variance: historical Postgres syntax for var_samp */ -DATA(insert ( 2148 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2151 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2152 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2148 n 0 int8_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2151 n 0 float4_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2152 n 0 float8_accum float8_var_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev_pop */ -DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev_samp */ -DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev: historical Postgres syntax for stddev_samp */ -DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); -DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 17 48 2281 48 _null_ _null_ )); -DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 17 128 2281 128 _null_ _null_ )); +DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp numeric_poly_combine numeric_poly_serialize numeric_poly_deserialize int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp float8_combine - - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_combine numeric_serialize numeric_deserialize numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* SQL2003 binary regression aggregates */ -DATA(insert ( 2818 n 0 int8inc_float8_float8 - int8pl - - - - - f f 0 20 0 0 0 0 "0" _null_ )); -DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2829 n 0 float8_regr_accum float8_corr float8_regr_combine - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2818 n 0 int8inc_float8_float8 - int8pl - - - - - f f 0 20 0 0 0 "0" _null_ )); +DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2829 n 0 float8_regr_accum float8_corr float8_regr_combine - - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); /* boolean-and and boolean-or */ -DATA(insert ( 2517 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ )); -DATA(insert ( 2518 n 0 boolor_statefunc - boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 0 2281 16 _null_ _null_ )); -DATA(insert ( 2519 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ )); +DATA(insert ( 2517 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); +DATA(insert ( 2518 n 0 boolor_statefunc - boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 2281 16 _null_ _null_ )); +DATA(insert ( 2519 n 0 booland_statefunc - booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); /* bitwise integer */ -DATA(insert ( 2236 n 0 int2and - int2and - - - - - f f 0 21 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2237 n 0 int2or - int2or - - - - - f f 0 21 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2238 n 0 int4and - int4and - - - - - f f 0 23 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2239 n 0 int4or - int4or - - - - - f f 0 23 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2240 n 0 int8and - int8and - - - - - f f 0 20 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2241 n 0 int8or - int8or - - - - - f f 0 20 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2242 n 0 bitand - bitand - - - - - f f 0 1560 0 0 0 0 _null_ _null_ )); -DATA(insert ( 2243 n 0 bitor - bitor - - - - - f f 0 1560 0 0 0 0 _null_ _null_ )); +DATA(insert ( 2236 n 0 int2and - int2and - - - - - f f 0 21 0 0 0 _null_ _null_ )); +DATA(insert ( 2237 n 0 int2or - int2or - - - - - f f 0 21 0 0 0 _null_ _null_ )); +DATA(insert ( 2238 n 0 int4and - int4and - - - - - f f 0 23 0 0 0 _null_ _null_ )); +DATA(insert ( 2239 n 0 int4or - int4or - - - - - f f 0 23 0 0 0 _null_ _null_ )); +DATA(insert ( 2240 n 0 int8and - int8and - - - - - f f 0 20 0 0 0 _null_ _null_ )); +DATA(insert ( 2241 n 0 int8or - int8or - - - - - f f 0 20 0 0 0 _null_ _null_ )); +DATA(insert ( 2242 n 0 bitand - bitand - - - - - f f 0 1560 0 0 0 _null_ _null_ )); +DATA(insert ( 2243 n 0 bitor - bitor - - - - - f f 0 1560 0 0 0 _null_ _null_ )); /* xml */ -DATA(insert ( 2901 n 0 xmlconcat2 - - - - - - - f f 0 142 0 0 0 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 - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); +DATA(insert ( 2335 n 0 array_agg_transfn array_agg_finalfn - - - - - - t f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - - - t f 0 2281 0 0 0 _null_ _null_ )); /* text */ -DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - - - f f 0 2281 0 0 0 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 - - - - - - f f 0 2281 0 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 - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); +DATA(insert ( 3175 n 0 json_agg_transfn json_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ )); /* jsonb */ -DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); +DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - - - f f 0 2281 0 0 0 _null_ _null_ )); /* ordered-set and hypothetical-set aggregates */ -DATA(insert ( 3972 o 1 ordered_set_transition percentile_disc_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3974 o 1 ordered_set_transition percentile_cont_float8_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3976 o 1 ordered_set_transition percentile_cont_interval_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3978 o 1 ordered_set_transition percentile_disc_multi_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3980 o 1 ordered_set_transition percentile_cont_float8_multi_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3982 o 1 ordered_set_transition percentile_cont_interval_multi_final - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3984 o 0 ordered_set_transition mode_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3986 h 1 ordered_set_transition_multi rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3988 h 1 ordered_set_transition_multi percent_rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3990 h 1 ordered_set_transition_multi cume_dist_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); -DATA(insert ( 3992 h 1 ordered_set_transition_multi dense_rank_final - - - - - - t f 0 2281 0 0 0 0 _null_ _null_ )); +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_ )); /* @@ -344,7 +341,6 @@ extern ObjectAddress AggregateCreate(const char *aggName, bool mfinalfnExtraArgs, List *aggsortopName, Oid aggTransType, - Oid aggSerialType, int32 aggTransSpace, Oid aggmTransType, int32 aggmTransSpace, diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 6a65e77b5ecfd4d6a42e5b101ecc1585af3bc705..f441025f58ddbdcdcb099c11e8a6059f0dcdac8b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2451,11 +2451,11 @@ DATA(insert OID = 3337 ( numeric_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f DESCR("aggregate combine function"); DATA(insert OID = 2740 ( numeric_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_serialize _null_ _null_ _null_ )); DESCR("aggregate serial function"); -DATA(insert OID = 2741 ( numeric_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ )); +DATA(insert OID = 2741 ( numeric_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ )); DESCR("aggregate deserial function"); DATA(insert OID = 3335 ( numeric_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_serialize _null_ _null_ _null_ )); DESCR("aggregate serial function"); -DATA(insert OID = 3336 ( numeric_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ )); +DATA(insert OID = 3336 ( numeric_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ )); DESCR("aggregate deserial function"); DATA(insert OID = 3548 ( numeric_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum_inv _null_ _null_ _null_ )); DESCR("aggregate transition function"); @@ -2469,7 +2469,7 @@ DATA(insert OID = 3338 ( numeric_poly_combine PGNSP PGUID 12 1 0 0 0 f f f f DESCR("aggregate combine function"); DATA(insert OID = 3339 ( numeric_poly_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_serialize _null_ _null_ _null_ )); DESCR("aggregate serial function"); -DATA(insert OID = 3340 ( numeric_poly_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ )); +DATA(insert OID = 3340 ( numeric_poly_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ )); DESCR("aggregate deserial function"); DATA(insert OID = 2746 ( int8_avg_accum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ )); DESCR("aggregate transition function"); @@ -2485,9 +2485,9 @@ DATA(insert OID = 2785 ( int8_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f f DESCR("aggregate combine function"); DATA(insert OID = 2786 ( int8_avg_serialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ int8_avg_serialize _null_ _null_ _null_ )); DESCR("aggregate serial function"); -DATA(insert OID = 2787 ( int8_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ )); +DATA(insert OID = 2787 ( int8_avg_deserialize PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ )); DESCR("aggregate deserial function"); -DATA(insert OID = 3324 ( int4_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ )); +DATA(insert OID = 3324 ( int4_avg_combine PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 1016 "1016 1016" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ )); DESCR("aggregate combine function"); DATA(insert OID = 3178 ( numeric_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i s 1 0 1700 "2281" _null_ _null_ _null_ _null_ _null_ numeric_sum _null_ _null_ _null_ )); DESCR("aggregate final function"); diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index 1408d4e9fd2bcc66dbcc589e2975b2e6bf2ecd7b..28fc354a424c8cdd040f8991c4314f41c2b2b168 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -51,12 +51,12 @@ extern void build_aggregate_combinefn_expr(Oid agg_state_type, Oid combinefn_oid, Expr **combinefnexpr); -extern void build_aggregate_serialfn_expr(Oid agg_state_type, - Oid agg_serial_type, - Oid agg_input_collation, - Oid serialfn_oid, +extern void build_aggregate_serialfn_expr(Oid serialfn_oid, Expr **serialfnexpr); +extern void build_aggregate_deserialfn_expr(Oid deserialfn_oid, + Expr **deserialfnexpr); + extern void build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs, Oid agg_state_type, diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out index 625dae5cdbb66cc76e3f28f3ef60a1483163f004..341ba52b8d6c9e3877f200cc582186bda3f0e0ef 100644 --- a/src/test/regress/expected/create_aggregate.out +++ b/src/test/regress/expected/create_aggregate.out @@ -102,36 +102,19 @@ CREATE AGGREGATE sumdouble (float8) minvfunc = float8mi ); -- aggregate combine and serialization functions --- Ensure stype and serialtype can't be the same +-- can't specify just one of serialfunc and deserialfunc CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = internal -); -ERROR: aggregate serialization data type cannot be internal --- if serialtype is specified we need a serialfunc and deserialfunc -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = bytea -); -ERROR: aggregate serialization function must be specified when serialization type is specified -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize ); -ERROR: aggregate deserialization function must be specified when serialization type is specified +ERROR: must specify both or neither of serialization and deserialization functions -- serialfunc must have correct parameters CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize ); @@ -141,27 +124,15 @@ CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_serialize ); -ERROR: function numeric_avg_serialize(bytea) does not exist --- ensure return type of serialfunc is checked -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = text, - serialfunc = numeric_avg_serialize, - deserialfunc = numeric_avg_deserialize -); -ERROR: return type of serialization function numeric_avg_serialize is not text +ERROR: function numeric_avg_serialize(bytea, internal) does not exist -- ensure combine function parameters are checked CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_deserialize, combinefunc = int4larger @@ -173,18 +144,17 @@ CREATE AGGREGATE myavg (numeric) stype = internal, sfunc = numeric_avg_accum, finalfunc = numeric_avg, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_deserialize, combinefunc = numeric_avg_combine ); -- Ensure all these functions made it into the catalog -SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype +SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn FROM pg_aggregate WHERE aggfnoid = 'myavg'::REGPROC; - aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggserialtype -----------+-------------------+---------------------+--------------+-----------------------+-------------------------+--------------- - myavg | numeric_avg_accum | numeric_avg_combine | 2281 | numeric_avg_serialize | numeric_avg_deserialize | 17 + aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn +----------+-------------------+---------------------+--------------+-----------------------+------------------------- + myavg | numeric_avg_accum | numeric_avg_combine | 2281 | numeric_avg_serialize | numeric_avg_deserialize (1 row) DROP AGGREGATE myavg (numeric); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index b1596401306179a8fff29ed19c459969fa6408e3..826441442b72c3e1c0ea4f082de99924cf99d94a 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -279,21 +279,16 @@ ORDER BY 1, 2; -- Look for functions that return type "internal" and do not have any -- "internal" argument. Such a function would be a security hole since -- it might be used to call an internal function from an SQL command. --- As of 7.3 this query should find internal_in, and as of 9.6 aggregate --- deserialization will be found too. These should contain a runtime check to --- ensure they can only be called in an aggregate context. +-- As of 7.3 this query should find only internal_in, which is safe because +-- it always throws an error when called. SELECT p1.oid, p1.proname FROM pg_proc as p1 WHERE p1.prorettype = 'internal'::regtype AND NOT 'internal'::regtype = ANY (p1.proargtypes); - oid | proname -------+-------------------------- - 2741 | numeric_avg_deserialize - 3336 | numeric_deserialize - 3340 | numeric_poly_deserialize - 2787 | int8_avg_deserialize + oid | proname +------+------------- 2304 | internal_in -(5 rows) +(1 row) -- Look for functions that return a polymorphic type and do not have any -- polymorphic argument. Calls of such functions would be unresolvable @@ -1442,6 +1437,84 @@ WHERE a.aggfnoid = p.oid AND ----------+---------+-----+---------+-----+--------- (0 rows) +-- Check that all combine functions have signature +-- combine(transtype, transtype) returns transtype +-- NOTE: use physically_coercible here, not binary_coercible, because +-- max and min on abstime are implemented using int4larger/int4smaller. +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggcombinefn = p.oid AND + (p.pronargs != 2 OR + p.prorettype != p.proargtypes[0] OR + p.prorettype != p.proargtypes[1] OR + NOT physically_coercible(a.aggtranstype, p.proargtypes[0])); + aggfnoid | proname +----------+--------- +(0 rows) + +-- Check that no combine function for an INTERNAL transtype is strict. +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggcombinefn = p.oid AND + a.aggtranstype = 'internal'::regtype AND p.proisstrict; + aggfnoid | proname +----------+--------- +(0 rows) + +-- serialize/deserialize functions should be specified only for aggregates +-- with transtype internal and a combine function, and we should have both +-- or neither of them. +SELECT aggfnoid, aggtranstype, aggserialfn, aggdeserialfn +FROM pg_aggregate +WHERE (aggserialfn != 0 OR aggdeserialfn != 0) + AND (aggtranstype != 'internal'::regtype OR aggcombinefn = 0 OR + aggserialfn = 0 OR aggdeserialfn = 0); + aggfnoid | aggtranstype | aggserialfn | aggdeserialfn +----------+--------------+-------------+--------------- +(0 rows) + +-- Check that all serialization functions have signature +-- serialize(internal) returns bytea +-- Also insist that they be strict; it's wasteful to run them on NULLs. +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggserialfn = p.oid AND + (p.prorettype != 'bytea'::regtype OR p.pronargs != 1 OR + p.proargtypes[0] != 'internal'::regtype OR + NOT p.proisstrict); + aggfnoid | proname +----------+--------- +(0 rows) + +-- Check that all deserialization functions have signature +-- deserialize(bytea, internal) returns internal +-- Also insist that they be strict; it's wasteful to run them on NULLs. +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggdeserialfn = p.oid AND + (p.prorettype != 'internal'::regtype OR p.pronargs != 2 OR + p.proargtypes[0] != 'bytea'::regtype OR + p.proargtypes[1] != 'internal'::regtype OR + NOT p.proisstrict); + aggfnoid | proname +----------+--------- +(0 rows) + +-- Check that aggregates which have the same transition function also have +-- the same combine, serialization, and deserialization functions. +-- While that isn't strictly necessary, it's fishy if they don't. +SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, + b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn +FROM + pg_aggregate a, pg_aggregate b +WHERE + a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND + (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn + OR a.aggdeserialfn != b.aggdeserialfn); + aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn | aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn +----------+--------------+-------------+---------------+----------+--------------+-------------+--------------- +(0 rows) + -- Cross-check aggsortop (if present) against pg_operator. -- We expect to find entries for bool_and, bool_or, every, max, and min. SELECT DISTINCT proname, oprname @@ -1534,89 +1607,6 @@ WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; -----+--------- (0 rows) --- Check that all serial functions have a return type the same as the serial --- type. -SELECT a.aggserialfn,a.aggserialtype,p.prorettype -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggserialfn = p.oid -WHERE a.aggserialtype <> p.prorettype; - aggserialfn | aggserialtype | prorettype --------------+---------------+------------ -(0 rows) - --- Check that all the deserial functions have the same input type as the --- serialtype -SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0] -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid -WHERE p.proargtypes[0] <> a.aggserialtype; - aggserialfn | aggserialtype | proargtypes --------------+---------------+------------- -(0 rows) - --- An aggregate should either have a complete set of serialtype, serial func --- and deserial func, or none of them. -SELECT aggserialtype,aggserialfn,aggdeserialfn -FROM pg_aggregate -WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0) - AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0); - aggserialtype | aggserialfn | aggdeserialfn ----------------+-------------+--------------- -(0 rows) - --- Check that all aggregates with serialtypes have internal states. --- (There's no point in serializing anything apart from internal) -SELECT aggfnoid,aggserialtype,aggtranstype -FROM pg_aggregate -WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype; - aggfnoid | aggserialtype | aggtranstype -----------+---------------+-------------- -(0 rows) - --- Check that all serial functions are strict. It's wasteful for these to be --- called with NULL values. -SELECT aggfnoid,aggserialfn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggserialfn = p.oid -WHERE p.proisstrict = false; - aggfnoid | aggserialfn -----------+------------- -(0 rows) - --- Check that all deserial functions are strict. It's wasteful for these to be --- called with NULL values. -SELECT aggfnoid,aggdeserialfn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid -WHERE p.proisstrict = false; - aggfnoid | aggdeserialfn -----------+--------------- -(0 rows) - --- Check that no combine functions with an INTERNAL return type are strict. -SELECT aggfnoid,aggcombinefn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggcombinefn = p.oid -INNER JOIN pg_type t ON a.aggtranstype = t.oid -WHERE t.typname = 'internal' AND p.proisstrict = true; - aggfnoid | aggcombinefn -----------+-------------- -(0 rows) - --- Check that aggregates which have the same transition function also have --- the same combine, serialization, and deserialization functions. -SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, - b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn -FROM - pg_aggregate a, pg_aggregate b -WHERE - a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND - (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn - OR a.aggdeserialfn != b.aggdeserialfn); - aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn | aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn -----------+--------------+-------------+---------------+----------+--------------+-------------+--------------- -(0 rows) - -- **************** pg_opfamily **************** -- Look for illegal values in pg_opfamily fields SELECT p1.oid diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql index c98c154a8296baa6e345576c716a482cdd23880d..ae3a6c0ebec9ccfc65752b8fbff3daca50e03474 100644 --- a/src/test/regress/sql/create_aggregate.sql +++ b/src/test/regress/sql/create_aggregate.sql @@ -117,27 +117,11 @@ CREATE AGGREGATE sumdouble (float8) -- aggregate combine and serialization functions --- Ensure stype and serialtype can't be the same +-- can't specify just one of serialfunc and deserialfunc CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = internal -); - --- if serialtype is specified we need a serialfunc and deserialfunc -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = bytea -); - -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize ); @@ -146,7 +130,6 @@ CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_deserialize, deserialfunc = numeric_avg_deserialize ); @@ -156,27 +139,15 @@ CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_serialize ); --- ensure return type of serialfunc is checked -CREATE AGGREGATE myavg (numeric) -( - stype = internal, - sfunc = numeric_avg_accum, - serialtype = text, - serialfunc = numeric_avg_serialize, - deserialfunc = numeric_avg_deserialize -); - -- ensure combine function parameters are checked CREATE AGGREGATE myavg (numeric) ( stype = internal, sfunc = numeric_avg_accum, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_deserialize, combinefunc = int4larger @@ -188,14 +159,13 @@ CREATE AGGREGATE myavg (numeric) stype = internal, sfunc = numeric_avg_accum, finalfunc = numeric_avg, - serialtype = bytea, serialfunc = numeric_avg_serialize, deserialfunc = numeric_avg_deserialize, combinefunc = numeric_avg_combine ); -- Ensure all these functions made it into the catalog -SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype +SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn FROM pg_aggregate WHERE aggfnoid = 'myavg'::REGPROC; diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 62c84d035d52b56b8154dc5e29abc9e785a96554..bb9b6bb3b8a351ec20af27bc2ed8a76c9ce25388 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -228,9 +228,8 @@ ORDER BY 1, 2; -- Look for functions that return type "internal" and do not have any -- "internal" argument. Such a function would be a security hole since -- it might be used to call an internal function from an SQL command. --- As of 7.3 this query should find internal_in, and as of 9.6 aggregate --- deserialization will be found too. These should contain a runtime check to --- ensure they can only be called in an aggregate context. +-- As of 7.3 this query should find only internal_in, which is safe because +-- it always throws an error when called. SELECT p1.oid, p1.proname FROM pg_proc as p1 @@ -937,6 +936,72 @@ WHERE a.aggfnoid = p.oid AND a.aggminvtransfn = iptr.oid AND ptr.proisstrict != iptr.proisstrict; +-- Check that all combine functions have signature +-- combine(transtype, transtype) returns transtype +-- NOTE: use physically_coercible here, not binary_coercible, because +-- max and min on abstime are implemented using int4larger/int4smaller. + +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggcombinefn = p.oid AND + (p.pronargs != 2 OR + p.prorettype != p.proargtypes[0] OR + p.prorettype != p.proargtypes[1] OR + NOT physically_coercible(a.aggtranstype, p.proargtypes[0])); + +-- Check that no combine function for an INTERNAL transtype is strict. + +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggcombinefn = p.oid AND + a.aggtranstype = 'internal'::regtype AND p.proisstrict; + +-- serialize/deserialize functions should be specified only for aggregates +-- with transtype internal and a combine function, and we should have both +-- or neither of them. + +SELECT aggfnoid, aggtranstype, aggserialfn, aggdeserialfn +FROM pg_aggregate +WHERE (aggserialfn != 0 OR aggdeserialfn != 0) + AND (aggtranstype != 'internal'::regtype OR aggcombinefn = 0 OR + aggserialfn = 0 OR aggdeserialfn = 0); + +-- Check that all serialization functions have signature +-- serialize(internal) returns bytea +-- Also insist that they be strict; it's wasteful to run them on NULLs. + +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggserialfn = p.oid AND + (p.prorettype != 'bytea'::regtype OR p.pronargs != 1 OR + p.proargtypes[0] != 'internal'::regtype OR + NOT p.proisstrict); + +-- Check that all deserialization functions have signature +-- deserialize(bytea, internal) returns internal +-- Also insist that they be strict; it's wasteful to run them on NULLs. + +SELECT a.aggfnoid, p.proname +FROM pg_aggregate as a, pg_proc as p +WHERE a.aggdeserialfn = p.oid AND + (p.prorettype != 'internal'::regtype OR p.pronargs != 2 OR + p.proargtypes[0] != 'bytea'::regtype OR + p.proargtypes[1] != 'internal'::regtype OR + NOT p.proisstrict); + +-- Check that aggregates which have the same transition function also have +-- the same combine, serialization, and deserialization functions. +-- While that isn't strictly necessary, it's fishy if they don't. + +SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, + b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn +FROM + pg_aggregate a, pg_aggregate b +WHERE + a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND + (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn + OR a.aggdeserialfn != b.aggdeserialfn); + -- Cross-check aggsortop (if present) against pg_operator. -- We expect to find entries for bool_and, bool_or, every, max, and min. @@ -1004,64 +1069,6 @@ SELECT p.oid, proname FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; --- Check that all serial functions have a return type the same as the serial --- type. -SELECT a.aggserialfn,a.aggserialtype,p.prorettype -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggserialfn = p.oid -WHERE a.aggserialtype <> p.prorettype; - --- Check that all the deserial functions have the same input type as the --- serialtype -SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0] -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid -WHERE p.proargtypes[0] <> a.aggserialtype; - --- An aggregate should either have a complete set of serialtype, serial func --- and deserial func, or none of them. -SELECT aggserialtype,aggserialfn,aggdeserialfn -FROM pg_aggregate -WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0) - AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0); - --- Check that all aggregates with serialtypes have internal states. --- (There's no point in serializing anything apart from internal) -SELECT aggfnoid,aggserialtype,aggtranstype -FROM pg_aggregate -WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype; - --- Check that all serial functions are strict. It's wasteful for these to be --- called with NULL values. -SELECT aggfnoid,aggserialfn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggserialfn = p.oid -WHERE p.proisstrict = false; - --- Check that all deserial functions are strict. It's wasteful for these to be --- called with NULL values. -SELECT aggfnoid,aggdeserialfn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid -WHERE p.proisstrict = false; - --- Check that no combine functions with an INTERNAL return type are strict. -SELECT aggfnoid,aggcombinefn -FROM pg_aggregate a -INNER JOIN pg_proc p ON a.aggcombinefn = p.oid -INNER JOIN pg_type t ON a.aggtranstype = t.oid -WHERE t.typname = 'internal' AND p.proisstrict = true; - --- Check that aggregates which have the same transition function also have --- the same combine, serialization, and deserialization functions. -SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, - b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn -FROM - pg_aggregate a, pg_aggregate b -WHERE - a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND - (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn - OR a.aggdeserialfn != b.aggdeserialfn); -- **************** pg_opfamily ****************