[postgis-users] Feeding geometries into a custom SRF query
Michael Toews
mwtoews at sfu.ca
Wed May 27 13:46:17 PDT 2009
Hi,
I'm blanking out on how to write the SQL query for this. I have a custom ST_DumpPoints(geometry) set returning function (SRF) written in PL/pgSQL that returns a set of geometry_dump items[1]. Since it is not written in C/SQL, I cannot use the SRF like I can with ST_Dump or generate_series of the form:
SELECT (ST_Dump(geometry)).geom FROM mytable;
.. works to extract the geom from the geometry_dump data type.
Instead, using my PL/pgSQL function:
SELECT (ST_DumpPoints(geometry)).geom FROM mytable;
ERROR: set-valued function called in context that cannot accept a set
For some undocumented reason, PostgreSQL cannot use a SRF written in plpgsql on the left-side of "FROM". Only SRF written in sql or c can do this[2]. I am instead forced to rewrite the SQL query in the form SELECT * FROM mysrf(value), or in my case:
SELECT * FROM ST_DumpPoints('MULTIPOLYGON(((-0.57 0.46,-0.85 0.08,0 0.03,-0.57 0.46)),((-0.52 0.02,-0.66 -0.04,-0.46 -0.18,-0.52 0.02)))'::geometry);
or something similar where I need to type the geometry in after the "FROM" part.
How can I rewrite this SQL statement so I'm selecting the geometry into the SRF on the right-side of the "FROM" part? I can't seem write this SQL query, and I don't want to copy/paste the geometry for each object.
Thanks in advance.
-Mike
[1] This half-thought-out function assumes multipolygon geometry; only uses boundary linestring (no inner rings); path::integer[] has the base-1 info format {geometry_number, point_number}. There is probably a better way to write this, but I'm not sure how. If written in pure sql, I would be able to query using the SRF on the left of FROM making the SQL easier to write. Here is what I have:
CREATE OR REPLACE FUNCTION ST_DumpPoints(geometry)
RETURNS SETOF geometry_dump AS
$BODY$DECLARE
m integer;
g geometry;
n integer;
p geometry_dump%rowtype;
BEGIN
FOR m IN SELECT generate_series(1, ST_NumGeometries($1)) LOOP
p.path[1] := m; -- use to store Multipolygon number
g := ST_Boundary(ST_GeometryN($1, m));
FOR n IN SELECT generate_series(1, ST_NumPoints(g) - 1) LOOP
p.path[2] := n; -- use to store Point number
p.geom := ST_PointN(g, n);
RETURN NEXT p;
END LOOP;
END LOOP;
RETURN;
END;$BODY$
LANGUAGE 'plpgsql' IMMUTABLE STRICT
COST 100
ROWS 1000;
-- Test it (with compliant SRF on right of "FROM"):
SELECT path, astext(geom) FROM ST_DumpPoints('MULTIPOLYGON(((-0.57 0.46,-0.85 0.08,0 0.03,-0.57 0.46)),((-0.52 0.02,-0.66 -0.04,-0.46 -0.18,-0.52 0.02)))'::geometry);
[2] Background discussion on PG issues with SRF with non c/sql functions is here:
http://postgis.refractions.net/pipermail/postgis-users/2006-March/thread.html#11568
More information about the postgis-users
mailing list