[postgis-tickets] r14525 - Fix crash on splitting edge defining multiple TopoGeometries

Sandro Santilli strk at keybit.net
Sat Dec 26 05:55:30 PST 2015


Author: strk
Date: 2015-12-26 05:55:30 -0800 (Sat, 26 Dec 2015)
New Revision: 14525

Modified:
   trunk/topology/postgis_topology.c
   trunk/topology/test/regress/st_modedgesplit.sql
   trunk/topology/test/regress/st_modedgesplit_expected
   trunk/topology/test/regress/st_newedgessplit.sql
   trunk/topology/test/regress/st_newedgessplit_expected
Log:
Fix crash on splitting edge defining multiple TopoGeometries

See #3407

Modified: trunk/topology/postgis_topology.c
===================================================================
--- trunk/topology/postgis_topology.c	2015-12-26 13:54:55 UTC (rev 14524)
+++ trunk/topology/postgis_topology.c	2015-12-26 13:55:30 UTC (rev 14525)
@@ -1903,50 +1903,60 @@
   }
 
   ntopogeoms = SPI_processed;
-  for ( i=0; i<ntopogeoms; ++i )
+  if ( ntopogeoms )
   {
-    HeapTuple row = SPI_tuptable->vals[i];
-    TupleDesc tdesc = SPI_tuptable->tupdesc;
-    int negate;
-    int element_id;
-    int topogeo_id;
-    int layer_id;
-    int element_type;
+    resetStringInfo(sql);
+    appendStringInfo(sql, "INSERT INTO \"%s\".relation VALUES ", topo->name);
+    for ( i=0; i<ntopogeoms; ++i )
+    {
+      HeapTuple row = SPI_tuptable->vals[i];
+      TupleDesc tdesc = SPI_tuptable->tupdesc;
+      int negate;
+      int element_id;
+      int topogeo_id;
+      int layer_id;
+      int element_type;
 
-    if ( ! getNotNullInt32( row, tdesc, 1, &element_id ) ) {
-		  cberror(topo->be_data,
-        "unexpected null element_id in \"%s\".relation",
-        topo->name);
-	    return 0;
-    }
-    negate = ( element_id < 0 );
+      if ( ! getNotNullInt32( row, tdesc, 1, &element_id ) ) {
+        cberror(topo->be_data,
+          "unexpected null element_id in \"%s\".relation",
+          topo->name);
+        return 0;
+      }
+      negate = ( element_id < 0 );
 
-    if ( ! getNotNullInt32( row, tdesc, 2, &topogeo_id ) ) {
-		  cberror(topo->be_data,
-        "unexpected null topogeo_id in \"%s\".relation",
-        topo->name);
-	    return 0;
-    }
+      if ( ! getNotNullInt32( row, tdesc, 2, &topogeo_id ) ) {
+        cberror(topo->be_data,
+          "unexpected null topogeo_id in \"%s\".relation",
+          topo->name);
+        return 0;
+      }
 
-    if ( ! getNotNullInt32( row, tdesc, 3, &layer_id ) ) {
-		  cberror(topo->be_data,
-        "unexpected null layer_id in \"%s\".relation",
-        topo->name);
-	    return 0;
-    }
+      if ( ! getNotNullInt32( row, tdesc, 3, &layer_id ) ) {
+        cberror(topo->be_data,
+          "unexpected null layer_id in \"%s\".relation",
+          topo->name);
+        return 0;
+      }
 
-    if ( ! getNotNullInt32( row, tdesc, 4, &element_type ) ) {
-		  cberror(topo->be_data,
-        "unexpected null element_type in \"%s\".relation",
-        topo->name);
-	    return 0;
-    }
+      if ( ! getNotNullInt32( row, tdesc, 4, &element_type ) ) {
+        cberror(topo->be_data,
+          "unexpected null element_type in \"%s\".relation",
+          topo->name);
+        return 0;
+      }
 
-    resetStringInfo(sql);
-    appendStringInfo(sql,
-      "INSERT INTO \"%s\".relation VALUES ("
-      "%d,%d,%" LWTFMT_ELEMID ",%d)", topo->name,
-      topogeo_id, layer_id, negate ? -new_edge1 : new_edge1, element_type);
+      if ( i ) appendStringInfoChar(sql, ',');
+      appendStringInfo(sql, "(%d,%d,%" LWTFMT_ELEMID ",%d)",
+        topogeo_id, layer_id, negate ? -new_edge1 : new_edge1, element_type);
+      if ( new_edge2 != -1 ) {
+        resetStringInfo(sql);
+        appendStringInfo(sql,
+          ",VALUES (%d,%d,%" LWTFMT_ELEMID ",%d",
+          topogeo_id, layer_id, negate ? -new_edge2 : new_edge2, element_type);
+      }
+    }
+    POSTGIS_DEBUGF(1, "cb_updateTopoGeomEdgeSplit query: %s", sql->data);
     spi_result = SPI_execute(sql->data, false, 0);
     MemoryContextSwitchTo( oldcontext ); /* switch back */
     if ( spi_result != SPI_OK_INSERT ) {
@@ -1956,28 +1966,11 @@
       return 0;
     }
     if ( SPI_processed ) topo->be_data->data_changed = true;
-    if ( new_edge2 != -1 ) {
-      resetStringInfo(sql);
-      appendStringInfo(sql,
-        "INSERT INTO FROM \"%s\".relation VALUES ("
-        "%d,%d,%" LWTFMT_ELEMID ",%d", topo->name,
-        topogeo_id, layer_id, negate ? -new_edge2 : new_edge2, element_type);
-      spi_result = SPI_execute(sql->data, false, 0);
-      MemoryContextSwitchTo( oldcontext ); /* switch back */
-      if ( spi_result != SPI_OK_INSERT ) {
-        cberror(topo->be_data, "unexpected return (%d) from query execution: %s",
-                spi_result, sql->data);
-        pfree(sqldata.data);
-        return 0;
-      }
-      if ( SPI_processed ) topo->be_data->data_changed = true;
-    }
   }
 
-  /* TODO: release string info ! */
-
   POSTGIS_DEBUGF(1, "cb_updateTopoGeomEdgeSplit: updated %d topogeoms", ntopogeoms);
 
+  pfree(sqldata.data);
   return 1;
 }
 

Modified: trunk/topology/test/regress/st_modedgesplit.sql
===================================================================
--- trunk/topology/test/regress/st_modedgesplit.sql	2015-12-26 13:54:55 UTC (rev 14524)
+++ trunk/topology/test/regress/st_modedgesplit.sql	2015-12-26 13:55:30 UTC (rev 14525)
@@ -92,12 +92,30 @@
 SELECT 'closed', ST_ModEdgeSplit('city_data', 1, 'SRID=4326;POINT(3 38)');
 SELECT check_changes();
 
+--
+-- Split an edge referenced by multiple TopoGeometries
+--
+-- See https://trac.osgeo.org/postgis/ticket/3407
+--
+CREATE TABLE city_data.fl(id varchar);
+SELECT 'L' || topology.AddTopoGeometryColumn('city_data',
+  'city_data', 'fl', 'g', 'LINESTRING');
+INSERT INTO city_data.fl VALUES
+ ('E7.1', topology.CreateTopoGeom('city_data', 2, 1, '{{7,2}}')),
+ ('E7.2', topology.CreateTopoGeom('city_data', 2, 1, '{{7,2}}'));
+SELECT '#3407', ST_ModEdgeSplit('city_data', 7, 'SRID=4326;POINT(28 22)');
+SELECT check_changes();
+
 -- Robustness of edge splitting (#1711)
 
 -- clean all up first
 DELETE FROM city_data.edge_data; 
 DELETE FROM city_data.node; 
 DELETE FROM city_data.face where face_id > 0; 
+SELECT 'seq_reset',
+       setval('city_data.edge_data_edge_id_seq', 1, false),
+       setval('city_data.face_face_id_seq', 1, false),
+       setval('city_data.node_node_id_seq', 1, false);
 
 CREATE TEMP TABLE t AS
 SELECT

Modified: trunk/topology/test/regress/st_modedgesplit_expected
===================================================================
--- trunk/topology/test/regress/st_modedgesplit_expected	2015-12-26 13:54:55 UTC (rev 14524)
+++ trunk/topology/test/regress/st_modedgesplit_expected	2015-12-26 13:55:30 UTC (rev 14525)
@@ -33,11 +33,12 @@
 N|27||POINT(3 38)
 E|1|sn1|en27|nl31|nr-31|lf1|rf0
 E|31|sn27|en1|nl1|nr-1|lf1|rf0
-robust.1|E32|N30
-N|28||POINT(20 10)
-N|29||POINT(10 20)
-N|30||POINT(9 12)
-E|32|sn28|en30|nl33|nr32|lf0|rf0
-E|33|sn30|en29|nl-33|nr-32|lf0|rf0
+L1
+#3407|28
+N|28||POINT(28 22)
+E|7|sn17|en28|nl32|nr-19|lf0|rf4
+E|32|sn28|en18|nl8|nr-7|lf0|rf4
+seq_reset|1|1|1
+robust.1|E1|N3
 robust.2|t|t
 Topology 'city_data' dropped

Modified: trunk/topology/test/regress/st_newedgessplit.sql
===================================================================
--- trunk/topology/test/regress/st_newedgessplit.sql	2015-12-26 13:54:55 UTC (rev 14524)
+++ trunk/topology/test/regress/st_newedgessplit.sql	2015-12-26 13:55:30 UTC (rev 14525)
@@ -92,12 +92,30 @@
 SELECT 'closed', ST_NewEdgesSplit('city_data', 1, 'SRID=4326;POINT(3 38)');
 SELECT check_changes();
 
+--
+-- Split an edge referenced by multiple TopoGeometries
+--
+-- See https://trac.osgeo.org/postgis/ticket/3407
+--
+CREATE TABLE city_data.fl(id varchar);
+SELECT 'L' || topology.AddTopoGeometryColumn('city_data',
+  'city_data', 'fl', 'g', 'LINESTRING');
+INSERT INTO city_data.fl VALUES
+ ('E7.1', topology.CreateTopoGeom('city_data', 2, 1, '{{7,2}}')),
+ ('E7.2', topology.CreateTopoGeom('city_data', 2, 1, '{{7,2}}'));
+SELECT '#3407', ST_ModEdgeSplit('city_data', 7, 'SRID=4326;POINT(28 22)');
+SELECT check_changes();
+
 -- Robustness of edge splitting (#1711)
 
 -- clean all up first
 DELETE FROM city_data.edge_data; 
 DELETE FROM city_data.node; 
 DELETE FROM city_data.face where face_id > 0; 
+SELECT 'seq_reset',
+       setval('city_data.edge_data_edge_id_seq', 1, false),
+       setval('city_data.face_face_id_seq', 1, false),
+       setval('city_data.node_node_id_seq', 1, false);
 
 CREATE TEMP TABLE t AS
 SELECT

Modified: trunk/topology/test/regress/st_newedgessplit_expected
===================================================================
--- trunk/topology/test/regress/st_newedgessplit_expected	2015-12-26 13:54:55 UTC (rev 14524)
+++ trunk/topology/test/regress/st_newedgessplit_expected	2015-12-26 13:55:30 UTC (rev 14525)
@@ -33,11 +33,12 @@
 N|27||POINT(3 38)
 E|35|sn1|en27|nl36|nr-36|lf1|rf0
 E|36|sn27|en1|nl35|nr-35|lf1|rf0
-robust.1|E37|N30
-N|28||POINT(20 10)
-N|29||POINT(10 20)
-N|30||POINT(9 12)
-E|38|sn28|en30|nl39|nr38|lf0|rf0
-E|39|sn30|en29|nl-39|nr-38|lf0|rf0
+L1
+#3407|28
+N|28||POINT(28 22)
+E|7|sn17|en28|nl37|nr-19|lf0|rf4
+E|37|sn28|en18|nl8|nr-7|lf0|rf4
+seq_reset|1|1|1
+robust.1|E1|N3
 robust.2|t|t
 Topology 'city_data' dropped



More information about the postgis-tickets mailing list