diff options
Diffstat (limited to 'src')
23 files changed, 726 insertions, 193 deletions
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index c612ab9809e..b420349835b 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -58,6 +58,8 @@ AggregateCreate(const char *aggName, List *aggtransfnName, List *aggfinalfnName, List *aggcombinefnName, + List *aggserialfnName, + List *aggdeserialfnName, List *aggmtransfnName, List *aggminvtransfnName, List *aggmfinalfnName, @@ -65,6 +67,7 @@ AggregateCreate(const char *aggName, bool mfinalfnExtraArgs, List *aggsortopName, Oid aggTransType, + Oid aggSerialType, int32 aggTransSpace, Oid aggmTransType, int32 aggmTransSpace, @@ -79,6 +82,8 @@ AggregateCreate(const char *aggName, Oid transfn; Oid finalfn = InvalidOid; /* can be omitted */ Oid combinefn = InvalidOid; /* can be omitted */ + Oid serialfn = InvalidOid; /* can be omitted */ + Oid deserialfn = InvalidOid; /* can be omitted */ Oid mtransfn = InvalidOid; /* can be omitted */ Oid minvtransfn = InvalidOid; /* can be omitted */ Oid mfinalfn = InvalidOid; /* can be omitted */ @@ -420,6 +425,57 @@ AggregateCreate(const char *aggName, errmsg("return type of combine function %s is not %s", NameListToString(aggcombinefnName), format_type_be(aggTransType)))); + + /* + * A combine function to combine INTERNAL states must accept nulls and + * ensure that the returned state is in the correct memory context. + */ + if (aggTransType == INTERNALOID && func_strict(combinefn)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("combine function with \"%s\" transition type must not be declared STRICT", + format_type_be(aggTransType)))); + + } + + /* + * Validate the serialization function, if present. We must ensure that the + * return type of this function is the same as the specified serialType. + */ + if (aggserialfnName) + { + fnArgs[0] = aggTransType; + + serialfn = lookup_agg_function(aggserialfnName, 1, + fnArgs, variadicArgType, + &rettype); + + if (rettype != aggSerialType) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("return type of serialization function %s is not %s", + NameListToString(aggserialfnName), + format_type_be(aggSerialType)))); + } + + /* + * Validate the deserialization function, if present. We must ensure that + * the return type of this function is the same as the transType. + */ + if (aggdeserialfnName) + { + fnArgs[0] = aggSerialType; + + deserialfn = lookup_agg_function(aggdeserialfnName, 1, + fnArgs, variadicArgType, + &rettype); + + if (rettype != aggTransType) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("return type of deserialization function %s is not %s", + NameListToString(aggdeserialfnName), + format_type_be(aggTransType)))); } /* @@ -594,6 +650,8 @@ AggregateCreate(const char *aggName, values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn); values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn); values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn); + values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn); + values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn); values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn); values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn); values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn); @@ -601,6 +659,7 @@ 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); @@ -627,7 +686,8 @@ 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 if any. + * Likewise for aggmTransType using the mtransfunc, and also for + * aggSerialType using the serialfn, if they exist. */ /* Depends on transition function */ @@ -654,6 +714,24 @@ AggregateCreate(const char *aggName, recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } + /* Depends on serialization function, if any */ + if (OidIsValid(serialfn)) + { + referenced.classId = ProcedureRelationId; + referenced.objectId = serialfn; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Depends on deserialization function, if any */ + if (OidIsValid(deserialfn)) + { + referenced.classId = ProcedureRelationId; + referenced.objectId = deserialfn; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + /* Depends on forward transition function, if any */ if (OidIsValid(mtransfn)) { diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 59bc6e6fd8f..3424f842b9c 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -62,6 +62,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, List *transfuncName = NIL; List *finalfuncName = NIL; List *combinefuncName = NIL; + List *serialfuncName = NIL; + List *deserialfuncName = NIL; List *mtransfuncName = NIL; List *minvtransfuncName = NIL; List *mfinalfuncName = NIL; @@ -70,6 +72,7 @@ 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; @@ -84,6 +87,7 @@ 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; @@ -127,6 +131,10 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, finalfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "combinefunc") == 0) combinefuncName = defGetQualifiedName(defel); + else if (pg_strcasecmp(defel->defname, "serialfunc") == 0) + serialfuncName = defGetQualifiedName(defel); + else if (pg_strcasecmp(defel->defname, "deserialfunc") == 0) + deserialfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "msfunc") == 0) mtransfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "minvfunc") == 0) @@ -154,6 +162,8 @@ 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) @@ -319,6 +329,75 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, format_type_be(transTypeId)))); } + if (serialType) + { + /* + * 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. + */ + 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\"", + 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 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 + { + /* + * If serialization type was not specified then there shouldn't be a + * serialization function. + */ + 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"))); + } + /* * If a moving-aggregate transtype is specified, look that up. Same * restrictions as for transtype. @@ -387,6 +466,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, transfuncName, /* step function name */ finalfuncName, /* final function name */ combinefuncName, /* combine function name */ + serialfuncName, /* serial function name */ + deserialfuncName, /* deserial function name */ mtransfuncName, /* fwd trans function name */ minvtransfuncName, /* inv trans function name */ mfinalfuncName, /* final function name */ @@ -394,6 +475,7 @@ 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 03aa20f61e0..aba54195a30 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -44,6 +44,12 @@ * incorrect. Instead a new state should be created in the correct aggregate * memory context and the 2nd state should be copied over. * + * The 'serialStates' option can be used to allow multi-stage aggregation + * for aggregates with an INTERNAL state type. When this mode is disabled + * only a pointer to the INTERNAL aggregate states are passed around the + * executor. When enabled, INTERNAL states are serialized and deserialized + * as required; this is useful when data must be passed between processes. + * * If a normal aggregate call specifies DISTINCT or ORDER BY, we sort the * input tuples and eliminate duplicates (if required) before performing * the above-depicted process. (However, we don't do that for ordered-set @@ -232,6 +238,12 @@ typedef struct AggStatePerTransData /* Oid of the state transition or combine function */ Oid transfn_oid; + /* Oid of the serialization function or InvalidOid */ + Oid serialfn_oid; + + /* Oid of the deserialization function or InvalidOid */ + Oid deserialfn_oid; + /* Oid of state value's datatype */ Oid aggtranstype; @@ -246,6 +258,12 @@ typedef struct AggStatePerTransData */ FmgrInfo transfn; + /* fmgr lookup data for serialization function */ + FmgrInfo serialfn; + + /* fmgr lookup data for deserialization function */ + FmgrInfo deserialfn; + /* Input collation derived for aggregate */ Oid aggCollation; @@ -326,6 +344,11 @@ typedef struct AggStatePerTransData * worth the extra space consumption. */ FunctionCallInfoData transfn_fcinfo; + + /* Likewise for serialization and deserialization functions */ + FunctionCallInfoData serialfn_fcinfo; + + FunctionCallInfoData deserialfn_fcinfo; } AggStatePerTransData; /* @@ -467,6 +490,10 @@ static void finalize_aggregate(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull); +static void finalize_partialaggregate(AggState *aggstate, + AggStatePerAgg peragg, + AggStatePerGroup pergroupstate, + Datum *resultVal, bool *resultIsNull); static void prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet); @@ -487,12 +514,15 @@ 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, - Datum initValue, bool initValueIsNull, - Oid *inputTypes, int numArguments); + Oid aggserialtype, 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, Oid aggtransfn, Oid aggtranstype, + Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos); @@ -944,8 +974,45 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup) slot = ExecProject(pertrans->evalproj, NULL); Assert(slot->tts_nvalid >= 1); - fcinfo->arg[1] = slot->tts_values[0]; - fcinfo->argnull[1] = slot->tts_isnull[0]; + /* + * deserialfn_oid will be set if we must deserialize the input state + * before calling the combine function + */ + if (OidIsValid(pertrans->deserialfn_oid)) + { + /* + * Don't call a strict deserialization function with NULL input. + * A strict deserialization function and a null value means we skip + * calling the combine function for this state. We assume that this + * would be a waste of time and effort anyway so just skip it. + */ + if (pertrans->deserialfn.fn_strict && slot->tts_isnull[0]) + continue; + else + { + FunctionCallInfo dsinfo = &pertrans->deserialfn_fcinfo; + MemoryContext oldContext; + + dsinfo->arg[0] = slot->tts_values[0]; + dsinfo->argnull[0] = slot->tts_isnull[0]; + + /* + * We run the deserialization functions in per-input-tuple + * memory context. + */ + oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory); + + fcinfo->arg[1] = FunctionCallInvoke(dsinfo); + fcinfo->argnull[1] = dsinfo->isnull; + + MemoryContextSwitchTo(oldContext); + } + } + else + { + fcinfo->arg[1] = slot->tts_values[0]; + fcinfo->argnull[1] = slot->tts_isnull[0]; + } advance_combine_function(aggstate, pertrans, pergroupstate); } @@ -1344,6 +1411,61 @@ finalize_aggregate(AggState *aggstate, MemoryContextSwitchTo(oldContext); } +/* + * Compute the final value of one partial aggregate. + * + * The serialization function will be run, and the result delivered, in the + * output-tuple context; caller's CurrentMemoryContext does not matter. + */ +static void +finalize_partialaggregate(AggState *aggstate, + AggStatePerAgg peragg, + AggStatePerGroup pergroupstate, + Datum *resultVal, bool *resultIsNull) +{ + AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno]; + MemoryContext oldContext; + + oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory); + + /* + * serialfn_oid will be set if we must serialize the input state + * before calling the combine function on the state. + */ + if (OidIsValid(pertrans->serialfn_oid)) + { + /* Don't call a strict serialization function with NULL input. */ + if (pertrans->serialfn.fn_strict && pergroupstate->transValueIsNull) + { + *resultVal = (Datum) 0; + *resultIsNull = true; + } + else + { + FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo; + fcinfo->arg[0] = pergroupstate->transValue; + fcinfo->argnull[0] = pergroupstate->transValueIsNull; + + *resultVal = FunctionCallInvoke(fcinfo); + *resultIsNull = fcinfo->isnull; + } + } + else + { + *resultVal = pergroupstate->transValue; + *resultIsNull = pergroupstate->transValueIsNull; + } + + /* If result is pass-by-ref, make sure it is in the right context. */ + if (!peragg->resulttypeByVal && !*resultIsNull && + !MemoryContextContains(CurrentMemoryContext, + DatumGetPointer(*resultVal))) + *resultVal = datumCopy(*resultVal, + peragg->resulttypeByVal, + peragg->resulttypeLen); + + MemoryContextSwitchTo(oldContext); +} /* * Prepare to finalize and project based on the specified representative tuple @@ -1455,10 +1577,8 @@ finalize_aggregates(AggState *aggstate, finalize_aggregate(aggstate, peragg, pergroupstate, &aggvalues[aggno], &aggnulls[aggno]); else - { - aggvalues[aggno] = pergroupstate->transValue; - aggnulls[aggno] = pergroupstate->transValueIsNull; - } + finalize_partialaggregate(aggstate, peragg, pergroupstate, + &aggvalues[aggno], &aggnulls[aggno]); } } @@ -2238,6 +2358,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) aggstate->agg_done = false; aggstate->combineStates = node->combineStates; aggstate->finalizeAggs = node->finalizeAggs; + aggstate->serialStates = node->serialStates; aggstate->input_done = false; aggstate->pergroup = NULL; aggstate->grp_firstTuple = NULL; @@ -2546,6 +2667,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) AclResult aclresult; Oid transfn_oid, finalfn_oid; + Oid serialtype_oid, + serialfn_oid, + deserialfn_oid; Expr *finalfnexpr; Oid aggtranstype; Datum textInitVal; @@ -2610,6 +2734,47 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) else peragg->finalfn_oid = finalfn_oid = InvalidOid; + serialtype_oid = InvalidOid; + serialfn_oid = InvalidOid; + deserialfn_oid = InvalidOid; + + /* + * Determine if we require serialization or deserialization of the + * aggregate states. This is only required if the aggregate state is + * internal. + */ + if (aggstate->serialStates && aggform->aggtranstype == INTERNALOID) + { + /* + * 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. + */ + 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"); + + if (!OidIsValid(aggform->aggdeserialfn)) + elog(ERROR, "deserialfunc not set during serialStates aggregation step"); + + /* 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 */ { HeapTuple procTuple; @@ -2638,6 +2803,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) get_func_name(finalfn_oid)); InvokeFunctionExecuteHook(finalfn_oid); } + if (OidIsValid(serialfn_oid)) + { + aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner, + ACL_EXECUTE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_PROC, + get_func_name(serialfn_oid)); + InvokeFunctionExecuteHook(serialfn_oid); + } + if (OidIsValid(deserialfn_oid)) + { + aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner, + ACL_EXECUTE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_PROC, + get_func_name(deserialfn_oid)); + InvokeFunctionExecuteHook(deserialfn_oid); + } } /* @@ -2707,7 +2890,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) */ existing_transno = find_compatible_pertrans(aggstate, aggref, transfn_oid, aggtranstype, - initValue, initValueIsNull, + serialfn_oid, deserialfn_oid, + initValue, initValueIsNull, same_input_transnos); if (existing_transno != -1) { @@ -2723,8 +2907,10 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) pertrans = &pertransstates[++transno]; build_pertrans_for_aggref(pertrans, aggstate, estate, aggref, transfn_oid, aggtranstype, - initValue, initValueIsNull, - inputTypes, numArguments); + serialtype_oid, serialfn_oid, + deserialfn_oid, initValue, + initValueIsNull, inputTypes, + numArguments); peragg->transno = transno; } ReleaseSysCache(aggTuple); @@ -2752,11 +2938,14 @@ static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggstate, EState *estate, Aggref *aggref, - Oid aggtransfn, Oid aggtranstype, + Oid aggtransfn, Oid aggtranstype, Oid aggserialtype, + Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments) { int numGroupingSets = Max(aggstate->maxsets, 1); + Expr *serialfnexpr = NULL; + Expr *deserialfnexpr = NULL; ListCell *lc; int numInputs; int numDirectArgs; @@ -2770,6 +2959,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, pertrans->aggref = aggref; pertrans->aggCollation = aggref->inputcollid; pertrans->transfn_oid = aggtransfn; + pertrans->serialfn_oid = aggserialfn; + pertrans->deserialfn_oid = aggdeserialfn; pertrans->initValue = initValue; pertrans->initValueIsNull = initValueIsNull; @@ -2809,6 +3000,17 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, 2, pertrans->aggCollation, (void *) aggstate, NULL); + + /* + * Ensure that a combine function to combine INTERNAL states is not + * strict. This should have been checked during CREATE AGGREGATE, but + * the strict property could have been changed since then. + */ + if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("combine function for aggregate %u must to be declared as strict", + aggref->aggfnoid))); } else { @@ -2861,6 +3063,41 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, &pertrans->transtypeLen, &pertrans->transtypeByVal); + if (OidIsValid(aggserialfn)) + { + build_aggregate_serialfn_expr(aggtranstype, + aggserialtype, + aggref->inputcollid, + aggserialfn, + &serialfnexpr); + fmgr_info(aggserialfn, &pertrans->serialfn); + fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn); + + InitFunctionCallInfoData(pertrans->serialfn_fcinfo, + &pertrans->serialfn, + 1, + pertrans->aggCollation, + (void *) aggstate, NULL); + } + + if (OidIsValid(aggdeserialfn)) + { + build_aggregate_serialfn_expr(aggserialtype, + aggtranstype, + aggref->inputcollid, + aggdeserialfn, + &deserialfnexpr); + fmgr_info(aggdeserialfn, &pertrans->deserialfn); + fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn); + + InitFunctionCallInfoData(pertrans->deserialfn_fcinfo, + &pertrans->deserialfn, + 1, + pertrans->aggCollation, + (void *) aggstate, NULL); + + } + /* * Get a tupledesc corresponding to the aggregated inputs (including sort * expressions) of the agg. @@ -3107,6 +3344,7 @@ find_compatible_peragg(Aggref *newagg, AggState *aggstate, static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, Oid aggtransfn, Oid aggtranstype, + Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos) { @@ -3125,6 +3363,17 @@ find_compatible_pertrans(AggState *aggstate, Aggref *newagg, aggtranstype != pertrans->aggtranstype) continue; + /* + * The serialization and deserialization functions must match, if + * present, as we're unable to share the trans state for aggregates + * which will serialize or deserialize into different formats. Remember + * that these will be InvalidOid if they're not required for this agg + * node. + */ + if (aggserialfn != pertrans->serialfn_oid || + aggdeserialfn != pertrans->deserialfn_oid) + continue; + /* Check that the initial condition matches, too. */ if (initValueIsNull && pertrans->initValueIsNull) return transno; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 6378db8bbea..f4e4a91ba53 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -871,6 +871,7 @@ _copyAgg(const Agg *from) COPY_SCALAR_FIELD(aggstrategy); COPY_SCALAR_FIELD(combineStates); COPY_SCALAR_FIELD(finalizeAggs); + COPY_SCALAR_FIELD(serialStates); COPY_SCALAR_FIELD(numCols); if (from->numCols > 0) { diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 83abaa68a38..5b71c95ede7 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -708,6 +708,7 @@ _outAgg(StringInfo str, const Agg *node) WRITE_ENUM_FIELD(aggstrategy, AggStrategy); WRITE_BOOL_FIELD(combineStates); WRITE_BOOL_FIELD(finalizeAggs); + WRITE_BOOL_FIELD(serialStates); WRITE_INT_FIELD(numCols); appendStringInfoString(str, " :grpColIdx"); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index cb0752a6ad8..202e90abc53 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1993,6 +1993,7 @@ _readAgg(void) READ_ENUM_FIELD(aggstrategy, AggStrategy); READ_BOOL_FIELD(combineStates); READ_BOOL_FIELD(finalizeAggs); + READ_BOOL_FIELD(serialStates); READ_INT_FIELD(numCols); READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols); READ_OID_ARRAY(grpOperators, local_node->numCols); diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index e4bc14a1510..994983b9164 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -1279,6 +1279,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags) AGG_HASHED, false, true, + false, numGroupCols, groupColIdx, groupOperators, @@ -1578,6 +1579,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path) best_path->aggstrategy, best_path->combineStates, best_path->finalizeAggs, + best_path->serialStates, list_length(best_path->groupClause), extract_grouping_cols(best_path->groupClause, subplan->targetlist), @@ -1732,6 +1734,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) AGG_SORTED, false, true, + false, list_length((List *) linitial(gsets)), new_grpColIdx, extract_grouping_ops(groupClause), @@ -1768,6 +1771,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN, false, true, + false, numGroupCols, top_grpColIdx, extract_grouping_ops(groupClause), @@ -5636,7 +5640,7 @@ materialize_finished_plan(Plan *subplan) Agg * make_agg(List *tlist, List *qual, AggStrategy aggstrategy, - bool combineStates, bool finalizeAggs, + bool combineStates, bool finalizeAggs, bool serialStates, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree) @@ -5651,6 +5655,7 @@ make_agg(List *tlist, List *qual, node->aggstrategy = aggstrategy; node->combineStates = combineStates; node->finalizeAggs = finalizeAggs; + node->serialStates = serialStates; node->numCols = numGroupCols; node->grpColIdx = grpColIdx; node->grpOperators = grpOperators; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 86d80727ed9..b2a9a8088f6 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -3455,7 +3455,8 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumPartialGroups, false, - false)); + false, + true)); else add_partial_path(grouped_rel, (Path *) create_group_path(root, @@ -3496,7 +3497,8 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumPartialGroups, false, - false)); + false, + true)); } } } @@ -3560,7 +3562,8 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumGroups, false, - true)); + true, + false)); } else if (parse->groupClause) { @@ -3626,6 +3629,7 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumGroups, true, + true, true)); else add_path(grouped_rel, (Path *) @@ -3668,7 +3672,8 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumGroups, false, - true)); + true, + false)); } /* @@ -3706,6 +3711,7 @@ create_grouping_paths(PlannerInfo *root, &agg_costs, dNumGroups, true, + true, true)); } } @@ -4039,7 +4045,8 @@ create_distinct_paths(PlannerInfo *root, NULL, numDistinctRows, false, - true)); + true, + false)); } /* Give a helpful error if we failed to find any implementation */ diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 16f572faf42..dd2b9ed9f08 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -2057,10 +2057,10 @@ search_indexed_tlist_for_sortgroupref(Node *node, * search_indexed_tlist_for_partial_aggref - find an Aggref in an indexed tlist * * Aggrefs for partial aggregates have their aggoutputtype adjusted to set it - * to the aggregate state's type. This means that a standard equal() comparison - * won't match when comparing an Aggref which is in partial mode with an Aggref - * which is not. Here we manually compare all of the fields apart from - * aggoutputtype. + * to the aggregate state's type, or serialization type. This means that a + * standard equal() comparison won't match when comparing an Aggref which is + * in partial mode with an Aggref which is not. Here we manually compare all of + * the fields apart from aggoutputtype. */ static Var * search_indexed_tlist_for_partial_aggref(Aggref *aggref, indexed_tlist *itlist, diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index fb139af2c1c..a1ab4daf11a 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -861,7 +861,8 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist, NULL, dNumGroups, false, - true); + true, + false); } else { diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index d80dfbe5c9f..c615717dea3 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -464,11 +464,15 @@ aggregates_allow_partial_walker(Node *node, partial_agg_context *context) } /* - * If we find any aggs with an internal transtype then we must ensure - * that pointers to aggregate states are not passed to other processes; - * therefore, we set the maximum allowed type to PAT_INTERNAL_ONLY. + * 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. */ - if (aggform->aggtranstype == INTERNALOID) + if (aggform->aggtranstype == INTERNALOID && + (!OidIsValid(aggform->aggserialtype) || + !OidIsValid(aggform->aggserialfn) || + !OidIsValid(aggform->aggdeserialfn))) context->allowedtype = PAT_INTERNAL_ONLY; ReleaseSysCache(aggTuple); diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 16b34fcf46a..89cae793ca3 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -2433,7 +2433,8 @@ create_agg_path(PlannerInfo *root, const AggClauseCosts *aggcosts, double numGroups, bool combineStates, - bool finalizeAggs) + bool finalizeAggs, + bool serialStates) { AggPath *pathnode = makeNode(AggPath); @@ -2458,6 +2459,7 @@ create_agg_path(PlannerInfo *root, pathnode->qual = qual; pathnode->finalizeAggs = finalizeAggs; pathnode->combineStates = combineStates; + pathnode->serialStates = serialStates; cost_agg(&pathnode->path, root, aggstrategy, aggcosts, diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index cd421b14632..4c8c83da80d 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -756,8 +756,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. This allows exprType() to return the actual type that - * will be produced. + * the aggtranstype or aggserialtype. 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 burried * within other expressions. @@ -785,7 +785,12 @@ apply_partialaggref_adjustment(PathTarget *target) aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); newaggref = (Aggref *) copyObject(aggref); - newaggref->aggoutputtype = aggform->aggtranstype; + + /* use the serialization type, if one exists */ + if (OidIsValid(aggform->aggserialtype)) + newaggref->aggoutputtype = aggform->aggserialtype; + else + newaggref->aggoutputtype = aggform->aggtranstype; lfirst(lc) = newaggref; diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 583462a9181..91bfe66c590 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -1966,6 +1966,45 @@ build_aggregate_combinefn_expr(Oid agg_state_type, /* * 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. + */ +void +build_aggregate_serialfn_expr(Oid agg_input_type, + Oid agg_output_type, + Oid agg_input_collation, + 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); + + fexpr = makeFuncExpr(serialfn_oid, + agg_output_type, + args, + InvalidOid, + agg_input_collation, + COERCE_EXPLICIT_CALL); + fexpr->funcvariadic = false; + *serialfnexpr = (Expr *) fexpr; +} + +/* + * Like build_aggregate_transfn_expr, but creates an expression tree for the * final function of an aggregate, rather than the transition function. */ void diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 077b37eb43d..454225da43c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12557,6 +12557,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) int i_aggtransfn; int i_aggfinalfn; int i_aggcombinefn; + int i_aggserialfn; + int i_aggdeserialfn; int i_aggmtransfn; int i_aggminvtransfn; int i_aggmfinalfn; @@ -12565,6 +12567,7 @@ 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; @@ -12574,6 +12577,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) const char *aggtransfn; const char *aggfinalfn; const char *aggcombinefn; + const char *aggserialfn; + const char *aggdeserialfn; const char *aggmtransfn; const char *aggminvtransfn; const char *aggmfinalfn; @@ -12583,6 +12588,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) char *aggsortconvop; bool hypothetical; const char *aggtranstype; + const char *aggserialtype; const char *aggtransspace; const char *aggmtranstype; const char *aggmtransspace; @@ -12608,10 +12614,11 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, " "aggfinalfn, aggtranstype::pg_catalog.regtype, " - "aggcombinefn, aggmtransfn, " + "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, " "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggfinalextra, aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " + "aggserialtype::pg_catalog.regtype, " "(aggkind = 'h') AS hypothetical, " "aggtransspace, agginitval, " "aggmtransspace, aggminitval, " @@ -12627,10 +12634,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, " "aggfinalfn, aggtranstype::pg_catalog.regtype, " - "'-' AS aggcombinefn, aggmtransfn, aggminvtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, " "aggmfinalfn, aggmtranstype::pg_catalog.regtype, " "aggfinalextra, aggmfinalextra, " "aggsortop::pg_catalog.regoperator, " + "0 AS aggserialtype, " "(aggkind = 'h') AS hypothetical, " "aggtransspace, agginitval, " "aggmtransspace, aggminitval, " @@ -12646,11 +12655,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, " "aggfinalfn, aggtranstype::pg_catalog.regtype, " - "'-' AS aggcombinefn, '-' AS aggmtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, '-' AS aggmtransfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "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, " @@ -12666,11 +12677,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, " "aggfinalfn, aggtranstype::pg_catalog.regtype, " - "'-' AS aggcombinefn, '-' AS aggmtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, '-' AS aggmtransfn, " "'-' AS aggminvtransfn, '-' AS aggmfinalfn, " "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, " @@ -12684,10 +12697,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, " "aggfinalfn, aggtranstype::pg_catalog.regtype, " - "'-' AS aggcombinefn, '-' AS aggmtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, '-' AS aggmtransfn, " "'-' 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, " @@ -12701,10 +12716,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) { appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, " "format_type(aggtranstype, NULL) AS aggtranstype, " - "'-' AS aggcombinefn, '-' AS aggmtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, '-' AS aggmtransfn, " "'-' 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, " @@ -12718,10 +12735,12 @@ dumpAgg(Archive *fout, AggInfo *agginfo) appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, " "aggfinalfn, " "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, " - "'-' AS aggcombinefn, '-' AS aggmtransfn, " + "'-' AS aggcombinefn, '-' AS aggserialfn, " + "'-' AS aggdeserialfn, '-' AS aggmtransfn, " "'-' 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, " @@ -12736,12 +12755,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo) i_aggtransfn = PQfnumber(res, "aggtransfn"); i_aggfinalfn = PQfnumber(res, "aggfinalfn"); i_aggcombinefn = PQfnumber(res, "aggcombinefn"); + i_aggserialfn = PQfnumber(res, "aggserialfn"); + i_aggdeserialfn = PQfnumber(res, "aggdeserialfn"); i_aggmtransfn = PQfnumber(res, "aggmtransfn"); i_aggminvtransfn = PQfnumber(res, "aggminvtransfn"); i_aggmfinalfn = PQfnumber(res, "aggmfinalfn"); i_aggfinalextra = PQfnumber(res, "aggfinalextra"); i_aggmfinalextra = PQfnumber(res, "aggmfinalextra"); i_aggsortop = PQfnumber(res, "aggsortop"); + i_aggserialtype = PQfnumber(res, "aggserialtype"); i_hypothetical = PQfnumber(res, "hypothetical"); i_aggtranstype = PQfnumber(res, "aggtranstype"); i_aggtransspace = PQfnumber(res, "aggtransspace"); @@ -12754,6 +12776,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) aggtransfn = PQgetvalue(res, 0, i_aggtransfn); aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn); aggcombinefn = PQgetvalue(res, 0, i_aggcombinefn); + aggserialfn = PQgetvalue(res, 0, i_aggserialfn); + aggdeserialfn = PQgetvalue(res, 0, i_aggdeserialfn); aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn); aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn); aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn); @@ -12762,6 +12786,7 @@ 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); @@ -12847,6 +12872,17 @@ dumpAgg(Archive *fout, AggInfo *agginfo) 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); + appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn); + appendPQExpBuffer(details, ",\n SERIALTYPE = %s", aggserialtype); + } + if (strcmp(aggmtransfn, "-") != 0) { appendPQExpBuffer(details, ",\n MSFUNC = %s,\n MINVFUNC = %s,\n MSTYPE = %s", diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index b690dc6b34f..92ea48da895 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201603231 +#define CATALOG_VERSION_NO 201603291 #endif diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 441db304dfb..4205fabb576 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -34,6 +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) * 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) @@ -43,6 +45,7 @@ * 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) @@ -58,6 +61,8 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS regproc aggtransfn; regproc aggfinalfn; regproc aggcombinefn; + regproc aggserialfn; + regproc aggdeserialfn; regproc aggmtransfn; regproc aggminvtransfn; regproc aggmfinalfn; @@ -65,6 +70,7 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS bool aggmfinalextra; Oid aggsortop; Oid aggtranstype; + Oid aggserialtype; int32 aggtransspace; Oid aggmtranstype; int32 aggmtransspace; @@ -87,25 +93,28 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; * ---------------- */ -#define Natts_pg_aggregate 18 +#define Natts_pg_aggregate 21 #define Anum_pg_aggregate_aggfnoid 1 #define Anum_pg_aggregate_aggkind 2 #define Anum_pg_aggregate_aggnumdirectargs 3 #define Anum_pg_aggregate_aggtransfn 4 #define Anum_pg_aggregate_aggfinalfn 5 #define Anum_pg_aggregate_aggcombinefn 6 -#define Anum_pg_aggregate_aggmtransfn 7 -#define Anum_pg_aggregate_aggminvtransfn 8 -#define Anum_pg_aggregate_aggmfinalfn 9 -#define Anum_pg_aggregate_aggfinalextra 10 -#define Anum_pg_aggregate_aggmfinalextra 11 -#define Anum_pg_aggregate_aggsortop 12 -#define Anum_pg_aggregate_aggtranstype 13 -#define Anum_pg_aggregate_aggtransspace 14 -#define Anum_pg_aggregate_aggmtranstype 15 -#define Anum_pg_aggregate_aggmtransspace 16 -#define Anum_pg_aggregate_agginitval 17 -#define Anum_pg_aggregate_aggminitval 18 +#define Anum_pg_aggregate_aggserialfn 7 +#define Anum_pg_aggregate_aggdeserialfn 8 +#define Anum_pg_aggregate_aggmtransfn 9 +#define Anum_pg_aggregate_aggminvtransfn 10 +#define Anum_pg_aggregate_aggmfinalfn 11 +#define Anum_pg_aggregate_aggfinalextra 12 +#define Anum_pg_aggregate_aggmfinalextra 13 +#define Anum_pg_aggregate_aggsortop 14 +#define Anum_pg_aggregate_aggtranstype 15 +#define Anum_pg_aggregate_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 /* * Symbolic values for aggkind column. We distinguish normal aggregates @@ -129,184 +138,184 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; */ /* avg */ -DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg - 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_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2102 n 0 int2_avg_accum int8_avg - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg - numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2104 n 0 float4_accum float8_avg - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2105 n 0 float8_accum float8_avg - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2106 n 0 interval_accum interval_avg - interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); +DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg - - - int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2101 n 0 int4_avg_accum int8_avg - - - int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2102 n 0 int2_avg_accum int8_avg - - - int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg - - - numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2104 n 0 float4_accum float8_avg - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2105 n 0 float8_accum float8_avg - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2106 n 0 interval_accum interval_avg - - - interval_accum interval_accum_inv interval_avg f f 0 1187 0 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_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_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum - - - int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 0 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_accum numeric_accum_inv numeric_sum f f 0 2281 0 128 2281 128 _null_ _null_ )); /* max */ -DATA(insert ( 2115 n 0 int8larger - int8larger - - - f f 413 20 0 0 0 _null_ _null_ )); -DATA(insert ( 2116 n 0 int4larger - int4larger - - - f f 521 23 0 0 0 _null_ _null_ )); -DATA(insert ( 2117 n 0 int2larger - int2larger - - - f f 520 21 0 0 0 _null_ _null_ )); -DATA(insert ( 2118 n 0 oidlarger - oidlarger - - - f f 610 26 0 0 0 _null_ _null_ )); -DATA(insert ( 2119 n 0 float4larger - float4larger - - - f f 623 700 0 0 0 _null_ _null_ )); -DATA(insert ( 2120 n 0 float8larger - float8larger - - - f f 674 701 0 0 0 _null_ _null_ )); -DATA(insert ( 2121 n 0 int4larger - int4larger - - - f f 563 702 0 0 0 _null_ _null_ )); -DATA(insert ( 2122 n 0 date_larger - date_larger - - - f f 1097 1082 0 0 0 _null_ _null_ )); -DATA(insert ( 2123 n 0 time_larger - time_larger - - - f f 1112 1083 0 0 0 _null_ _null_ )); -DATA(insert ( 2124 n 0 timetz_larger - timetz_larger - - - f f 1554 1266 0 0 0 _null_ _null_ )); -DATA(insert ( 2125 n 0 cashlarger - cashlarger - - - f f 903 790 0 0 0 _null_ _null_ )); -DATA(insert ( 2126 n 0 timestamp_larger - timestamp_larger - - - f f 2064 1114 0 0 0 _null_ _null_ )); -DATA(insert ( 2127 n 0 timestamptz_larger - timestamptz_larger - - - f f 1324 1184 0 0 0 _null_ _null_ )); -DATA(insert ( 2128 n 0 interval_larger - interval_larger - - - f f 1334 1186 0 0 0 _null_ _null_ )); -DATA(insert ( 2129 n 0 text_larger - text_larger - - - f f 666 25 0 0 0 _null_ _null_ )); -DATA(insert ( 2130 n 0 numeric_larger - numeric_larger - - - f f 1756 1700 0 0 0 _null_ _null_ )); -DATA(insert ( 2050 n 0 array_larger - array_larger - - - f f 1073 2277 0 0 0 _null_ _null_ )); -DATA(insert ( 2244 n 0 bpchar_larger - bpchar_larger - - - f f 1060 1042 0 0 0 _null_ _null_ )); -DATA(insert ( 2797 n 0 tidlarger - tidlarger - - - f f 2800 27 0 0 0 _null_ _null_ )); -DATA(insert ( 3526 n 0 enum_larger - enum_larger - - - f f 3519 3500 0 0 0 _null_ _null_ )); -DATA(insert ( 3564 n 0 network_larger - network_larger - - - f f 1205 869 0 0 0 _null_ _null_ )); +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_ )); /* min */ -DATA(insert ( 2131 n 0 int8smaller - int8smaller - - - f f 412 20 0 0 0 _null_ _null_ )); -DATA(insert ( 2132 n 0 int4smaller - int4smaller - - - f f 97 23 0 0 0 _null_ _null_ )); -DATA(insert ( 2133 n 0 int2smaller - int2smaller - - - f f 95 21 0 0 0 _null_ _null_ )); -DATA(insert ( 2134 n 0 oidsmaller - oidsmaller - - - f f 609 26 0 0 0 _null_ _null_ )); -DATA(insert ( 2135 n 0 float4smaller - float4smaller - - - f f 622 700 0 0 0 _null_ _null_ )); -DATA(insert ( 2136 n 0 float8smaller - float8smaller - - - f f 672 701 0 0 0 _null_ _null_ )); -DATA(insert ( 2137 n 0 int4smaller - int4smaller - - - f f 562 702 0 0 0 _null_ _null_ )); -DATA(insert ( 2138 n 0 date_smaller - date_smaller - - - f f 1095 1082 0 0 0 _null_ _null_ )); -DATA(insert ( 2139 n 0 time_smaller - time_smaller - - - f f 1110 1083 0 0 0 _null_ _null_ )); -DATA(insert ( 2140 n 0 timetz_smaller - timetz_smaller - - - f f 1552 1266 0 0 0 _null_ _null_ )); -DATA(insert ( 2141 n 0 cashsmaller - cashsmaller - - - f f 902 790 0 0 0 _null_ _null_ )); -DATA(insert ( 2142 n 0 timestamp_smaller - timestamp_smaller - - - f f 2062 1114 0 0 0 _null_ _null_ )); -DATA(insert ( 2143 n 0 timestamptz_smaller - timestamptz_smaller - - - f f 1322 1184 0 0 0 _null_ _null_ )); -DATA(insert ( 2144 n 0 interval_smaller - interval_smaller - - - f f 1332 1186 0 0 0 _null_ _null_ )); -DATA(insert ( 2145 n 0 text_smaller - text_smaller - - - f f 664 25 0 0 0 _null_ _null_ )); -DATA(insert ( 2146 n 0 numeric_smaller - numeric_smaller - - - f f 1754 1700 0 0 0 _null_ _null_ )); -DATA(insert ( 2051 n 0 array_smaller - array_smaller - - - f f 1072 2277 0 0 0 _null_ _null_ )); -DATA(insert ( 2245 n 0 bpchar_smaller - bpchar_smaller - - - f f 1058 1042 0 0 0 _null_ _null_ )); -DATA(insert ( 2798 n 0 tidsmaller - tidsmaller - - - f f 2799 27 0 0 0 _null_ _null_ )); -DATA(insert ( 3527 n 0 enum_smaller - enum_smaller - - - f f 3518 3500 0 0 0 _null_ _null_ )); -DATA(insert ( 3565 n 0 network_smaller - network_smaller - - - f f 1203 869 0 0 0 _null_ _null_ )); +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_ )); /* count */ -DATA(insert ( 2147 n 0 int8inc_any - int8pl int8inc_any int8dec_any - f f 0 20 0 20 0 "0" "0" )); -DATA(insert ( 2803 n 0 int8inc - int8pl int8inc int8dec - f f 0 20 0 20 0 "0" "0" )); +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" )); /* var_pop */ -DATA(insert ( 2718 n 0 int8_accum numeric_var_pop - int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop - numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2718 n 0 int8_accum numeric_var_pop - - - int8_accum int8_accum_inv numeric_var_pop f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop - - - int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop - - - int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2721 n 0 float4_accum float8_var_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop - - - numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 0 128 2281 128 _null_ _null_ )); /* var_samp */ -DATA(insert ( 2641 n 0 int8_accum numeric_var_samp - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2641 n 0 int8_accum numeric_var_samp - - - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp - - - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp - - - int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2644 n 0 float4_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp - - - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); /* variance: historical Postgres syntax for var_samp */ -DATA(insert ( 2148 n 0 int8_accum numeric_var_samp - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2148 n 0 int8_accum numeric_var_samp - - - int8_accum int8_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp - - - int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp - - - int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2151 n 0 float4_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp - - - numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); /* stddev_pop */ -DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop - int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop - numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop - - - int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop - - - int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop - - - int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop - - - numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 0 128 2281 128 _null_ _null_ )); /* stddev_samp */ -DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp - - - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp - - - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp - - - int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp - - - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); /* stddev: historical Postgres syntax for stddev_samp */ -DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp - 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 - 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 - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp - - - int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); +DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp - - - int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp - - - int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 0 48 2281 48 _null_ _null_ )); +DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp - - - numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 0 128 2281 128 _null_ _null_ )); /* SQL2003 binary regression aggregates */ -DATA(insert ( 2818 n 0 int8inc_float8_float8 - - - - - f f 0 20 0 0 0 "0" _null_ )); -DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); -DATA(insert ( 2829 n 0 float8_regr_accum float8_corr - - - - f f 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2818 n 0 int8inc_float8_float8 - - - - - - - f f 0 20 0 0 0 0 "0" _null_ )); +DATA(insert ( 2819 n 0 float8_regr_accum float8_regr_sxx - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2820 n 0 float8_regr_accum float8_regr_syy - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2821 n 0 float8_regr_accum float8_regr_sxy - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2822 n 0 float8_regr_accum float8_regr_avgx - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2823 n 0 float8_regr_accum float8_regr_avgy - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2824 n 0 float8_regr_accum float8_regr_r2 - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2825 n 0 float8_regr_accum float8_regr_slope - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2826 n 0 float8_regr_accum float8_regr_intercept - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2827 n 0 float8_regr_accum float8_covar_pop - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2828 n 0 float8_regr_accum float8_covar_samp - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); +DATA(insert ( 2829 n 0 float8_regr_accum float8_corr - - - - - - f f 0 1022 0 0 0 0 "{0,0,0,0,0,0}" _null_ )); /* boolean-and and boolean-or */ -DATA(insert ( 2517 n 0 booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); -DATA(insert ( 2518 n 0 boolor_statefunc - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 2281 16 _null_ _null_ )); -DATA(insert ( 2519 n 0 booland_statefunc - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 2281 16 _null_ _null_ )); +DATA(insert ( 2517 n 0 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 - - - - bool_accum bool_accum_inv bool_anytrue f f 59 16 0 0 2281 16 _null_ _null_ )); +DATA(insert ( 2519 n 0 booland_statefunc - - - - bool_accum bool_accum_inv bool_alltrue f f 58 16 0 0 2281 16 _null_ _null_ )); /* bitwise integer */ -DATA(insert ( 2236 n 0 int2and - int2and - - - f f 0 21 0 0 0 _null_ _null_ )); -DATA(insert ( 2237 n 0 int2or - int2or - - - f f 0 21 0 0 0 _null_ _null_ )); -DATA(insert ( 2238 n 0 int4and - int4and - - - f f 0 23 0 0 0 _null_ _null_ )); -DATA(insert ( 2239 n 0 int4or - int4or - - - f f 0 23 0 0 0 _null_ _null_ )); -DATA(insert ( 2240 n 0 int8and - int8and - - - f f 0 20 0 0 0 _null_ _null_ )); -DATA(insert ( 2241 n 0 int8or - int8or - - - f f 0 20 0 0 0 _null_ _null_ )); -DATA(insert ( 2242 n 0 bitand - bitand - - - f f 0 1560 0 0 0 _null_ _null_ )); -DATA(insert ( 2243 n 0 bitor - bitor - - - f f 0 1560 0 0 0 _null_ _null_ )); +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_ )); /* xml */ -DATA(insert ( 2901 n 0 xmlconcat2 - - - - - f f 0 142 0 0 0 _null_ _null_ )); +DATA(insert ( 2901 n 0 xmlconcat2 - - - - - - - f f 0 142 0 0 0 0 _null_ _null_ )); /* array */ -DATA(insert ( 2335 n 0 array_agg_transfn array_agg_finalfn - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - - t f 0 2281 0 0 0 _null_ _null_ )); +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_ )); /* text */ -DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); /* bytea */ -DATA(insert ( 3545 n 0 bytea_string_agg_transfn bytea_string_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 3545 n 0 bytea_string_agg_transfn bytea_string_agg_finalfn - - - - - - f f 0 2281 0 0 0 0 _null_ _null_ )); /* json */ -DATA(insert ( 3175 n 0 json_agg_transfn json_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3197 n 0 json_object_agg_transfn json_object_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); +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_ )); /* jsonb */ -DATA(insert ( 3267 n 0 jsonb_agg_transfn jsonb_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3270 n 0 jsonb_object_agg_transfn jsonb_object_agg_finalfn - - - - f f 0 2281 0 0 0 _null_ _null_ )); +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_ )); /* ordered-set and hypothetical-set aggregates */ -DATA(insert ( 3972 o 1 ordered_set_transition percentile_disc_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3974 o 1 ordered_set_transition percentile_cont_float8_final - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3976 o 1 ordered_set_transition percentile_cont_interval_final - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3978 o 1 ordered_set_transition percentile_disc_multi_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3980 o 1 ordered_set_transition percentile_cont_float8_multi_final - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3982 o 1 ordered_set_transition percentile_cont_interval_multi_final - - - - f f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3984 o 0 ordered_set_transition mode_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3986 h 1 ordered_set_transition_multi rank_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3988 h 1 ordered_set_transition_multi percent_rank_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3990 h 1 ordered_set_transition_multi cume_dist_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); -DATA(insert ( 3992 h 1 ordered_set_transition_multi dense_rank_final - - - - t f 0 2281 0 0 0 _null_ _null_ )); +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_ )); /* @@ -326,6 +335,8 @@ extern ObjectAddress AggregateCreate(const char *aggName, List *aggtransfnName, List *aggfinalfnName, List *aggcombinefnName, + List *aggserialfnName, + List *aggdeserialfnName, List *aggmtransfnName, List *aggminvtransfnName, List *aggmfinalfnName, @@ -333,6 +344,7 @@ 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/nodes/execnodes.h b/src/include/nodes/execnodes.h index bf2a09bc39c..dbec07e5a37 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1836,6 +1836,7 @@ typedef struct AggState bool agg_done; /* indicates completion of Agg scan */ bool combineStates; /* input tuples contain transition states */ bool finalizeAggs; /* should we call the finalfn on agg states? */ + bool serialStates; /* should agg states be (de)serialized? */ int projected_set; /* The last projected grouping set */ int current_set; /* The current grouping set being evaluated */ Bitmapset *grouped_cols; /* grouped cols in current projection */ diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 465d72fe890..ea8554f275c 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -712,6 +712,7 @@ typedef struct Agg AggStrategy aggstrategy; /* basic strategy, see nodes.h */ bool combineStates; /* input tuples contain transition states */ bool finalizeAggs; /* should we call the finalfn on agg states? */ + bool serialStates; /* should agg states be (de)serialized? */ int numCols; /* number of grouping columns */ AttrNumber *grpColIdx; /* their indexes in the target list */ Oid *grpOperators; /* equality operators to compare with */ diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 32f04b25dde..641446ca712 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -1296,6 +1296,7 @@ typedef struct AggPath List *qual; /* quals (HAVING quals), if any */ bool combineStates; /* input is partially aggregated agg states */ bool finalizeAggs; /* should the executor call the finalfn? */ + bool serialStates; /* should agg states be (de)serialized? */ } AggPath; /* diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 1744ff058e8..acc827de488 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -171,7 +171,8 @@ extern AggPath *create_agg_path(PlannerInfo *root, const AggClauseCosts *aggcosts, double numGroups, bool combineStates, - bool finalizeAggs); + bool finalizeAggs, + bool serialStates); extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 596ffb3d175..1f96e27034c 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -58,7 +58,7 @@ extern bool is_projection_capable_plan(Plan *plan); /* External use of these functions is deprecated: */ extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree); extern Agg *make_agg(List *tlist, List *qual, AggStrategy aggstrategy, - bool combineStates, bool finalizeAggs, + bool combineStates, bool finalizeAggs, bool serialStates, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree); diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index 699b61c528e..23ce8d6ce35 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -51,6 +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, + Expr **serialfnexpr); + extern void build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs, Oid agg_state_type, |