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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers