e2rec RECORD;
rec RECORD;
newedgeid int;
+ connectededges int[];
commonnode int;
caseno int;
topoid int;
END IF;
-- Find common node
+
IF e1rec.end_node = e2rec.start_node THEN
commonnode = e1rec.end_node;
caseno = 1;
ELSIF e1rec.end_node = e2rec.end_node THEN
commonnode = e1rec.end_node;
caseno = 2;
- ELSIF e1rec.start_node = e2rec.start_node THEN
- commonnode = e1rec.start_node;
- caseno = 3;
- ELSIF e1rec.start_node = e2rec.end_node THEN
- commonnode = e1rec.start_node;
- caseno = 4;
- ELSE
- RAISE EXCEPTION 'SQL/MM Spatial exception - non-connected edges';
END IF;
-- Check if any other edge is connected to the common node
- FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
- || '.edge_data WHERE ( edge_id != ' || e1id
- || ' AND edge_id != ' || e2id || ') AND ( start_node = '
- || commonnode || ' OR end_node = ' || commonnode || ' )'
- LOOP
- RAISE EXCEPTION
- 'SQL/MM Spatial exception - other edges connected (ie: %)', rec.edge_id;
- END LOOP;
+ IF commonnode IS NOT NULL THEN
+ FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
+ || '.edge_data WHERE ( edge_id != ' || e1id
+ || ' AND edge_id != ' || e2id || ') AND ( start_node = '
+ || commonnode || ' OR end_node = ' || commonnode || ' )'
+ LOOP
+ commonnode := NULL;
+ connectededges = connectededges || rec.edge_id;
+ END LOOP;
+ END IF;
+
+ IF commonnode IS NULL THEN
+ IF e1rec.start_node = e2rec.start_node THEN
+ commonnode = e1rec.start_node;
+ caseno = 3;
+ ELSIF e1rec.start_node = e2rec.end_node THEN
+ commonnode = e1rec.start_node;
+ caseno = 4;
+ END IF;
+
+ -- Check if any other edge is connected to the common node
+ IF commonnode IS NOT NULL THEN
+ FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
+ || '.edge_data WHERE ( edge_id != ' || e1id
+ || ' AND edge_id != ' || e2id || ') AND ( start_node = '
+ || commonnode || ' OR end_node = ' || commonnode || ' )'
+ LOOP
+ commonnode := NULL;
+ connectededges = connectededges || rec.edge_id;
+ END LOOP;
+ END IF;
+ END IF;
+
+ IF commonnode IS NULL THEN
+ IF connectededges IS NOT NULL THEN
+ RAISE EXCEPTION 'SQL/MM Spatial exception - other edges connected (%)', array_to_string(connectededges, ',');
+ ELSE
+ RAISE EXCEPTION 'SQL/MM Spatial exception - non-connected edges';
+ END IF;
+ END IF;
-- NOT IN THE SPECS:
-- check if any topo_geom is defined only by one of the
e1rec RECORD;
e2rec RECORD;
rec RECORD;
+ connectededges int[];
commonnode int;
caseno int;
topoid int;
END IF;
-- Find common node
+
IF e1rec.end_node = e2rec.start_node THEN
commonnode = e1rec.end_node;
caseno = 1;
ELSIF e1rec.end_node = e2rec.end_node THEN
commonnode = e1rec.end_node;
caseno = 2;
- ELSIF e1rec.start_node = e2rec.start_node THEN
- commonnode = e1rec.start_node;
- caseno = 3;
- ELSIF e1rec.start_node = e2rec.end_node THEN
- commonnode = e1rec.start_node;
- caseno = 4;
- ELSE
- RAISE EXCEPTION 'SQL/MM Spatial exception - non-connected edges';
END IF;
-- Check if any other edge is connected to the common node
- FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
- || '.edge_data WHERE ( edge_id != ' || e1id
- || ' AND edge_id != ' || e2id || ') AND ( start_node = '
- || commonnode || ' OR end_node = ' || commonnode || ' )'
- LOOP
- RAISE EXCEPTION
- 'SQL/MM Spatial exception - other edges connected (ie: %)', rec.edge_id;
- END LOOP;
+ IF commonnode IS NOT NULL THEN
+ FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
+ || '.edge_data WHERE ( edge_id != ' || e1id
+ || ' AND edge_id != ' || e2id || ') AND ( start_node = '
+ || commonnode || ' OR end_node = ' || commonnode || ' )'
+ LOOP
+ commonnode := NULL;
+ connectededges = connectededges || rec.edge_id;
+ END LOOP;
+ END IF;
+
+ IF commonnode IS NULL THEN
+ IF e1rec.start_node = e2rec.start_node THEN
+ commonnode = e1rec.start_node;
+ caseno = 3;
+ ELSIF e1rec.start_node = e2rec.end_node THEN
+ commonnode = e1rec.start_node;
+ caseno = 4;
+ END IF;
+
+ -- Check if any other edge is connected to the common node
+ IF commonnode IS NOT NULL THEN
+ FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(toponame)
+ || '.edge_data WHERE ( edge_id != ' || e1id
+ || ' AND edge_id != ' || e2id || ') AND ( start_node = '
+ || commonnode || ' OR end_node = ' || commonnode || ' )'
+ LOOP
+ commonnode := NULL;
+ connectededges = connectededges || rec.edge_id;
+ END LOOP;
+ END IF;
+ END IF;
+
+ IF commonnode IS NULL THEN
+ IF connectededges IS NOT NULL THEN
+ RAISE EXCEPTION 'SQL/MM Spatial exception - other edges connected (%)', array_to_string(connectededges, ',');
+ ELSE
+ RAISE EXCEPTION 'SQL/MM Spatial exception - non-connected edges';
+ END IF;
+ END IF;
-- NOT IN THE SPECS:
-- check if any topo_geom is defined only by one of the
-------------------------------------------------------------------------
-------------------------------------------------------------------------
+-- Test edges sharing both endpoints
+-- See http://trac.osgeo.org/postgis/ticket/1955
+
+SELECT '#1955', topology.CreateTopology('t') > 1;
+
+SELECT '#1955.1', 'E'||topology.AddEdge('t', 'LINESTRING(0 0, 10 0, 10 10)'); -- 1
+SELECT '#1955.1', 'E'||topology.AddEdge('t', 'LINESTRING(0 0, 0 10, 10 10)'); ; -- 2
+
+SELECT '#1955.1', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Deletes second node. Not very predictable which one is removed
+SELECT '#1955.1', 'H:1,2', 'N' || topology.ST_ModEdgeHeal('t', 1, 2), 'deleted';
+
+SELECT '#1955.1', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(50 0, 60 0, 60 10)'); -- 3
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(50 0, 50 10, 60 10)'); ; -- 4
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(60 10, 70 10)'); ; -- 5
+
+SELECT '#1955.2', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Only the start node can be deleted (50 0) because the other is shared by
+-- another edge
+SELECT '#1955.2', 'H:3,4', 'N' || topology.ST_ModEdgeHeal('t', 3, 4), 'deleted';
+
+SELECT '#1955.2', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(80 0, 90 0, 90 10)'); -- 6
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(80 0, 80 10, 90 10)'); ; -- 7
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(70 10, 80 0)'); ; -- 8
+
+SELECT '#1955.3', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Only the end node can be deleted (90 10) because the other is shared by
+-- another edge
+SELECT '#1955.3', 'H:6,7', 'N' || topology.ST_ModEdgeHeal('t', 6, 7), 'deleted';
+
+SELECT '#1955.3', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955', topology.DropTopology('t');
+
+-------------------------------------------------------------------------
+-------------------------------------------------------------------------
+-------------------------------------------------------------------------
+
-- TODO: test registered but unexistent topology
-- TODO: test registered but corrupted topology
-- (missing node, edge, relation...)
ERROR: SQL/MM Spatial exception - null argument
ERROR: SQL/MM Spatial exception - invalid topology name
ERROR: SQL/MM Spatial exception - non-connected edges
-ERROR: SQL/MM Spatial exception - other edges connected (ie: 19)
+ERROR: SQL/MM Spatial exception - other edges connected (19,20)
ERROR: Edge 2 is closed, cannot heal to edge 3
ERROR: Edge 2 is closed, cannot heal to edge 3
ERROR: Cannot heal edge 25 with itself, try with another
2|3
3|-3
Topology 't' dropped
+#1955|t
+#1955.1|E1
+#1955.1|E2
+#1955.1|2|start nodes
+#1955.1|H:1,2|N2|deleted
+#1955.1|1|nodes left
+#1955.2|E3
+#1955.2|E4
+#1955.2|E5
+#1955.2|4|start nodes
+#1955.2|H:3,4|N3|deleted
+#1955.2|3|nodes left
+#1955.3|E6
+#1955.3|E7
+#1955.3|E8
+#1955.3|5|start nodes
+#1955.3|H:6,7|N7|deleted
+#1955.3|4|nodes left
+#1955|Topology 't' dropped
-------------------------------------------------------------------------
-------------------------------------------------------------------------
+SELECT '#1955', topology.CreateTopology('t') > 1;
+
+SELECT '#1955.1', 'E'||topology.AddEdge('t', 'LINESTRING(0 0, 10 0, 10 10)'); -- 1
+SELECT '#1955.1', 'E'||topology.AddEdge('t', 'LINESTRING(0 0, 0 10, 10 10)'); ; -- 2
+
+SELECT '#1955.1', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Deletes second node. Not very predictable which one is removed
+SELECT '#1955.1', 'H:1,2', 'E' || topology.ST_NewEdgeHeal('t', 1, 2), 'created';
+
+SELECT '#1955.1', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(50 0, 60 0, 60 10)'); -- 4
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(50 0, 50 10, 60 10)'); ; -- 5
+SELECT '#1955.2', 'E'||topology.AddEdge('t', 'LINESTRING(60 10, 70 10)'); ; -- 6
+
+SELECT '#1955.2', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Only the start node can be deleted (50 0) because the other is shared by
+-- another edge
+SELECT '#1955.2', 'H:4,5', 'E' || topology.ST_NewEdgeHeal('t', 4, 5), 'created';
+
+SELECT '#1955.2', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(80 0, 90 0, 90 10)'); -- 8
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(80 0, 80 10, 90 10)'); ; -- 9
+SELECT '#1955.3', 'E'||topology.AddEdge('t', 'LINESTRING(70 10, 80 0)'); ; -- 10
+
+SELECT '#1955.3', count(node_id), 'start nodes' as label FROM t.node GROUP BY label;
+
+-- Only the end node can be deleted (90 10) because the other is shared by
+-- another edge
+SELECT '#1955.3', 'H:8,9', 'E' || topology.ST_NewEdgeHeal('t', 8, 9), 'created';
+
+SELECT '#1955.3', count(node_id), 'nodes left' as label FROM t.node GROUP BY label;
+
+SELECT '#1955', topology.DropTopology('t');
+
+-------------------------------------------------------------------------
+-------------------------------------------------------------------------
+-------------------------------------------------------------------------
+
+
-- TODO: test registered but unexistent topology
-- TODO: test registered but corrupted topology
-- (missing node, edge, relation...)
ERROR: SQL/MM Spatial exception - null argument
ERROR: SQL/MM Spatial exception - invalid topology name
ERROR: SQL/MM Spatial exception - non-connected edges
-ERROR: SQL/MM Spatial exception - other edges connected (ie: 19)
+ERROR: SQL/MM Spatial exception - other edges connected (19,20)
ERROR: Edge 2 is closed, cannot heal to edge 3
ERROR: Edge 2 is closed, cannot heal to edge 3
ERROR: Cannot heal edge 25 with itself, try with another
2|5
3|-5
Topology 't' dropped
+#1955|t
+#1955.1|E1
+#1955.1|E2
+#1955.1|2|start nodes
+#1955.1|H:1,2|E3|created
+#1955.1|1|nodes left
+#1955.2|E4
+#1955.2|E5
+#1955.2|E6
+#1955.2|4|start nodes
+#1955.2|H:4,5|E7|created
+#1955.2|3|nodes left
+#1955.3|E8
+#1955.3|E9
+#1955.3|E10
+#1955.3|5|start nodes
+#1955.3|H:8,9|E11|created
+#1955.3|4|nodes left
+#1955|Topology 't' dropped