Here are two more, cumulative with the previous patch and each other: The first removes the assumption in ordered_set_startup that the aggcontext can be cached in fn_extra, and puts it in the transvalue instead.
The second exposes the OSA* structures in a header file, so that user-defined ordered-set aggs can use ordered_set_transition[_multi] directly rather than having to cargo-cult it into their own code. -- Andrew (irc:RhodiumToad)
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index d116a63..92fa9f3 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -47,8 +47,6 @@ typedef struct OSAPerQueryState Aggref *aggref; /* Memory context containing this struct and other per-query data: */ MemoryContext qcontext; - /* Memory context containing per-group data: */ - MemoryContext gcontext; /* These fields are used only when accumulating tuples: */ @@ -86,6 +84,8 @@ typedef struct OSAPerGroupState { /* Link to the per-query state for this aggregate: */ OSAPerQueryState *qstate; + /* MemoryContext for per-group data */ + MemoryContext gcontext; /* Sort object we're accumulating data in: */ Tuplesortstate *sortstate; /* Number of normal rows inserted into sortstate: */ @@ -104,6 +104,15 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) OSAPerGroupState *osastate; OSAPerQueryState *qstate; MemoryContext oldcontext; + MemoryContext gcontext; + + /* + * Check we're called as aggregate (and not a window function), and + * get the Agg node's group-lifespan context (which might not be the + * same throughout the query, but will be the same for each transval) + */ + if (AggCheckCallContext(fcinfo, &gcontext) != AGG_CONTEXT_AGGREGATE) + elog(ERROR, "ordered-set aggregate called in non-aggregate context"); /* * We keep a link to the per-query state in fn_extra; if it's not there, @@ -114,16 +123,9 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) { Aggref *aggref; MemoryContext qcontext; - MemoryContext gcontext; List *sortlist; int numSortCols; - /* - * Check we're called as aggregate (and not a window function), and - * get the Agg node's group-lifespan context - */ - if (AggCheckCallContext(fcinfo, &gcontext) != AGG_CONTEXT_AGGREGATE) - elog(ERROR, "ordered-set aggregate called in non-aggregate context"); /* Need the Aggref as well */ aggref = AggGetAggref(fcinfo); if (!aggref) @@ -142,7 +144,6 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) qstate = (OSAPerQueryState *) palloc0(sizeof(OSAPerQueryState)); qstate->aggref = aggref; qstate->qcontext = qcontext; - qstate->gcontext = gcontext; /* Extract the sort information */ sortlist = aggref->aggorder; @@ -259,10 +260,11 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) } /* Now build the stuff we need in group-lifespan context */ - oldcontext = MemoryContextSwitchTo(qstate->gcontext); + oldcontext = MemoryContextSwitchTo(gcontext); osastate = (OSAPerGroupState *) palloc(sizeof(OSAPerGroupState)); osastate->qstate = qstate; + osastate->gcontext = gcontext; /* Initialize tuplesort object */ if (use_tuples)
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index 92fa9f3..bbad0e5 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -16,6 +16,8 @@ #include <math.h> +#include "utils/orderedset.h" + #include "catalog/pg_aggregate.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" @@ -30,71 +32,8 @@ #include "utils/tuplesort.h" -/* - * Generic support for ordered-set aggregates - * - * The state for an ordered-set aggregate is divided into a per-group struct - * (which is the internal-type transition state datum returned to nodeAgg.c) - * and a per-query struct, which contains data and sub-objects that we can - * create just once per query because they will not change across groups. - * The per-query struct and subsidiary data live in the executor's per-query - * memory context, and go away implicitly at ExecutorEnd(). - */ - -typedef struct OSAPerQueryState -{ - /* Aggref for this aggregate: */ - Aggref *aggref; - /* Memory context containing this struct and other per-query data: */ - MemoryContext qcontext; - - /* These fields are used only when accumulating tuples: */ - - /* Tuple descriptor for tuples inserted into sortstate: */ - TupleDesc tupdesc; - /* Tuple slot we can use for inserting/extracting tuples: */ - TupleTableSlot *tupslot; - /* Per-sort-column sorting information */ - int numSortCols; - AttrNumber *sortColIdx; - Oid *sortOperators; - Oid *eqOperators; - Oid *sortCollations; - bool *sortNullsFirsts; - /* Equality operator call info, created only if needed: */ - FmgrInfo *equalfns; - - /* These fields are used only when accumulating datums: */ - - /* Info about datatype of datums being sorted: */ - Oid sortColType; - int16 typLen; - bool typByVal; - char typAlign; - /* Info about sort ordering: */ - Oid sortOperator; - Oid eqOperator; - Oid sortCollation; - bool sortNullsFirst; - /* Equality operator call info, created only if needed: */ - FmgrInfo equalfn; -} OSAPerQueryState; - -typedef struct OSAPerGroupState -{ - /* Link to the per-query state for this aggregate: */ - OSAPerQueryState *qstate; - /* MemoryContext for per-group data */ - MemoryContext gcontext; - /* Sort object we're accumulating data in: */ - Tuplesortstate *sortstate; - /* Number of normal rows inserted into sortstate: */ - int64 number_of_rows; -} OSAPerGroupState; - static void ordered_set_shutdown(Datum arg); - /* * Set up working state for an ordered-set aggregate */ diff --git a/src/include/utils/orderedset.h b/src/include/utils/orderedset.h new file mode 100644 index 0000000..ab1113e --- /dev/null +++ b/src/include/utils/orderedset.h @@ -0,0 +1,82 @@ +/*------------------------------------------------------------------------- + * + * orderedset.h + * Generic support for ordered-set aggregates + * + * Ordered-set aggregates are free to supply their own transition functions, + * but it is expected that the same transition function will serve for almost + * all imaginable cases including the built-in ones. We therefore expose here + * the structures used by the builtin ordered_set_transition and + * ordered_set_transition_multi functions. + * + * User-defined ordered-set aggs can therefore use the stock transition + * function and supply their own final function to interpret the sorted data. + * + * The state for an ordered-set aggregate is divided into a per-group struct + * (which is the internal-type transition state datum returned to nodeAgg.c) + * and a per-query struct, which contains data and sub-objects that we can + * create just once per query because they will not change across groups. The + * per-query struct and subsidiary data live in the executor's per-query memory + * context, and go away implicitly at ExecutorEnd(). + */ +#ifndef ORDEREDSET_H +#define ORDEREDSET_H + +#include "nodes/primnodes.h" +#include "access/tupdesc.h" +#include "executor/tuptable.h" +#include "utils/tuplesort.h" +#include "fmgr.h" + +typedef struct OSAPerQueryState +{ + /* Aggref for this aggregate: */ + Aggref *aggref; + /* Memory context containing this struct and other per-query data: */ + MemoryContext qcontext; + + /* These fields are used only when accumulating tuples: */ + + /* Tuple descriptor for tuples inserted into sortstate: */ + TupleDesc tupdesc; + /* Tuple slot we can use for inserting/extracting tuples: */ + TupleTableSlot *tupslot; + /* Per-sort-column sorting information */ + int numSortCols; + AttrNumber *sortColIdx; + Oid *sortOperators; + Oid *eqOperators; + Oid *sortCollations; + bool *sortNullsFirsts; + /* Equality operator call info, created only if needed: */ + FmgrInfo *equalfns; + + /* These fields are used only when accumulating datums: */ + + /* Info about datatype of datums being sorted: */ + Oid sortColType; + int16 typLen; + bool typByVal; + char typAlign; + /* Info about sort ordering: */ + Oid sortOperator; + Oid eqOperator; + Oid sortCollation; + bool sortNullsFirst; + /* Equality operator call info, created only if needed: */ + FmgrInfo equalfn; +} OSAPerQueryState; + +typedef struct OSAPerGroupState +{ + /* Link to the per-query state for this aggregate: */ + OSAPerQueryState *qstate; + /* MemoryContext for per-group data */ + MemoryContext gcontext; + /* Sort object we're accumulating data in: */ + Tuplesortstate *sortstate; + /* Number of normal rows inserted into sortstate: */ + int64 number_of_rows; +} OSAPerGroupState; + +#endif /* ORDEREDSET_H */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers