[postgis-commits] svn - r3552 - trunk/lwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Wed Jan 21 17:39:13 PST 2009


Author: pramsey
Date: 2009-01-21 17:39:13 -0800 (Wed, 21 Jan 2009)
New Revision: 3552

Added:
   trunk/lwgeom/lwgeom_accum.c
Modified:
   trunk/lwgeom/Makefile.in
   trunk/lwgeom/postgis.sql.in.c
Log:
First stab at a back-port of the array_agg from 8.4. Our's isn't generic, and it's got it's own name, so it won't collide, ... needs testing on PgSQL < 8.3 still.


Modified: trunk/lwgeom/Makefile.in
===================================================================
--- trunk/lwgeom/Makefile.in	2009-01-22 01:16:10 UTC (rev 3551)
+++ trunk/lwgeom/Makefile.in	2009-01-22 01:39:13 UTC (rev 3552)
@@ -22,6 +22,7 @@
 # PostgreSQL objects
 PG_OBJS=lwgeom_pg.o \
 	lwgeom_debug.o \
+	lwgeom_accum.o \
 	lwgeom_spheroid.o \
 	lwgeom_ogc.o \
 	lwgeom_functions_analytic.o \

Added: trunk/lwgeom/lwgeom_accum.c
===================================================================
--- trunk/lwgeom/lwgeom_accum.c	2009-01-22 01:16:10 UTC (rev 3551)
+++ trunk/lwgeom/lwgeom_accum.c	2009-01-22 01:39:13 UTC (rev 3552)
@@ -0,0 +1,105 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2009 Paul Ramsey <pramsey at opengeo.org>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "funcapi.h"
+#include "access/tupmacs.h"
+#include "utils/array.h"
+#include "utils/lsyscache.h"
+
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
+
+Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS);
+Datum pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS);
+
+/*
+ * ARRAY_AGG aggregate function
+ */
+PG_FUNCTION_INFO_V1(pgis_geometry_accum_transfn);
+Datum
+pgis_geometry_accum_transfn(PG_FUNCTION_ARGS)
+{
+	Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
+	MemoryContext aggcontext;
+	ArrayBuildState *state;
+	Datum		elem;
+
+	if (arg1_typeid == InvalidOid)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("could not determine input data type")));
+
+	if (fcinfo->context && IsA(fcinfo->context, AggState))
+		aggcontext = ((AggState *) fcinfo->context)->aggcontext;
+#if POSTGIS_PGSQL_VERSION >= 84
+	else if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
+		aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
+#endif
+	else
+	{
+		/* cannot be called directly because of internal-type argument */
+		elog(ERROR, "array_agg_transfn called in non-aggregate context");
+		aggcontext = NULL;		/* keep compiler quiet */
+	}
+
+	state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
+	elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
+	state = accumArrayResult(state,
+							 elem,
+							 PG_ARGISNULL(1),
+							 arg1_typeid,
+							 aggcontext);
+
+	/*
+	 * The transition type for array_agg() is declared to be "internal",
+	 * which is a pass-by-value type the same size as a pointer.  So we
+	 * can safely pass the ArrayBuildState pointer through nodeAgg.c's
+	 * machinations.
+	 */
+	PG_RETURN_POINTER(state);
+}
+
+PG_FUNCTION_INFO_V1(pgis_geometry_accum_finalfn);
+Datum
+pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS)
+{
+	Datum		result;
+	ArrayBuildState *state;
+	int			dims[1];
+	int			lbs[1];
+
+	/* cannot be called directly because of internal-type argument */
+	Assert(fcinfo->context &&
+		   (IsA(fcinfo->context, AggState) ||
+			IsA(fcinfo->context, WindowAggState)));
+
+	if (PG_ARGISNULL(0))
+		PG_RETURN_NULL();   /* returns null iff no input values */
+
+	state = (ArrayBuildState *) PG_GETARG_POINTER(0);
+
+	dims[0] = state->nelems;
+	lbs[0] = 1;
+
+#if POSTGIS_PGSQL_VERSION < 84
+    result = makeMdArrayResult(state, 1, dims, lbs,
+                               CurrentMemoryContext);
+#else
+	/* Release working state if regular aggregate, but not if window agg */
+ 	result = makeMdArrayResult(state, 1, dims, lbs,
+                       	       CurrentMemoryContext,
+                       	       IsA(fcinfo->context, AggState));
+#endif
+	PG_RETURN_DATUM(result);
+}
\ No newline at end of file

Modified: trunk/lwgeom/postgis.sql.in.c
===================================================================
--- trunk/lwgeom/postgis.sql.in.c	2009-01-22 01:16:10 UTC (rev 3551)
+++ trunk/lwgeom/postgis.sql.in.c	2009-01-22 01:39:13 UTC (rev 3552)
@@ -4042,6 +4042,31 @@
 	stype = geometry
 	);
 
+#if 0
+-- Availability: 1.4.0
+CREATE FUNCTION pgis_geometry_accum_transfn(int, geometry)
+    RETURNS int
+    AS 'MODULE_PATHNAME' LANGUAGE 'C';
+    
+-- Availability: 1.4.0
+CREATE FUNCTION pgis_geometry_accum_finalfn(int)
+    RETURNS geometry[]
+    AS 'MODULE_PATHNAME' LANGUAGE 'C';
+
+-- Availability: 1.4.0
+CREATE AGGREGATE ST_GeometryArray (
+    BASETYPE = geometry,
+    SFUNC = pgis_geometry_accum_transfn,
+    STYPE = int,
+    FINALFUNC = pgis_geometry_accum_finalfn
+    );
+
+UPDATE pg_aggregate SET aggtranstype = 2281 WHERE aggfnoid = 'st_geometryarray'::regproc;
+UPDATE pg_proc SET prorettype = 2281 WHERE oid = 'pgis_geometry_accum_transfn'::regproc;
+UPDATE pg_proc SET proargtypes = ('2281 ' || proargtypes[1]::text)::oidvector WHERE oid = 'pgis_geometry_accum_transfn'::regproc;
+UPDATE pg_proc SET proargtypes = '2281' WHERE oid = 'pgis_geometry_accum_finalfn'::regproc;
+#endif
+
 -- Deprecation in 1.2.3
 CREATEFUNCTION unite_garray (geometry[])
 	RETURNS geometry



More information about the postgis-commits mailing list