]> granicus.if.org Git - postgis/commitdiff
Forbid healing edges if any feature is defined by only one of the two [RT-SIGTA]
authorSandro Santilli <strk@keybit.net>
Wed, 4 May 2011 18:20:01 +0000 (18:20 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 4 May 2011 18:20:01 +0000 (18:20 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@7087 b70326c6-7e19-0410-871a-916f4a2858ee

topology/sql/sqlmm.sql
topology/test/regress/st_modedgeheal.sql
topology/test/regress/st_modedgeheal_expected

index 6d4617ceab03e095e33f374836bd9ddf8b390d1d..5518af3d56c137ccab585636c5916876ff4c47df 100644 (file)
@@ -112,6 +112,9 @@ LANGUAGE 'plpgsql' VOLATILE;
 -- * Returns the id of the node being removed
 -- * Refuses to heal two edges if any of the two is closed 
 -- * Raise an exception when trying to heal an edge with itself
+-- * Raise an exception if any TopoGeometry is defined by only one
+--   of the two edges
+-- * Update references in the Relation table.
 -- 
 CREATE OR REPLACE FUNCTION topology.ST_ModEdgeHeal(toponame varchar, e1id integer, e2id integer)
   RETURNS int
@@ -123,8 +126,10 @@ DECLARE
   rec RECORD;
   commonnode int;
   caseno int;
+  topoid int;
   sql text;
   e2sign int;
+  eidary int[];
 BEGIN
   --
   -- toponame and face_id are required
@@ -138,10 +143,42 @@ BEGIN
     RAISE EXCEPTION 'Cannot heal edge % with itself, try with another', e1id;
   END IF;
 
-  -- NOT IN THE SPECS: check toponame is not empty
-  IF toponame = '' THEN
-    RAISE EXCEPTION 'Invalid (empty) topology name';
-  END IF;
+       -- Get topology id
+  BEGIN
+    SELECT id FROM topology.topology
+      INTO STRICT topoid WHERE name = toponame;
+    EXCEPTION
+      WHEN NO_DATA_FOUND THEN
+        RAISE EXCEPTION 'unknown topology "%"', toponame;
+  END;
+
+  -- NOT IN THE SPECS:
+  -- check if any topo_geom is defined only by one of the
+  -- input edges. In such case there would be no way to adapt
+  -- the definition in case of healing, so we'd have to bail out
+  eidary = ARRAY[e1id, e2id];
+  sql := 'SELECT t.* from ('
+    || 'SELECT r.topogeo_id, r.layer_id'
+    || ', l.schema_name, l.table_name, l.feature_column'
+    || ', array_agg(abs(r.element_id)) as elems '
+    || 'FROM topology.layer l INNER JOIN '
+    || quote_ident(toponame)
+    || '.relation r ON (l.layer_id = r.layer_id) '
+    || 'WHERE l.level = 0 AND l.feature_type = 2 '
+    || ' AND l.topology_id = ' || topoid
+    || ' AND abs(r.element_id) IN (' || e1id || ',' || e2id || ') '
+    || 'group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
+    || ' l.feature_column ) t WHERE t.elems && '
+    || quote_literal(eidary) 
+    || ' AND NOT t.elems @> '
+    || quote_literal(eidary);
+  RAISE DEBUG 'SQL: %', sql;
+  FOR rec IN EXECUTE sql LOOP
+    RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing edges % and %',
+          rec.topogeo_id, rec.layer_id,
+          rec.schema_name, rec.table_name, rec.feature_column,
+          e1id, e2id;
+  END LOOP;
 
   BEGIN
     EXECUTE 'SELECT * FROM ' || quote_ident(toponame)
@@ -151,9 +188,9 @@ BEGIN
       WHEN NO_DATA_FOUND THEN
         RAISE EXCEPTION 'SQL/MM Spatial exception – non-existent edge %', e1id;
       WHEN INVALID_SCHEMA_NAME THEN
-        RAISE EXCEPTION 'non-existent topology "%"', toponame;
+        RAISE EXCEPTION 'non-existent topology schema "%"', toponame;
       WHEN UNDEFINED_TABLE THEN
-        RAISE EXCEPTION 'Invalid topology "%" (missing edge_data table)',
+        RAISE EXCEPTION 'corrupted topology "%" (missing edge_data table)',
           toponame;
   END;
 
@@ -282,10 +319,21 @@ BEGIN
             || '.node WHERE node_id = ' || commonnode;
     EXCEPTION
       WHEN UNDEFINED_TABLE THEN
-        RAISE EXCEPTION 'Invalid topology "%" (missing node table)',
+        RAISE EXCEPTION 'corrupted topology "%" (missing node table)',
           toponame;
   END;
 
+       --
+  -- NOT IN THE SPECS:
+       -- Update references in the Relation table.
+       -- We only take into considerations non-hierarchical
+       -- TopoGeometry here, for obvious reasons.
+       --
+
+  -- Now we can safely drop composition rows involving second
+  -- edge, as the first edge took its space.
+
+
        RETURN commonnode;
 END
 $$
@@ -677,6 +725,9 @@ LANGUAGE 'plpgsql' VOLATILE;
 --
 --  ST_NewEdgesSplit(atopology, anedge, apoint)
 --
+-- Not in the specs:
+-- * Update references in the Relation table.
+--
 CREATE OR REPLACE FUNCTION topology.ST_NewEdgesSplit(varchar, integer, geometry)
        RETURNS INTEGER AS
 $$
@@ -938,6 +989,9 @@ LANGUAGE 'plpgsql' VOLATILE;
 --
 --  ST_ModEdgeSplit(atopology, anedge, apoint)
 --
+-- Not in the specs:
+-- * Update references in the Relation table.
+--
 CREATE OR REPLACE FUNCTION topology.ST_ModEdgeSplit(varchar, integer, geometry)
        RETURNS INTEGER AS
 $$
index 1b5852fd6c359fee172b9841ab7a7f8ffdb8ebed..9ecb82f9a4a4f44ce1884fc4497b2416c4679c5e 100644 (file)
@@ -8,8 +8,6 @@ SELECT topology.ST_ModEdgeHeal('city_data', 1, null);
 SELECT topology.ST_ModEdgeHeal('city_data', null, 1);
 SELECT topology.ST_ModEdgeHeal(null, 1, 2);
 SELECT topology.ST_ModEdgeHeal('', 1, 2);
-SELECT topology.ST_ModEdgeHeal('  ', 1, 2);
-SELECT topology.ST_ModEdgeHeal('public', 1, 2);
 
 -- Not connected edges
 SELECT topology.ST_ModEdgeHeal('city_data', 25, 3);
@@ -58,3 +56,6 @@ SELECT 'N'||node_id FROM city_data.node;
 SELECT topology.DropTopology('city_data');
 
 -- TODO: add TopoGeometry tests !
+-- TODO: test registered but unexistent topology
+-- TODO: test registered but corrupted topology
+--       (missing node, edge, relation...)
index 3a832f3e57591ab31224fbb3511f326a42f8448a..392a65788fa5f963de0d35094875ae04691fc563 100644 (file)
@@ -7,9 +7,7 @@ COMMIT
 ERROR:  SQL/MM Spatial exception - null argument
 ERROR:  SQL/MM Spatial exception - null argument
 ERROR:  SQL/MM Spatial exception - null argument
-ERROR:  Invalid (empty) topology name
-ERROR:  non-existent topology "  "
-ERROR:  Invalid topology "public" (missing edge_data table)
+ERROR:  unknown topology ""
 ERROR:  SQL/MM Spatial exception – non-connected edges
 ERROR:  SQL/MM Spatial exception – other edges connected (ie: 19)
 ERROR:  Edge 2 is closed, cannot heal to edge 3