From: Sandro Santilli Date: Thu, 8 Nov 2012 08:40:56 +0000 (+0000) Subject: Rewrite topology.GetRingEdges using a recursive CTE (#2087) X-Git-Tag: 2.1.0beta2~408 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a4ce1e04b22469d2fa19d52978e9e93583fc7d68;p=postgis Rewrite topology.GetRingEdges using a recursive CTE (#2087) Walking around a ring of ~22k edges takes 1/7 of the time git-svn-id: http://svn.osgeo.org/postgis/trunk@10660 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/sql/query/GetRingEdges.sql.in.c b/topology/sql/query/GetRingEdges.sql.in.c index 3a1b71ecb..ed32bba7b 100644 --- a/topology/sql/query/GetRingEdges.sql.in.c +++ b/topology/sql/query/GetRingEdges.sql.in.c @@ -3,7 +3,7 @@ -- PostGIS - Spatial Types for PostgreSQL -- http://postgis.refractions.net -- --- Copyright (C) 2011 Sandro Santilli +-- Copyright (C) 2011 2012 Sandro Santilli -- -- This is free software; you can redistribute and/or modify it under -- the terms of the GNU General Public Licence. See the COPYING file. @@ -42,56 +42,31 @@ CREATE OR REPLACE FUNCTION topology.GetRingEdges(atopology varchar, anedge int, AS $$ DECLARE - curedge int; - nextedge int; rec RECORD; - bounds geometry; retrec topology.GetFaceEdges_ReturnType; n int; sql text; BEGIN + sql := 'WITH RECURSIVE edgering AS ( SELECT ' + || anedge + || ' as signed_edge_id, edge_id, next_left_edge, next_right_edge FROM ' + || quote_ident(atopology) + || '.edge_data WHERE edge_id = ' + || abs(anedge) + || ' UNION ' + || ' SELECT CASE WHEN p.signed_edge_id < 0 THEN p.next_right_edge ' + || ' ELSE p.next_left_edge END, e.edge_id, e.next_left_edge, e.next_right_edge ' + || ' FROM ' || quote_ident(atopology) + || '.edge_data e, edgering p WHERE e.edge_id = CASE WHEN p.signed_edge_id < 0 ' + || 'THEN abs(p.next_right_edge) ELSE abs(p.next_left_edge) END ) SELECT * FROM edgering'; - curedge := anedge; n := 1; - - WHILE true LOOP - sql := 'SELECT edge_id, next_left_edge, next_right_edge FROM ' - || quote_ident(atopology) || '.edge_data WHERE edge_id = ' - || abs(curedge); - EXECUTE sql INTO rec; + FOR rec IN EXECUTE sql + LOOP retrec.sequence := n; - retrec.edge := curedge; - -#ifdef POSTGIS_TOPOLOGY_DEBUG - RAISE DEBUG 'Edge:% left:% right:%', - curedge, rec.next_left_edge, rec.next_right_edge; -#endif - + retrec.edge := rec.signed_edge_id; RETURN NEXT retrec; - IF curedge < 0 THEN - nextedge := rec.next_right_edge; - ELSE - nextedge := rec.next_left_edge; - END IF; - - IF nextedge = anedge THEN -#ifdef POSTGIS_TOPOLOGY_DEBUG - RAISE DEBUG ' finish'; -#endif - RETURN; - END IF; - - IF nextedge = curedge THEN - RAISE EXCEPTION 'Detected bogus loop traversing edge %', curedge; - END IF; - - curedge := nextedge; - -#ifdef POSTGIS_TOPOLOGY_DEBUG - RAISE DEBUG ' curedge:% anedge:%', curedge, anedge; -#endif - n := n + 1; IF n > maxedges THEN