From d6d6c35c91d917246d3e9e18a6efd9e5ed98612c Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Sat, 26 Dec 2015 13:55:30 +0000 Subject: [PATCH] Fix crash on splitting edge defining multiple TopoGeometries See #3407 git-svn-id: http://svn.osgeo.org/postgis/trunk@14525 b70326c6-7e19-0410-871a-916f4a2858ee --- topology/postgis_topology.c | 107 ++++++++---------- topology/test/regress/st_modedgesplit.sql | 18 +++ .../test/regress/st_modedgesplit_expected | 13 ++- topology/test/regress/st_newedgessplit.sql | 18 +++ .../test/regress/st_newedgessplit_expected | 13 ++- 5 files changed, 100 insertions(+), 69 deletions(-) diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c index 9a057f3aa..aa2c1c66b 100644 --- a/topology/postgis_topology.c +++ b/topology/postgis_topology.c @@ -1903,50 +1903,60 @@ cb_updateTopoGeomEdgeSplit ( const LWT_BE_TOPOLOGY* topo, } ntopogeoms = SPI_processed; - for ( i=0; ivals[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 ); + resetStringInfo(sql); + appendStringInfo(sql, "INSERT INTO \"%s\".relation VALUES ", topo->name); + for ( i=0; ivals[i]; + TupleDesc tdesc = SPI_tuptable->tupdesc; + int negate; + int element_id; + int topogeo_id; + int layer_id; + int element_type; - 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, 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, 3, &layer_id ) ) { - cberror(topo->be_data, - "unexpected null layer_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, 4, &element_type ) ) { - cberror(topo->be_data, - "unexpected null element_type 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; + } - 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 ( ! getNotNullInt32( row, tdesc, 4, &element_type ) ) { + cberror(topo->be_data, + "unexpected null element_type in \"%s\".relation", + topo->name); + return 0; + } + + 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 @@ cb_updateTopoGeomEdgeSplit ( const LWT_BE_TOPOLOGY* topo, 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; } diff --git a/topology/test/regress/st_modedgesplit.sql b/topology/test/regress/st_modedgesplit.sql index b4747a84c..4684965e8 100644 --- a/topology/test/regress/st_modedgesplit.sql +++ b/topology/test/regress/st_modedgesplit.sql @@ -92,12 +92,30 @@ SELECT check_changes(); 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 diff --git a/topology/test/regress/st_modedgesplit_expected b/topology/test/regress/st_modedgesplit_expected index 443833d3c..263e9c311 100644 --- a/topology/test/regress/st_modedgesplit_expected +++ b/topology/test/regress/st_modedgesplit_expected @@ -33,11 +33,12 @@ closed|27 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 diff --git a/topology/test/regress/st_newedgessplit.sql b/topology/test/regress/st_newedgessplit.sql index 42a1489b6..e82b75d01 100644 --- a/topology/test/regress/st_newedgessplit.sql +++ b/topology/test/regress/st_newedgessplit.sql @@ -92,12 +92,30 @@ SELECT check_changes(); 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 diff --git a/topology/test/regress/st_newedgessplit_expected b/topology/test/regress/st_newedgessplit_expected index 771d07101..eefe3caeb 100644 --- a/topology/test/regress/st_newedgessplit_expected +++ b/topology/test/regress/st_newedgessplit_expected @@ -33,11 +33,12 @@ closed|27 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 -- 2.50.0