changeset 3561:453f15ba8030

Improve error handling in area generation Instead of hitting a NOT NULL constraint later on, raise an error if no candidate area for cutting is found.
author Tom Gottfried <tom@intevation.de>
date Fri, 31 May 2019 16:58:42 +0200
parents ec1aec03676d
children c03224d33e78
files pkg/imports/errors.go schema/isrs_functions.sql schema/isrs_tests.sql schema/run_tests.sh
diffstat 4 files changed, 40 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/imports/errors.go	Fri May 31 16:54:09 2019 +0200
+++ b/pkg/imports/errors.go	Fri May 31 16:58:42 2019 +0200
@@ -72,6 +72,8 @@
 			return "No distance mark found for at least one given ISRS Location Code"
 		case strings.Contains(recent, "isrsrange_axis"):
 			return "No contiguous axis found between given ISRS Location Codes"
+		case strings.Contains(recent, "isrsrange_area"):
+			return "No area around axis between given ISRS Location Codes"
 		}
 	}
 	return "Unexpected database error: " + err.Message
--- a/schema/isrs_functions.sql	Fri May 31 16:54:09 2019 +0200
+++ b/schema/isrs_functions.sql	Fri May 31 16:58:42 2019 +0200
@@ -165,16 +165,21 @@
     area geometry
 ) RETURNS geometry
 AS $$
+DECLARE
+    area_subset geometry;
+    result_geom geometry;
+BEGIN
+    -- In case area is a multipolygon, process the union of those
+    -- polygons, which intersect with the axis. The union is to avoid
+    -- problems with invalid/self-intersecting multipolygons
+    SELECT ST_Union(a_dmp.geom)
+        INTO STRICT area_subset
+        FROM (SELECT ST_MakeValid(ST_Transform(geom, ST_SRID(axis)))
+                FROM ST_Dump(area)) AS a_dmp (geom)
+        WHERE ST_Intersects(a_dmp.geom, axis)
+        HAVING ST_Union(a_dmp.geom) IS NOT NULL;
+
     WITH
-        area_subset AS (
-            -- In case area is a multipolygon, process the union of those
-            -- polygons, which intersect with the axis. The union is to avoid
-            -- problems with invalid/self-intersecting multipolygons
-            SELECT ST_Union(a_dmp.geom) AS area
-                FROM (SELECT ST_MakeValid(ST_Transform(geom, ST_SRID(axis)))
-                        FROM ST_Dump(area)) AS a_dmp (geom)
-                WHERE ST_Intersects(a_dmp.geom, axis)
-            ),
         rotated_ends AS (
             SELECT ST_Collect(ST_Scale(
                     ST_Translate(e,
@@ -185,18 +190,23 @@
                         FROM (VALUES (1), (-1)) AS idx (i)) AS ep,
                     ST_Rotate(ST_PointN(axis, i*2), pi()/2, p1) AS ep2 (p2),
                     ST_Makeline(p1, p2) AS e (e),
-                    area_subset,
-                    LATERAL (SELECT (ST_MaxDistance(p1, area) / ST_Length(e))
+                    LATERAL (
+                        SELECT (ST_MaxDistance(p1, area_subset) / ST_Length(e))
                             * 2) AS d (d)),
         range_area AS (
             -- Split area by orthogonal lines at the ends of the clipped axis
             SELECT (ST_Dump(ST_CollectionExtract(
-                    ST_Split(area, blade), 3))).geom
-                FROM area_subset, rotated_ends)
+                    ST_Split(area_subset, blade), 3))).geom
+                FROM rotated_ends)
         -- From the polygons returned by the last CTE, select only those
         -- around the clipped axis
         SELECT ST_Multi(ST_Transform(ST_Union(range_area.geom), ST_SRID(area)))
+            INTO result_geom
             FROM range_area
-            WHERE ST_Intersects(ST_Buffer(range_area.geom, -0.0001), axis)
+            WHERE ST_Intersects(ST_Buffer(range_area.geom, -0.0001), axis);
+
+    RETURN result_geom;
+END;
     $$
-    LANGUAGE sql;
+    LANGUAGE plpgsql
+    STABLE PARALLEL SAFE;
--- a/schema/isrs_tests.sql	Fri May 31 16:54:09 2019 +0200
+++ b/schema/isrs_tests.sql	Fri May 31 16:58:42 2019 +0200
@@ -58,14 +58,21 @@
         5)),
     'ISRSrange_axis returns a valid simple feature');
 
-SELECT ok(
-    ISRSrange_area(ISRSrange_axis(isrsrange(
+SELECT throws_ok($$
+    SELECT ISRSrange_area('LINESTRING(0 0, 1 1)', NULL)
+    $$,
+    'P0002', NULL,
+    'ISRSrange_area fails if no input area is given');
+
+SELECT throws_ok($$
+    SELECT ISRSrange_area(ISRSrange_axis(isrsrange(
                 ('AT', 'XXX', '00001', '00000', 0)::isrs,
                 ('AT', 'XXX', '00001', '00000', 1)::isrs),
             5),
-        ST_SetSRID('POLYGON((0 1, 0 2, 1 2, 1 1, 0 1))'::geometry, 4326)
-    ) IS NULL,
-    'ISRSrange_area returns NULL, if given area does not intersect with axis');
+        ST_SetSRID('POLYGON((0 1, 0 2, 1 2, 1 1, 0 1))'::geometry, 4326))
+    $$,
+    'P0002', NULL,
+    'ISRSrange_area fails, if given area does not intersect with axis');
 
 SELECT results_eq($$
     SELECT every(ST_DWithin(
--- a/schema/run_tests.sh	Fri May 31 16:54:09 2019 +0200
+++ b/schema/run_tests.sh	Fri May 31 16:58:42 2019 +0200
@@ -28,7 +28,7 @@
     -c 'SET client_min_messages TO WARNING' \
     -c "DROP ROLE IF EXISTS $TEST_ROLES" \
     -f tap_tests_data.sql \
-    -c "SELECT plan(64 + (
+    -c "SELECT plan(65 + (
             SELECT count(*)::int
                 FROM information_schema.tables
                 WHERE table_schema = 'waterway'))" \