[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