1111 * This file is the property of the Digital Music Network (DMN).
1212 * It is being made available to users of the PostgreSQL system
1313 * under the BSD license.
14- *
15- * NOTE: This module requires sizeof(void *) to be the same as sizeof(int)
1614 */
1715#include "postgres.h"
1816
3634#include "utils/lsyscache.h"
3735
3836
39- /* Uncomment this define if you are compiling for postgres 7.2.x */
40- /* #define PG_7_2 */
41-
4237/* This is actually a postgres version of a one dimensional array */
4338
4439typedef struct
@@ -58,19 +53,17 @@ typedef struct callContext
5853}CTX ;
5954
6055#define TOASTED 1
61- #define START_NUM 8
62- #define PGARRAY_SIZE (n ) (sizeof(PGARRAY) + ((n -1)*sizeof(int4)))
56+ #define START_NUM 8/* initial size of arrays */
57+ #define PGARRAY_SIZE (n ) (sizeof(PGARRAY) + (((n) -1)*sizeof(int4)))
6358
64- static PGARRAY * GetPGArray (int4 state ,int fAdd );
65- static PGARRAY * ShrinkPGArray (PGARRAY * p );
59+ static PGARRAY * GetPGArray (PGARRAY * p ,int fAdd );
60+ static PGARRAY * ShrinkPGArray (PGARRAY * p );
6661
6762Datum int_agg_state (PG_FUNCTION_ARGS );
68- Datum int_agg_final_count (PG_FUNCTION_ARGS );
6963Datum int_agg_final_array (PG_FUNCTION_ARGS );
7064Datum int_enum (PG_FUNCTION_ARGS );
7165
7266PG_FUNCTION_INFO_V1 (int_agg_state );
73- PG_FUNCTION_INFO_V1 (int_agg_final_count );
7467PG_FUNCTION_INFO_V1 (int_agg_final_array );
7568PG_FUNCTION_INFO_V1 (int_enum );
7669
@@ -81,11 +74,9 @@ PG_FUNCTION_INFO_V1(int_enum);
8174 * PortalContext isn't really right, but it's close enough.
8275 */
8376static PGARRAY *
84- GetPGArray (int4 state ,int fAdd )
77+ GetPGArray (PGARRAY * p ,int fAdd )
8578{
86- PGARRAY * p = (PGARRAY * )state ;
87-
88- if (!state )
79+ if (!p )
8980{
9081/* New array */
9182int cb = PGARRAY_SIZE (START_NUM );
@@ -94,9 +85,7 @@ GetPGArray(int4 state, int fAdd)
9485p -> a .size = cb ;
9586p -> a .ndim = 0 ;
9687p -> a .flags = 0 ;
97- #ifndef PG_7_2
9888p -> a .elemtype = INT4OID ;
99- #endif
10089p -> items = 0 ;
10190p -> lower = START_NUM ;
10291}
@@ -118,7 +107,8 @@ GetPGArray(int4 state, int fAdd)
118107}
119108
120109/* Shrinks the array to its actual size and moves it into the standard
121- * memory allocation context, frees working memory*/
110+ * memory allocation context, frees working memory
111+ */
122112static PGARRAY *
123113ShrinkPGArray (PGARRAY * p )
124114{
@@ -139,10 +129,8 @@ ShrinkPGArray(PGARRAY * p)
139129pnew -> a .size = cb ;
140130pnew -> a .ndim = 1 ;
141131pnew -> a .flags = 0 ;
142- #ifndef PG_7_2
143132pnew -> a .elemtype = INT4OID ;
144- #endif
145- pnew -> lower = 0 ;
133+ pnew -> lower = 1 ;
146134
147135pfree (p );
148136}
@@ -153,28 +141,37 @@ ShrinkPGArray(PGARRAY * p)
153141Datum
154142int_agg_state (PG_FUNCTION_ARGS )
155143{
156- int4 state = PG_GETARG_INT32 (0 );
157- int4 value = PG_GETARG_INT32 (1 );
158-
159- PGARRAY * p = GetPGArray (state ,1 );
144+ PGARRAY * state ;
145+ PGARRAY * p ;
160146
161- if (!p )
162- /* internal error */
163- elog (ERROR ,"no aggregate storage" );
164- else if (p -> items >=p -> lower )
165- /* internal error */
166- elog (ERROR ,"aggregate storage too small" );
147+ if (PG_ARGISNULL (0 ))
148+ state = NULL ;
167149else
168- p -> array [p -> items ++ ]= value ;
169- PG_RETURN_INT32 (p );
150+ state = (PGARRAY * )PG_GETARG_POINTER (0 );
151+ p = GetPGArray (state ,1 );
152+
153+ if (!PG_ARGISNULL (1 ))
154+ {
155+ int4 value = PG_GETARG_INT32 (1 );
156+
157+ if (!p )/* internal error */
158+ elog (ERROR ,"no aggregate storage" );
159+ else if (p -> items >=p -> lower )/* internal error */
160+ elog (ERROR ,"aggregate storage too small" );
161+ else
162+ p -> array [p -> items ++ ]= value ;
163+ }
164+ PG_RETURN_POINTER (p );
170165}
171166
172- /* This is the final function used for the integer aggregator. It returns all the integers
173- * collected as a one dimensional integer array */
167+ /* This is the final function used for the integer aggregator. It returns all
168+ * the integers collected as a one dimensional integer array
169+ */
174170Datum
175171int_agg_final_array (PG_FUNCTION_ARGS )
176172{
177- PGARRAY * pnew = ShrinkPGArray (GetPGArray (PG_GETARG_INT32 (0 ),0 ));
173+ PGARRAY * state = (PGARRAY * )PG_GETARG_POINTER (0 );
174+ PGARRAY * pnew = ShrinkPGArray (GetPGArray (state ,0 ));
178175
179176if (pnew )
180177PG_RETURN_POINTER (pnew );
@@ -206,30 +203,23 @@ int_enum(PG_FUNCTION_ARGS)
206203/* Allocate a working context */
207204pc = (CTX * )palloc (sizeof (CTX ));
208205
209- /* Don't copy attribute if you don't needtoo */
206+ /* Don't copy attribute if you don't needto */
210207if (VARATT_IS_EXTENDED (p ))
211208{
212209/* Toasted!!! */
213210pc -> p = (PGARRAY * )PG_DETOAST_DATUM_COPY (p );
214211pc -> flags = TOASTED ;
215- if (!pc -> p )
216- {
217- /* internal error */
218- elog (ERROR ,"error in toaster; not detoasting" );
219- PG_RETURN_NULL ();
220- }
221212}
222213else
223214{
224215/* Untoasted */
225216pc -> p = p ;
226217pc -> flags = 0 ;
227218}
228- fcinfo -> context = (Node * )pc ;
229219pc -> num = 0 ;
220+ fcinfo -> context = (Node * )pc ;
230221}
231- else
232- /* use an existing one */
222+ else /* use an existing one */
233223pc = (CTX * )fcinfo -> context ;
234224/* Are we done yet? */
235225if (pc -> num >=pc -> p -> items )
@@ -242,8 +232,8 @@ int_enum(PG_FUNCTION_ARGS)
242232rsi -> isDone = ExprEndResult ;
243233}
244234else
245- /* nope, return the next value */
246235{
236+ /* nope, return the next value */
247237int val = pc -> p -> array [pc -> num ++ ];
248238
249239rsi -> isDone = ExprMultipleResult ;