[postgis-tickets] [SCM] PostGIS branch main updated. 3.1.0rc1-340-g1ea1cb6

git at osgeo.org git at osgeo.org
Wed Jul 14 14:00:20 PDT 2021


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, main has been updated
       via  1ea1cb69940be217f3a98412b1621c5b887c566e (commit)
      from  a4fc3247a71f192231088987eda2f556e9f27ee2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1ea1cb69940be217f3a98412b1621c5b887c566e
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Jul 14 22:41:32 2021 +0200

    Prevent healing edges if connecting node is used in a TopoGeometry
    
    Closes #3239 in main branch (3.2.0dev)

diff --git a/NEWS b/NEWS
index b45bd41..d100a21 100644
--- a/NEWS
+++ b/NEWS
@@ -6,8 +6,10 @@ PostGIS 3.2.0
   - #4933, topology.GetFaceByPoint will not work with topologies having invalid edge linking.
 
  * Enhancements *
+  - #3239, Prevent headling topology edges if the connecting node is
+           used in the definition of a TopoGeometry (Sandro Santilli)
   - #4950, Speed up checking containing_face for nodes in ValidateTopology
-    (Sandro Santilli)
+           (Sandro Santilli)
   - #4945, Multi-shell face check in ValidateTopology (Sandro Santilli)
   - #4944, Side-location conflict check in ValidateTopology (Sandro Santilli)
   - #3042, ValidateTopology check for edge linking (Sandro Santilli)
diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c
index 9480bf8..1874b23 100644
--- a/topology/postgis_topology.c
+++ b/topology/postgis_topology.c
@@ -2565,6 +2565,9 @@ cb_checkTopoGeomRemNode ( const LWT_BE_TOPOLOGY* topo,
   TupleDesc tdesc;
 
   initStringInfo(sql);
+
+  /* 1: check for lineal TopoGeometry objects being defined by
+   * only one of the edges to be merged */
   appendStringInfo( 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 "
@@ -2574,7 +2577,7 @@ cb_checkTopoGeomRemNode ( const LWT_BE_TOPOLOGY* topo,
                     " AND abs(r.element_id) = ANY (ARRAY[%" LWTFMT_ELEMID ",%" LWTFMT_ELEMID
                     "]::int4[]) group by r.topogeo_id, r.layer_id, l.schema_name, "
                     "l.table_name, l.feature_column ) t WHERE NOT t.elems @> ARRAY[%"
-                    LWTFMT_ELEMID ",%" LWTFMT_ELEMID "]::int4[]",
+                    LWTFMT_ELEMID ",%" LWTFMT_ELEMID "]::int4[] LIMIT 1",
                     topo->name, topo->id,
                     edge1, edge2, edge1, edge2 );
 
@@ -2612,8 +2615,54 @@ cb_checkTopoGeomRemNode ( const LWT_BE_TOPOLOGY* topo,
     return 0;
   }
 
-  /* TODO: check for TopoGeometry objects being defined by the common
+  /* 2: check for puntual TopoGeometry objects being defined by the common
    * node, see https://trac.osgeo.org/postgis/ticket/3239 */
+  resetStringInfo(sql);
+  appendStringInfo( 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 \"%s\".relation r ON (l.layer_id = r.layer_id) "
+                    "WHERE l.level = 0 and l.feature_type = 1 "
+                    "AND l.topology_id = %d"
+                    " AND r.element_id = %" LWTFMT_ELEMID
+                    " group by r.topogeo_id, r.layer_id, l.schema_name, "
+                    "l.table_name, l.feature_column ) t LIMIT 1",
+                    topo->name, topo->id,
+                    rem_node );
+
+  POSTGIS_DEBUGF(1, "cb_checkTopoGeomRemNode query 2: %s", sql->data);
+
+  spi_result = SPI_execute(sql->data, !topo->be_data->data_changed, 0);
+  MemoryContextSwitchTo( oldcontext ); /* switch back */
+  if ( spi_result != SPI_OK_SELECT )
+  {
+    cberror(topo->be_data, "unexpected return (%d) from query execution: %s",
+            spi_result, sql->data);
+    pfree(sqldata.data);
+    return 0;
+  }
+
+  if ( SPI_processed )
+  {
+    row = SPI_tuptable->vals[0];
+    tdesc = SPI_tuptable->tupdesc;
+
+    tg_id = SPI_getvalue(row, tdesc, 1);
+    layer_id = SPI_getvalue(row, tdesc, 2);
+    schema_name = SPI_getvalue(row, tdesc, 3);
+    table_name = SPI_getvalue(row, tdesc, 4);
+    col_name = SPI_getvalue(row, tdesc, 5);
+
+    SPI_freetuptable(SPI_tuptable);
+
+    cberror(topo->be_data, "TopoGeom %s in layer %s "
+            "(%s.%s.%s) cannot be represented "
+            "healing edges %" LWTFMT_ELEMID
+            " and %" LWTFMT_ELEMID,
+            tg_id, layer_id, schema_name, table_name,
+            col_name, edge1, edge2);
+    return 0;
+  }
 
   return 1;
 }
diff --git a/topology/test/regress/st_modedgeheal.sql b/topology/test/regress/st_modedgeheal.sql
index 8322992..782737f 100644
--- a/topology/test/regress/st_modedgeheal.sql
+++ b/topology/test/regress/st_modedgeheal.sql
@@ -63,11 +63,27 @@ SELECT topology.DropTopology('city_data');
 
 SELECT topology.CreateTopology('t') > 1;
 CREATE TABLE t.f(id varchar);
-SELECT topology.AddTopoGeometryColumn('t', 't', 'f','g', 'LINE');
+SELECT 'line_layer', topology.AddTopoGeometryColumn('t', 't', 'f','g', 'LINE');
+CREATE TABLE t.p(id varchar);
+SELECT 'point_layer', topology.AddTopoGeometryColumn('t', 't', 'p','g', 'POINT');
 
+SELECT 'N'||topology.TopoGeo_AddPoint('t', 'POINT(2 8)');  -- 1
 SELECT 'E'||topology.AddEdge('t', 'LINESTRING(2 2, 2  8)');        -- 1
 SELECT 'E'||topology.AddEdge('t', 'LINESTRING(2  8,  8  8)');      -- 2
 
+INSERT INTO t.p VALUES ('F+N1',
+  topology.CreateTopoGeom('t', 1, 2, '{{1,1}}'));
+
+-- This should be forbidden, as F+N1 above could not be
+-- defined w/out the joining node
+-- See https://trac.osgeo.org/postgis/ticket/3239
+SELECT 'unexpected-success-with-orphaned-point-topogeom-1',
+  topology.ST_ModEdgeHeal('t', 1, 2);
+SELECT 'unexpected-success-with-orphaned-point-topogeom-2',
+  topology.ST_ModEdgeHeal('t', 2, 1);
+
+DELETE FROM t.p;
+
 INSERT INTO t.f VALUES ('F+E1',
   topology.CreateTopoGeom('t', 2, 1, '{{1,2}}'));
 
diff --git a/topology/test/regress/st_modedgeheal_expected b/topology/test/regress/st_modedgeheal_expected
index 115c6ae..cab772a 100644
--- a/topology/test/regress/st_modedgeheal_expected
+++ b/topology/test/regress/st_modedgeheal_expected
@@ -96,9 +96,13 @@ N21
 N22
 Topology 'city_data' dropped
 t
-1
+line_layer|1
+point_layer|2
+N1
 E1
 E2
+ERROR:  TopoGeom 1 in layer 2 (t.p.g) cannot be represented healing edges 1 and 2
+ERROR:  TopoGeom 1 in layer 2 (t.p.g) cannot be represented healing edges 2 and 1
 ERROR:  TopoGeom 1 in layer 1 (t.f.g) cannot be represented healing edges 1 and 2
 ERROR:  TopoGeom 1 in layer 1 (t.f.g) cannot be represented healing edges 2 and 1
 ERROR:  SQL/MM Spatial exception - non-existent edge 200
diff --git a/topology/test/regress/st_newedgeheal.sql b/topology/test/regress/st_newedgeheal.sql
index e49979f..de4c218 100644
--- a/topology/test/regress/st_newedgeheal.sql
+++ b/topology/test/regress/st_newedgeheal.sql
@@ -63,11 +63,27 @@ SELECT topology.DropTopology('city_data');
 
 SELECT topology.CreateTopology('t') > 1;
 CREATE TABLE t.f(id varchar);
-SELECT topology.AddTopoGeometryColumn('t', 't', 'f','g', 'LINE');
+SELECT 'line_layer', topology.AddTopoGeometryColumn('t', 't', 'f','g', 'LINE');
+CREATE TABLE t.p(id varchar);
+SELECT 'point_layer', topology.AddTopoGeometryColumn('t', 't', 'p','g', 'POINT');
 
+SELECT 'N'||topology.TopoGeo_AddPoint('t', 'POINT(2 8)');  -- 1
 SELECT 'E'||topology.AddEdge('t', 'LINESTRING(2 2, 2  8)');        -- 1
 SELECT 'E'||topology.AddEdge('t', 'LINESTRING(2  8,  8  8)');      -- 2
 
+INSERT INTO t.p VALUES ('F+N1',
+  topology.CreateTopoGeom('t', 1, 2, '{{1,1}}'));
+
+-- This should be forbidden, as F+N1 above could not be
+-- defined w/out the joining node
+-- See https://trac.osgeo.org/postgis/ticket/3239
+SELECT 'unexpected-success-with-orphaned-point-topogeom-1',
+  topology.ST_ModEdgeHeal('t', 1, 2);
+SELECT 'unexpected-success-with-orphaned-point-topogeom-2',
+  topology.ST_ModEdgeHeal('t', 2, 1);
+
+DELETE FROM t.p;
+
 INSERT INTO t.f VALUES ('F+E1',
   topology.CreateTopoGeom('t', 2, 1, '{{1,2}}'));
 
diff --git a/topology/test/regress/st_newedgeheal_expected b/topology/test/regress/st_newedgeheal_expected
index 07579f1..a41313a 100644
--- a/topology/test/regress/st_newedgeheal_expected
+++ b/topology/test/regress/st_newedgeheal_expected
@@ -96,9 +96,13 @@ N21
 N22
 Topology 'city_data' dropped
 t
-1
+line_layer|1
+point_layer|2
+N1
 E1
 E2
+ERROR:  TopoGeom 1 in layer 2 (t.p.g) cannot be represented healing edges 1 and 2
+ERROR:  TopoGeom 1 in layer 2 (t.p.g) cannot be represented healing edges 2 and 1
 ERROR:  TopoGeom 1 in layer 1 (t.f.g) cannot be represented healing edges 1 and 2
 ERROR:  TopoGeom 1 in layer 1 (t.f.g) cannot be represented healing edges 2 and 1
 ERROR:  SQL/MM Spatial exception - non-existent edge 200

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                          |  4 +-
 topology/postgis_topology.c                   | 53 ++++++++++++++++++++++++++-
 topology/test/regress/st_modedgeheal.sql      | 18 ++++++++-
 topology/test/regress/st_modedgeheal_expected |  6 ++-
 topology/test/regress/st_newedgeheal.sql      | 18 ++++++++-
 topology/test/regress/st_newedgeheal_expected |  6 ++-
 6 files changed, 98 insertions(+), 7 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list