of the component inside the collection.
</para>
- <para>NOTE: this function is not available for
- builds against PostgreSQL 7.2.x</para>
+ <para>
+ Availability: PostGIS 1.0.0RC1.
+ Requires PostgreSQL 7.3 or higher.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>DumpRings(geometry)</term>
+
+ <listitem>
+ <para>This is a set-returning function (SRF).
+ It returns a set of geometry_dump rows, formed
+ by a geometry (geom) and an array of integers (path).
+ The 'path' field holds the polygon ring index, contains
+ a single element: 0 for the shell, hole number for holes.
+ The 'geom' field contains the corresponding ring
+ as a polygon.
+ </para>
+
+ <para>
+ Availability: PostGIS 1.1.3.
+ Requires PostgreSQL 7.3 or higher.
+ </para>
+
</listitem>
</varlistentry>
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#include <assert.h>
#include "postgres.h"
#include "fmgr.h"
/*#define PGIS_DEBUG 1 */
Datum LWGEOM_dump(PG_FUNCTION_ARGS);
+Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS);
typedef struct GEOMDUMPNODE_T {
int idx;
SRF_RETURN_NEXT(funcctx, result);
}
+struct POLYDUMPSTATE {
+ int ringnum;
+ LWPOLY *poly;
+};
+
+PG_FUNCTION_INFO_V1(LWGEOM_dump_rings);
+Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS)
+{
+ PG_LWGEOM *pglwgeom;
+ LWGEOM *lwgeom;
+ FuncCallContext *funcctx;
+ struct POLYDUMPSTATE *state;
+ TupleDesc tupdesc;
+ TupleTableSlot *slot;
+ HeapTuple tuple;
+ AttInMetadata *attinmeta;
+ MemoryContext oldcontext, newcontext;
+ Datum result;
+ char address[256];
+ char *values[2];
+
+ if (SRF_IS_FIRSTCALL())
+ {
+ funcctx = SRF_FIRSTCALL_INIT();
+ newcontext = funcctx->multi_call_memory_ctx;
+
+ oldcontext = MemoryContextSwitchTo(newcontext);
+
+ pglwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+ if ( TYPE_GETTYPE(pglwgeom->type) != POLYGONTYPE )
+ {
+ lwerror("Input is not a polygon");
+ }
+
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(pglwgeom));
+
+ /* Create function state */
+ state = lwalloc(sizeof(struct POLYDUMPSTATE));
+ state->poly = lwgeom_as_lwpoly(lwgeom);
+ assert (state->poly);
+ state->ringnum=0;
+
+ funcctx->user_fctx = state;
+
+ /*
+ * Build a tuple description for an
+ * geometry_dump tuple
+ */
+ tupdesc = RelationNameGetTupleDesc("geometry_dump");
+
+ /* allocate a slot for a tuple with this tupdesc */
+ slot = TupleDescGetSlot(tupdesc);
+
+ /* allocate a slot for a tuple with this tupdesc */
+ slot = TupleDescGetSlot(tupdesc);
+
+ /* assign slot to function context */
+ funcctx->slot = slot;
+
+ /*
+ * generate attribute metadata needed later to produce
+ * tuples from raw C strings
+ */
+ attinmeta = TupleDescGetAttInMetadata(tupdesc);
+ funcctx->attinmeta = attinmeta;
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+ newcontext = funcctx->multi_call_memory_ctx;
+
+ /* get state */
+ state = funcctx->user_fctx;
+
+ /* Loop trough polygon rings */
+ while (state->ringnum < state->poly->nrings )
+ {
+ LWPOLY* poly = state->poly;
+
+ /* Switch to an appropriate memory context for POINTARRAY
+ * cloning and hexwkb allocation */
+ oldcontext = MemoryContextSwitchTo(newcontext);
+
+ /* We need a copy of input ring here */
+ POINTARRAY *ring = ptarray_clone(poly->rings[state->ringnum]);
+
+ /* Construct another polygon with shell only */
+ LWGEOM* ringgeom = (LWGEOM*)lwpoly_construct(
+ poly->SRID,
+ NULL, /* TODO: could use input bounding box here */
+ 1, /* one ring */
+ &ring);
+
+ /* Write path as ``{ <ringnum> }'' */
+ sprintf(address, "{%d}", state->ringnum);
+
+ values[0] = address;
+ values[1] = lwgeom_to_hexwkb(ringgeom, -1);
+
+ MemoryContextSwitchTo(oldcontext);
+
+ tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+ result = TupleGetDatum(funcctx->slot, tuple);
+ ++state->ringnum;
+ SRF_RETURN_NEXT(funcctx, result);
+ }
+
+ SRF_RETURN_DONE(funcctx);
+
+}
+
#endif /* USE_VERSION > 72 */
CREATE TYPE geometry_dump AS (path integer[], geom geometry);
-CREATEFUNCTION dump(geometry)
+CREATEFUNCTION Dump(geometry)
RETURNS SETOF geometry_dump
AS '@MODULE_FILENAME@', 'LWGEOM_dump'
LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+CREATEFUNCTION DumpRings(geometry)
+ RETURNS SETOF geometry_dump
+ AS '@MODULE_FILENAME@', 'LWGEOM_dump_rings'
+ LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
#endif
------------------------------------------------------------------------