[postgis-tickets] [SCM] PostGIS branch main updated. 3.1.0rc1-275-g96cb70a

git at osgeo.org git at osgeo.org
Tue Jul 6 10:40:13 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  96cb70a4803f5d9856c811a4684bf801751648da (commit)
      from  44fb5e6edcb59c9582e83d58e8f286b2bd20357e (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 96cb70a4803f5d9856c811a4684bf801751648da
Author: Sandro Santilli <strk at kbt.io>
Date:   Tue Jul 6 18:18:38 2021 +0200

    Add ValidateTopologyRelation function
    
    Closes #4923
    Includes regress test and simple docs

diff --git a/NEWS b/NEWS
index 5cc7e53..05dbcd5 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,7 @@ PostGIS 3.2.0
            line to topology (Sandro Santilli)
 
  * New features*
+  - #4923, topology.ValidateTopologyRelation (Sandro Santilli)
   - #4933, topology.GetFaceContainingPoint (Sandro Santilli)
   - #2175, ST_Scroll (Sandro Santilli)
   - #4841, FindTopology to quickly get a topology record (Sandro Santilli)
diff --git a/doc/extras_topology.xml b/doc/extras_topology.xml
index 952b5fb..6e64c5b 100644
--- a/doc/extras_topology.xml
+++ b/doc/extras_topology.xml
@@ -658,6 +658,42 @@ face without edges |   0 |
 			</refsection>
 		</refentry>
 
+		<refentry id="ValidateTopologyRelation">
+			<refnamediv>
+				<refname>ValidateTopologyRelation</refname>
+
+				<refpurpose>Returns info about invalid topology relation records</refpurpose>
+			</refnamediv>
+
+			<refsynopsisdiv>
+				<funcsynopsis>
+					<funcprototype>
+					<funcdef>setof record <function>ValidateTopologyRelation</function></funcdef>
+					<paramdef><type>varchar </type> <parameter>toponame</parameter></paramdef>
+					</funcprototype>
+				</funcsynopsis>
+			</refsynopsisdiv>
+
+			<refsection>
+                <title>Description</title>
+
+                <para>
+Returns a set records giving information about invalidities in the
+relation table of the topology.
+                </para>
+
+                <!-- use this format if new function -->
+                <para>Availability: 3.2.0</para>
+			</refsection>
+
+
+			<!-- Optionally add a "See Also" section -->
+			<refsection>
+				<title>See Also</title>
+				<para><xref linkend="ValidateTopology"/></para>
+			</refsection>
+		</refentry>
+
 		<refentry id="FindTopology">
 			<refnamediv>
 				<refname>FindTopology</refname>
diff --git a/topology/Makefile.in b/topology/Makefile.in
index d6d5fea..42763b6 100644
--- a/topology/Makefile.in
+++ b/topology/Makefile.in
@@ -126,6 +126,7 @@ topology.sql: \
 	sql/manage/FindTopology.sql.in \
 	sql/manage/ManageHelper.sql.in \
 	sql/manage/ValidateTopology.sql.in \
+	sql/manage/ValidateTopologyRelation.sql.in \
 	sql/topoelement/topoelement_agg.sql.in \
 	sql/topogeometry/type.sql.in \
 	sql/topogeometry/totopogeom.sql.in \
diff --git a/topology/sql/manage/ValidateTopologyRelation.sql.in b/topology/sql/manage/ValidateTopologyRelation.sql.in
new file mode 100644
index 0000000..588d40d
--- /dev/null
+++ b/topology/sql/manage/ValidateTopologyRelation.sql.in
@@ -0,0 +1,134 @@
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+--
+-- PostGIS - Spatial Types for PostgreSQL
+-- http://postgis.net
+--
+-- Copyright (C) 2021 Sandro Santilli <strk at kbt.io>
+--
+-- This is free software; you can redistribute and/or modify it under
+-- the terms of the GNU General Public Licence. See the COPYING file.
+--
+-- Author: Sandro Santilli <strk at kbt.io>
+--
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+-- Invalidities are:
+--   - Referenced element does not exist
+--   - Same element listed twice
+--
+CREATE OR REPLACE FUNCTION topology.ValidateTopologyRelation(toponame varchar)
+RETURNS TABLE(error text, layer_id int, topogeo_id int, element_id int)
+AS
+$BODY$
+DECLARE
+  layerrec RECORD;
+  rel RECORD;
+  search_path_backup text;
+BEGIN
+  IF NOT EXISTS (
+    SELECT oid
+    FROM pg_catalog.pg_namespace
+    WHERE nspname = toponame
+  )
+  THEN
+    RAISE EXCEPTION 'Topology schema % does not exist', toponame;
+  END IF;
+
+  IF NOT EXISTS (
+    SELECT id
+    FROM topology.topology
+    WHERE name = toponame
+  )
+  THEN
+    RAISE WARNING 'Topology % is not registered in topology.topology', toponame;
+  END IF;
+
+  EXECUTE 'SHOW search_path' INTO search_path_backup;
+  EXECUTE 'SET search_PATH TO ' || quote_ident(toponame) || ','
+                                || search_path_backup;
+
+  FOR layerrec IN SELECT * FROM topology.layer
+  LOOP --{
+    IF layerrec.child_id IS NULL
+    THEN --{ Layer is simple
+
+      -- Check that all referenced nodes exist
+      FOR rel IN
+        SELECT r.layer_id, r.topogeo_id, r.element_id
+        FROM relation r
+        WHERE r.layer_id = layerrec.layer_id
+        AND r.element_type = 1
+        AND r.element_id NOT IN (
+          SELECT node_id FROM node
+        )
+      LOOP
+        error := 'TopoGeometry references unexistent node';
+        layer_id := rel.layer_id;
+        topogeo_id := rel.topogeo_id;
+        element_id := rel.element_id;
+        RETURN NEXT;
+      END LOOP;
+
+      -- Check that all referenced edges exist
+      FOR rel IN
+        SELECT r.layer_id, r.topogeo_id, r.element_id
+        FROM relation r
+        WHERE r.layer_id = layerrec.layer_id
+        AND r.element_type = 2
+        AND abs(r.element_id) NOT IN (
+          SELECT edge_id FROM edge_data
+        )
+      LOOP
+        error := 'TopoGeometry references unexistent edge';
+        layer_id := rel.layer_id;
+        topogeo_id := rel.topogeo_id;
+        element_id := rel.element_id;
+        RETURN NEXT;
+      END LOOP;
+
+      -- Check that all referenced faces exist
+      FOR rel IN
+        SELECT r.layer_id, r.topogeo_id, r.element_id
+        FROM relation r
+        WHERE r.layer_id = layerrec.layer_id
+        AND r.element_type = 3
+        AND r.element_id NOT IN (
+          SELECT face_id FROM face
+        )
+      LOOP
+        error := 'TopoGeometry references unexistent face';
+        layer_id := rel.layer_id;
+        topogeo_id := rel.topogeo_id;
+        element_id := rel.element_id;
+        RETURN NEXT;
+      END LOOP;
+
+    ELSE -- }{ Layer is hierarchical
+
+      --RAISE DEBUG 'Checking hierarchical layer %', layerrec.layer_id;
+
+      FOR rel IN
+        SELECT r.layer_id, r.topogeo_id, r.element_id
+        FROM relation r
+        WHERE r.layer_id = layerrec.layer_id
+        AND abs(r.element_id) NOT IN (
+          SELECT r2.topogeo_id
+          FROM relation r2
+          WHERE r2.layer_id = layerrec.child_id
+        )
+      LOOP
+        error := 'TopoGeometry references unexistent child';
+        layer_id := rel.layer_id;
+        topogeo_id := rel.topogeo_id;
+        element_id := rel.element_id;
+        RETURN NEXT;
+      END LOOP;
+
+    END IF; --} Layer is hierarchical
+  END LOOP; --}
+
+  EXECUTE 'SET search_PATH TO ' || search_path_backup;
+END;
+$BODY$
+LANGUAGE 'plpgsql' VOLATILE STRICT;
diff --git a/topology/test/regress/validatetopologyrelation.sql b/topology/test/regress/validatetopologyrelation.sql
new file mode 100644
index 0000000..36ab036
--- /dev/null
+++ b/topology/test/regress/validatetopologyrelation.sql
@@ -0,0 +1,50 @@
+
+\set VERBOSITY terse
+set client_min_messages to ERROR;
+
+\i ../load_topology.sql
+\i ../load_features.sql
+\i ../hierarchy.sql
+--\i ../more_features.sql
+
+SELECT 'valid-start', * FROM topology.ValidateTopologyRelation('city_data');
+
+-- Delete all primitives
+DELETE FROM city_data.edge_data;
+DELETE FROM city_data.node;
+DELETE FROM city_data.face WHERE face_id > 0;
+
+SELECT 'invalid-primitives', * FROM topology.ValidateTopologyRelation('city_data')
+ORDER BY 3,4,5;
+
+-- Delete features from primitive tables
+WITH
+deleted_land_parcels AS (
+  DELETE FROM features.land_parcels
+  RETURNING feature
+),
+deleted_traffic_signs AS (
+  DELETE FROM features.traffic_signs
+  RETURNING feature
+),
+deleted_city_streets AS (
+  DELETE FROM features.city_streets
+  RETURNING feature
+)
+SELECT NULL FROM (
+  SELECT ClearTopoGeom(feature) FROM deleted_land_parcels
+    UNION
+  SELECT ClearTopoGeom(feature) FROM deleted_traffic_signs
+    UNION
+  SELECT ClearTopoGeom(feature) FROM deleted_city_streets
+) foo
+;
+
+SELECT 'invalid-hierarchical', * FROM topology.ValidateTopologyRelation('city_data')
+ORDER BY 3,4,5;
+
+--SELECT * FROM topology.layer WHERE child_id IS NOT NULL;
+
+SELECT topology.DropTopology('city_data');
+DROP SCHEMA features CASCADE;
+
diff --git a/topology/test/regress/validatetopologyrelation_expected b/topology/test/regress/validatetopologyrelation_expected
new file mode 100644
index 0000000..b08a3a0
--- /dev/null
+++ b/topology/test/regress/validatetopologyrelation_expected
@@ -0,0 +1,28 @@
+invalid-primitives|TopoGeometry references unexistent face|1|1|3
+invalid-primitives|TopoGeometry references unexistent face|1|1|6
+invalid-primitives|TopoGeometry references unexistent face|1|2|4
+invalid-primitives|TopoGeometry references unexistent face|1|2|7
+invalid-primitives|TopoGeometry references unexistent face|1|3|5
+invalid-primitives|TopoGeometry references unexistent face|1|3|8
+invalid-primitives|TopoGeometry references unexistent face|1|4|2
+invalid-primitives|TopoGeometry references unexistent face|1|5|1
+invalid-primitives|TopoGeometry references unexistent node|2|1|14
+invalid-primitives|TopoGeometry references unexistent node|2|2|13
+invalid-primitives|TopoGeometry references unexistent node|2|3|6
+invalid-primitives|TopoGeometry references unexistent node|2|4|4
+invalid-primitives|TopoGeometry references unexistent edge|3|1|-10
+invalid-primitives|TopoGeometry references unexistent edge|3|1|9
+invalid-primitives|TopoGeometry references unexistent edge|3|2|-5
+invalid-primitives|TopoGeometry references unexistent edge|3|2|4
+invalid-primitives|TopoGeometry references unexistent edge|3|3|25
+invalid-primitives|TopoGeometry references unexistent edge|3|4|3
+invalid-hierarchical|TopoGeometry references unexistent child|4|1|1
+invalid-hierarchical|TopoGeometry references unexistent child|4|1|2
+invalid-hierarchical|TopoGeometry references unexistent child|4|2|3
+invalid-hierarchical|TopoGeometry references unexistent child|4|2|4
+invalid-hierarchical|TopoGeometry references unexistent child|5|1|1
+invalid-hierarchical|TopoGeometry references unexistent child|5|1|2
+invalid-hierarchical|TopoGeometry references unexistent child|5|2|4
+invalid-hierarchical|TopoGeometry references unexistent child|6|1|1
+invalid-hierarchical|TopoGeometry references unexistent child|6|1|2
+Topology 'city_data' dropped
diff --git a/topology/topology.sql.in b/topology/topology.sql.in
index d23f1dc..8719604 100644
--- a/topology/topology.sql.in
+++ b/topology/topology.sql.in
@@ -1812,6 +1812,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
 #include "sql/manage/FindTopology.sql.in"
 #include "sql/manage/FindLayer.sql.in"
 #include "sql/manage/ValidateTopology.sql.in"
+#include "sql/manage/ValidateTopologyRelation.sql.in"
 
 
 CREATE OR REPLACE FUNCTION topology.postgis_topology_scripts_installed() RETURNS text

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

Summary of changes:
 NEWS                                               |   1 +
 doc/extras_topology.xml                            |  36 ++++++
 topology/Makefile.in                               |   1 +
 .../sql/manage/ValidateTopologyRelation.sql.in     | 134 +++++++++++++++++++++
 topology/test/regress/validatetopologyrelation.sql |  50 ++++++++
 .../test/regress/validatetopologyrelation_expected |  28 +++++
 topology/topology.sql.in                           |   1 +
 7 files changed, 251 insertions(+)
 create mode 100644 topology/sql/manage/ValidateTopologyRelation.sql.in
 create mode 100644 topology/test/regress/validatetopologyrelation.sql
 create mode 100644 topology/test/regress/validatetopologyrelation_expected


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list