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

Reply via email to