]> granicus.if.org Git - postgis/commitdiff
Have TopoGeometry::Geometry always return a MULTI* (#1462)
authorSandro Santilli <strk@keybit.net>
Fri, 20 Jan 2012 14:47:36 +0000 (14:47 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 20 Jan 2012 14:47:36 +0000 (14:47 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8893 b70326c6-7e19-0410-871a-916f4a2858ee

topology/test/regress/createtopogeom_expected
topology/test/regress/legacy_query_expected
topology/test/regress/topo2.5d_expected
topology/test/regress/totopogeom_expected
topology/topology.sql.in.c

index 95af83eb50a0a4e9ed20b70d1f77dfbe1327c87c..a6102229f394a2e71d2524aa721dad1aece97118 100644 (file)
@@ -13,20 +13,20 @@ l2|2
 n2|2
 e1|1
 ERROR:  A TopoGeometry of type 2 cannot contain topology elements of type 1
-L1|LINESTRING(0 0,10 0)
+L1|MULTILINESTRING((0 0,10 0))
 l3|3
 e2|2
 f1|1
 ERROR:  A Layer of type 3 cannot contain a TopoGeometry of type 2
 ERROR:  A TopoGeometry of type 3 cannot contain topology elements of type 2
-A1|POLYGON((10 0,0 0,5 5,10 0))
+A1|MULTIPOLYGON(((10 0,0 0,5 5,10 0)))
 l4|4
-MP|POINT(0 0)
-ML|LINESTRING(0 0,10 0)
-MA|POLYGON((10 0,0 0,5 5,10 0))
+MP|MULTIPOINT(0 0)
+ML|MULTILINESTRING((0 0,10 0))
+MA|MULTIPOLYGON(((10 0,0 0,5 5,10 0)))
 MM|GEOMETRYCOLLECTION(POLYGON((10 0,0 0,5 5,10 0)),LINESTRING(0 0,10 0),POINT(0 0))
-POINT EMPTY|POINT EMPTY
-LINESTRING EMPTY|LINESTRING EMPTY
-POLYGON EMPTY|POLYGON EMPTY
+POINT EMPTY|MULTIPOINT EMPTY
+LINESTRING EMPTY|MULTILINESTRING EMPTY
+POLYGON EMPTY|MULTIPOLYGON EMPTY
 GEOMETRYCOLLECTION EMPTY|GEOMETRYCOLLECTION EMPTY
 Topology 'MiX' dropped
index 2c80da1a1b9468a299957a007d63af6eb21dd6b9..e92a2402febe9ed34ff3f07454b754fc0efe79ac 100644 (file)
@@ -15,36 +15,36 @@ features.big_parcels.the_geom SRID:0 TYPE:MULTIPOLYGON DIMS:2
 6
 features.big_signs.the_geom SRID:0 TYPE:MULTIPOINT DIMS:2 
 BEGIN
-P1|1|POLYGON((21 14,21 6,9 6,9 14,9 22,21 22,21 14))
-P2|2|POLYGON((35 14,35 6,21 6,21 14,21 22,35 22,35 14))
-P3|3|POLYGON((47 14,47 6,35 6,35 14,35 22,47 22,47 14))
-P4|4|POLYGON((25 30,17 30,17 40,31 40,31 30,25 30))
-P5|5|POLYGON((8 30,3 30,3 38,16 38,16 30,8 30),(4 31,7 31,7 34,4 34,4 31))
-F3|6|POLYGON((9 22,21 22,21 14,9 14,9 22))
-F6|7|POLYGON((9 14,21 14,21 6,9 6,9 14))
-F3F4|8|POLYGON((9 22,21 22,35 22,35 14,21 14,9 14,9 22))
-F1|9|POLYGON((8 30,3 30,3 38,16 38,16 30,8 30),(4 31,7 31,7 34,4 34,4 31))
-S1|1|POINT(21 14)
-S2|2|POINT(35 14)
-S3|3|POINT(57 33)
-S4|4|POINT(20 37)
+P1|1|MULTIPOLYGON(((21 14,21 6,9 6,9 14,9 22,21 22,21 14)))
+P2|2|MULTIPOLYGON(((35 14,35 6,21 6,21 14,21 22,35 22,35 14)))
+P3|3|MULTIPOLYGON(((47 14,47 6,35 6,35 14,35 22,47 22,47 14)))
+P4|4|MULTIPOLYGON(((25 30,17 30,17 40,31 40,31 30,25 30)))
+P5|5|MULTIPOLYGON(((8 30,3 30,3 38,16 38,16 30,8 30),(4 31,7 31,7 34,4 34,4 31)))
+F3|6|MULTIPOLYGON(((9 22,21 22,21 14,9 14,9 22)))
+F6|7|MULTIPOLYGON(((9 14,21 14,21 6,9 6,9 14)))
+F3F4|8|MULTIPOLYGON(((9 22,21 22,35 22,35 14,21 14,9 14,9 22)))
+F1|9|MULTIPOLYGON(((8 30,3 30,3 38,16 38,16 30,8 30),(4 31,7 31,7 34,4 34,4 31)))
+S1|1|MULTIPOINT(21 14)
+S2|2|MULTIPOINT(35 14)
+S3|3|MULTIPOINT(57 33)
+S4|4|MULTIPOINT(20 37)
 N1N2N3|5|MULTIPOINT(8 30,25 30,25 35)
 N1N6N14|6|MULTIPOINT(8 30,21 14,57 33)
 N3N4|7|MULTIPOINT(20 37,25 35)
-N4|8|POINT(20 37)
-R1|1|LINESTRING(9 14,21 14,35 14)
-R2|2|LINESTRING(36 38,38 35,41 34,42 33,45 32,47 28,50 28,52 32,57 33,57 36,59 39,61 38,62 41,47 42,45 40,41 40)
-R3|3|LINESTRING(9 35,13 35)
-R4|4|LINESTRING(25 30,25 35)
-E7E8|5|LINESTRING(21 22,35 22,47 22)
-E20E19|6|LINESTRING(21 6,21 14,21 22)
-E25|7|LINESTRING(9 35,13 35)
-R1a|8|LINESTRING(9 14,21 14,35 14)
+N4|8|MULTIPOINT(20 37)
+R1|1|MULTILINESTRING((9 14,21 14,35 14))
+R2|2|MULTILINESTRING((36 38,38 35,41 34,42 33,45 32,47 28,50 28,52 32,57 33,57 36,59 39,61 38,62 41,47 42,45 40,41 40))
+R3|3|MULTILINESTRING((9 35,13 35))
+R4|4|MULTILINESTRING((25 30,25 35))
+E7E8|5|MULTILINESTRING((21 22,35 22,47 22))
+E20E19|6|MULTILINESTRING((21 6,21 14,21 22))
+E25|7|MULTILINESTRING((9 35,13 35))
+R1a|8|MULTILINESTRING((9 14,21 14,35 14))
 S1S2|MULTIPOINT(21 14,35 14)
 R1R2|MULTILINESTRING((36 38,38 35,41 34,42 33,45 32,47 28,50 28,52 32,57 33,57 36,59 39,61 38,62 41,47 42,45 40,41 40),(9 14,21 14,35 14))
-R4|LINESTRING(25 30,25 35)
-P1P2|POLYGON((21 6,9 6,9 14,9 22,21 22,35 22,35 14,35 6,21 6))
+R4|MULTILINESTRING((25 30,25 35))
+P1P2|MULTIPOLYGON(((21 6,9 6,9 14,9 22,21 22,35 22,35 14,35 6,21 6)))
 P3P4|MULTIPOLYGON(((47 14,47 6,35 6,35 14,35 22,47 22,47 14)),((25 30,17 30,17 40,31 40,31 30,25 30)))
-F3F6|POLYGON((21 14,21 6,9 6,9 14,9 22,21 22,21 14))
+F3F6|MULTIPOLYGON(((21 14,21 6,9 6,9 14,9 22,21 22,21 14)))
 COMMIT
 Topology 'city_data' dropped
index 6bffb8869aa1dbc5434741c375930ba61434bf12..0f47c1d079576c894629f1e22e9b258359eadf3d 100644 (file)
@@ -1,6 +1,6 @@
 t
 1
 2
-f1|POLYGON((0 0 30,0 10 25,10 10 20,10 0 18,0 0 30))
-l1|LINESTRING(0 0 30,0 10 25,10 10 20,10 0 18,0 0 30)
+f1|MULTIPOLYGON(((0 0 30,0 10 25,10 10 20,10 0 18,0 0 30)))
+l1|MULTILINESTRING((0 0 30,0 10 25,10 10 20,10 0 18,0 0 30))
 Topology 'tt3d' dropped
index ce5d19a9da83b4cc701ba151b6c819da026d566c..22dce3ea715ae1427d1f60430c6f18870f27dbaa 100644 (file)
@@ -22,11 +22,11 @@ MULTIPOINT(0 -10,5 -10)|t
 MULTILINESTRING((-1 10,-10 10),(-10 8,-2 9))|t
 MULTIPOLYGON(((100 20,110 20,105 30,100 20),(102 22,108 22,105 28,102 22)),((80 20,90 20,90 60,80 20)))|t
 GEOMETRYCOLLECTION(POINT(-100 -100),LINESTRING(-100 -90,-90 -90),POLYGON((-100 -80,-90 -80,-95 -70,-100 -80),(-98 -78,-92 -78,-95 -72,-98 -78)),MULTIPOINT(-100 -110,-95 -110),LINESTRING EMPTY,MULTILINESTRING((-101 -90,-110 -90),(-110 -92,-102 -91)),MULTIPOLYGON(((0 -80,10 -80,5 -70,0 -80),(2 -78,8 -78,5 -72,2 -78)),((-20 -80,-10 -80,-10 -40,-20 -80))))|GEOMETRYCOLLECTION(MULTIPOLYGON(((-100 -80,-95 -70,-90 -80,-100 -80),(-98 -78,-92 -78,-95 -72,-98 -78)),((0 -80,5 -70,10 -80,0 -80),(2 -78,8 -78,5 -72,2 -78)),((-20 -80,-10 -40,-10 -80,-20 -80))),MULTILINESTRING((-110 -92,-102 -91),(-101 -90,-110 -90),(-100 -90,-90 -90)),MULTIPOINT(-100 -110,-100 -100,-95 -110))
-POINT EMPTY
-POINT EMPTY
-LINESTRING EMPTY
-LINESTRING EMPTY
-POLYGON EMPTY
-POLYGON EMPTY
+MULTIPOINT EMPTY
+MULTIPOINT EMPTY
+MULTILINESTRING EMPTY
+MULTILINESTRING EMPTY
+MULTIPOLYGON EMPTY
+MULTIPOLYGON EMPTY
 GEOMETRYCOLLECTION EMPTY
 Topology 'tt' dropped
index ef8cd57ccd2ee329ef754b269fae6b30f87a68fe..ea4256f911b527697cb0e4648e2c44f932af622a 100644 (file)
@@ -1167,112 +1167,98 @@ DECLARE
   rec RECORD;
   plyr RECORD;
   clyr RECORD;
-  query text;
-  ok BOOL;
   sql TEXT;
 BEGIN
-        -- Get topology name
-        SELECT name FROM topology.topology into toponame
-                WHERE id = topogeom.topology_id;
 
-       -- Get layer info
-       ok = false;
-       FOR rec IN EXECUTE 'SELECT * FROM topology.layer '
-               || ' WHERE topology_id = ' || topogeom.topology_id
-               || ' AND layer_id = ' || topogeom.layer_id
-       LOOP
-               ok = true;
-               plyr = rec;
-       END LOOP;
+  -- Get topology name
+  SELECT name FROM topology.topology
+       WHERE id = topogeom.topology_id
+  INTO toponame;
+  IF toponame IS NULL THEN
+    RAISE EXCEPTION 'Invalid TopoGeometry (unexistent topology id %)', topogeom.topology_id;
+  END IF;
 
-       IF NOT ok THEN
-               RAISE EXCEPTION 'Could not find TopoGeometry layer % in topology %', topogeom.layer_id, topogeom.topology_id;
-       END IF;
+  -- Get layer info
+  SELECT * FROM topology.layer
+    WHERE topology_id = topogeom.topology_id
+    AND layer_id = topogeom.layer_id
+    INTO plyr;
+  IF plyr IS NULL THEN
+    RAISE EXCEPTION 'Could not find TopoGeometry layer % in topology %', topogeom.layer_id, topogeom.topology_id;
+  END IF;
 
-       --
-       -- If this feature layer is on any level > 0 we will
-       -- compute the topological union of all child features
-       -- in fact recursing.
-       --
-       IF plyr.level > 0 THEN
-
-               -- Get child layer info
-               SELECT * INTO STRICT clyr FROM topology.layer
-                       WHERE layer_id = plyr.child_id
-                       AND topology_id = topogeom.topology_id;
-
-               query = 'SELECT st_union(topology.Geometry('
-                       || quote_ident(clyr.feature_column)
-                       || ')) as geom FROM '
-                       || quote_ident(clyr.schema_name) || '.'
-                       || quote_ident(clyr.table_name)
-                       || ', ' || quote_ident(toponame) || '.relation pr'
-                       || ' WHERE '
-                       || ' pr.topogeo_id = ' || topogeom.id
-                       || ' AND '
-                       || ' pr.layer_id = ' || topogeom.layer_id
-                       || ' AND '
-                       || ' id('||quote_ident(clyr.feature_column)
-                       || ') = pr.element_id '
-                       || ' AND '
-                       || 'layer_id('||quote_ident(clyr.feature_column)
-                       || ') = pr.element_type ';
-               --RAISE DEBUG '%', query;
-               FOR rec IN EXECUTE query
-               LOOP
-                       RETURN rec.geom;
-               END LOOP;
-                       
-       END IF;
-       
+  --
+  -- If this feature layer is on any level > 0 we will
+  -- compute the topological union of all child features
+  -- in fact recursing.
+  --
+  IF plyr.level > 0 THEN -- {
+
+    -- Get child layer info
+    SELECT * FROM topology.layer WHERE layer_id = plyr.child_id
+      AND topology_id = topogeom.topology_id
+      INTO clyr;
+    IF clyr IS NULL THEN
+      RAISE EXCEPTION 'Invalid layer % in topology % (unexistent child layer %)', topogeom.layer_id, topogeom.topology_id, plyr.child_id;
+    END IF;
 
-  IF topogeom.type = 3 THEN -- [multi]polygon
-               FOR rec IN EXECUTE 'SELECT st_union('
-                       || 'topology.ST_GetFaceGeometry('
-                       || quote_literal(toponame) || ','
-                       || 'element_id)) as g FROM ' 
-                       || quote_ident(toponame)
-                       || '.relation WHERE topogeo_id = '
-                       || topogeom.id || ' AND layer_id = '
-                       || topogeom.layer_id || ' AND element_type = 3 '
-               LOOP
-                       geom := rec.g;
-               END LOOP;
-               IF geom IS NULL THEN
-                       geom := 'POLYGON EMPTY';
-               END IF;
+    sql := 'SELECT st_multi(st_union(topology.Geometry('
+      || quote_ident(clyr.feature_column)
+      || '))) as geom FROM '
+      || quote_ident(clyr.schema_name) || '.'
+      || quote_ident(clyr.table_name)
+      || ', ' || quote_ident(toponame) || '.relation pr'
+      || ' WHERE '
+      || ' pr.topogeo_id = ' || topogeom.id
+      || ' AND '
+      || ' pr.layer_id = ' || topogeom.layer_id
+      || ' AND '
+      || ' id('||quote_ident(clyr.feature_column)
+      || ') = pr.element_id '
+      || ' AND '
+      || 'layer_id('||quote_ident(clyr.feature_column)
+      || ') = pr.element_type ';
+    --RAISE DEBUG '%', query;
+    EXECUTE sql INTO geom;
+      
+  ELSIF topogeom.type = 3 THEN -- [multi]polygon -- }{
 
-  ELSIF topogeom.type = 2 THEN -- [multi]line
-               FOR rec IN EXECUTE 'SELECT ST_LineMerge(ST_Collect(e.geom)) as g FROM '
-                       || quote_ident(toponame) || '.edge e, '
-                       || quote_ident(toponame) || '.relation r '
-                       || ' WHERE r.topogeo_id = ' || topogeom.id
-                       || ' AND r.layer_id = ' || topogeom.layer_id
-                       || ' AND r.element_type = 2 '
-                       || ' AND abs(r.element_id) = e.edge_id'
-               LOOP
-                       geom := rec.g;
-               END LOOP;
-               IF geom IS NULL THEN
-                       geom := 'LINESTRING EMPTY';
-               END IF;
-       
-  ELSIF topogeom.type = 1 THEN -- [multi]point
-               FOR rec IN EXECUTE 'SELECT st_union(n.geom) as g FROM '
-                       || quote_ident(toponame) || '.node n, '
-                       || quote_ident(toponame) || '.relation r '
-                       || ' WHERE r.topogeo_id = ' || topogeom.id
-                       || ' AND r.layer_id = ' || topogeom.layer_id
-                       || ' AND r.element_type = 1 '
-                       || ' AND r.element_id = n.node_id'
-               LOOP
-                       geom := rec.g;
-               END LOOP;
-               IF geom IS NULL THEN
-                       geom := 'POINT EMPTY';
-               END IF;
+    sql := 'SELECT st_multi(st_union('
+      || 'topology.ST_GetFaceGeometry('
+      || quote_literal(toponame) || ','
+      || 'element_id))) as g FROM ' 
+      || quote_ident(toponame)
+      || '.relation WHERE topogeo_id = '
+      || topogeom.id || ' AND layer_id = '
+      || topogeom.layer_id || ' AND element_type = 3 ';
+    EXECUTE sql INTO geom;
+
+  ELSIF topogeom.type = 2 THEN -- [multi]line -- }{
+
+    sql := 
+      'SELECT st_multi(ST_LineMerge(ST_Collect(e.geom))) as g FROM '
+      || quote_ident(toponame) || '.edge e, '
+      || quote_ident(toponame) || '.relation r '
+      || ' WHERE r.topogeo_id = ' || topogeom.id
+      || ' AND r.layer_id = ' || topogeom.layer_id
+      || ' AND r.element_type = 2 '
+      || ' AND abs(r.element_id) = e.edge_id';
+    EXECUTE sql INTO geom;
+  
+  ELSIF topogeom.type = 1 THEN -- [multi]point -- }{
+
+    sql :=
+      'SELECT st_multi(st_union(n.geom)) as g FROM '
+      || quote_ident(toponame) || '.node n, '
+      || quote_ident(toponame) || '.relation r '
+      || ' WHERE r.topogeo_id = ' || topogeom.id
+      || ' AND r.layer_id = ' || topogeom.layer_id
+      || ' AND r.element_type = 1 '
+      || ' AND r.element_id = n.node_id';
+    EXECUTE sql INTO geom;
+
+  ELSIF topogeom.type = 4 THEN -- mixed collection -- }{
 
-  ELSIF topogeom.type = 4 THEN -- mixed collection
     sql := 'WITH areas AS ( SELECT ST_Union('
       || 'topology.ST_GetFaceGeometry('
       || quote_literal(toponame) || ','
@@ -1297,18 +1283,28 @@ BEGIN
       || ' AND r.element_id = n.node_id ), '
       || ' un as ( SELECT g FROM areas UNION ALL SELECT g FROM lines '
       || '          UNION ALL SELECT g FROM points ) '
-      || 'SELECT ST_Collect(g) FROM un';
+      || 'SELECT ST_Multi(ST_Collect(g)) FROM un';
     EXECUTE sql INTO geom;
-    IF geom IS NULL THEN
+
+  ELSE -- }{
+
+    RAISE EXCEPTION 'Invalid TopoGeometries (unknown type %)', topogeom.type;
+
+  END IF; -- }
+
+  IF geom IS NULL THEN
+    IF topogeom.type = 3 THEN -- [multi]polygon
+      geom := 'MULTIPOLYGON EMPTY';
+    ELSIF topogeom.type = 2 THEN -- [multi]line
+      geom := 'MULTILINESTRING EMPTY';
+    ELSIF topogeom.type = 1 THEN -- [multi]point
+      geom := 'MULTIPOINT EMPTY';
+    ELSE
       geom := 'GEOMETRYCOLLECTION EMPTY';
     END IF;
-
-  ELSE
-    RAISE NOTICE 'Geometry from TopoGeometry does not support TopoGeometries of type % so far', topogeom.type;
-    geom := 'GEOMETRYCOLLECTION EMPTY';
   END IF;
 
-       RETURN geom;
+  RETURN geom;
 END
 $$
 LANGUAGE 'plpgsql' VOLATILE STRICT;