]> granicus.if.org Git - postgis/commitdiff
Implement interruptability of ST_Segmentize(geometry)
authorSandro Santilli <strk@keybit.net>
Wed, 22 Oct 2014 14:22:25 +0000 (14:22 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 22 Oct 2014 14:22:25 +0000 (14:22 +0000)
Includes testcases at sql and cunit levels.
Closes #2893

git-svn-id: http://svn.osgeo.org/postgis/trunk@13105 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
liblwgeom/cunit/cu_measures.c
liblwgeom/lwcollection.c
liblwgeom/lwline.c
liblwgeom/lwpoly.c
liblwgeom/ptarray.c
libpgcommon/lwgeom_pg.h
postgis/lwgeom_functions_basic.c
regress/Makefile.in
regress/interrupt.sql [new file with mode: 0644]
regress/interrupt_expected [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 060831111be40b00133a5d55dddb8e37d7a4278f..162da5d6d6989a77e64d6d1489363bf00c802d87 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,8 @@ PostGIS 2.2.0
 
  * Bug Fixes *
 
+  - #2893, Allow interruptibility of ST_Segmentize(geometry)
+           (Sandro Santilli / CartoDB)
   - #2540, Change GUC name for GDAL_DATA to postgis.gdal_datapath
   - #2777, Raster max extent constraint based upon envelope to behave
            like geometry extent
index 14487e339768f1e2c4dc3dbc225e2dd0a2b50d9b..20af13fcab33d7f8aace6d77ea7bf4ec5492d29f 100644 (file)
@@ -409,6 +409,46 @@ test_lwgeom_segmentize2d(void)
        lwfree(strout);
        lwgeom_free(linein);
        lwgeom_free(lineout);
+
+       /* test interruption */
+
+       linein = lwgeom_from_wkt("LINESTRING(0 0,10 0)", LW_PARSER_CHECK_NONE);
+       lwgeom_request_interrupt();
+       lineout = lwgeom_segmentize2d(linein, 1e-100);
+       CU_ASSERT_EQUAL(lineout, NULL);
+       lwgeom_free(linein);
+
+       linein = lwgeom_from_wkt("MULTILINESTRING((0 0,10 0),(20 0, 30 0))", LW_PARSER_CHECK_NONE);
+       lwgeom_request_interrupt();
+       lineout = lwgeom_segmentize2d(linein, 1e-100);
+       CU_ASSERT_EQUAL(lineout, NULL);
+       lwgeom_free(linein);
+
+       linein = lwgeom_from_wkt(
+"MULTIPOLYGON(((0 0,20 0,20 20,0 20,0 0),(2 2,2 4,4 4,4 2,2 2),(6 6,6 8,8 8,8 6,6 6)),((40 0,40 20,60 20,60 0,40 0),(42 2,42 4,44 4,44 2,42 2)))"
+    , LW_PARSER_CHECK_NONE);
+       lwgeom_request_interrupt();
+       lineout = lwgeom_segmentize2d(linein, 1e-100);
+       CU_ASSERT_EQUAL(lineout, NULL);
+       lwgeom_free(linein);
+
+       linein = lwgeom_from_wkt(
+"GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,20 0,20 20,0 20,0 0),(2 2,2 4,4 4,4 2,2 2),(6 6,6 8,8 8,8 6,6 6)),((40 0,40 20,60 20,60 0,40 0),(42 2,42 4,44 4,44 2,42 2))),MULTILINESTRING((0 0,10 0),(20 0, 30 0)),MULTIPOINT(0 0, 3 4))"
+    , LW_PARSER_CHECK_NONE);
+       CU_ASSERT_FATAL(linein != NULL);
+       lwgeom_request_interrupt();
+       lineout = lwgeom_segmentize2d(linein, 1e-100);
+       CU_ASSERT_EQUAL(lineout, NULL);
+       lwgeom_free(linein);
+
+       linein = lwgeom_from_wkt("LINESTRING(20 0, 30 0)", LW_PARSER_CHECK_NONE);
+       /* NOT INTERRUPTED */
+       lineout = lwgeom_segmentize2d(linein, 5);
+       strout = lwgeom_to_ewkt(lineout);
+       CU_ASSERT_STRING_EQUAL(strout, "LINESTRING(20 0,25 0,30 0)");
+       lwfree(strout);
+       lwgeom_free(linein);
+       lwgeom_free(lineout);
 }
 
 static void
index 68a6f800ab39faa29b0c4ecf9f0e54400253ed3b..089ad61afa22cadf19fa5b61b6aec2543e1b7f12 100644 (file)
@@ -229,7 +229,14 @@ lwcollection_segmentize2d(LWCOLLECTION *col, double dist)
 
        newgeoms = lwalloc(sizeof(LWGEOM *)*col->ngeoms);
        for (i=0; i<col->ngeoms; i++)
+       {
                newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
+               if ( ! newgeoms[i] ) {
+                       while (i--) lwgeom_free(newgeoms[i]);
+                       lwfree(newgeoms);
+                       return NULL;
+               }
+       }
 
        return lwcollection_construct(col->type, col->srid, NULL, col->ngeoms, newgeoms);
 }
index 570dea0782d8412955fafcfcb412321e232fde17..0fe0138a605ac1ee7428aa6e593f9f41d19280d8 100644 (file)
@@ -133,8 +133,9 @@ lwline_reverse(LWLINE *line)
 LWLINE *
 lwline_segmentize2d(LWLINE *line, double dist)
 {
-       return lwline_construct(line->srid, NULL,
-                               ptarray_segmentize2d(line->points, dist));
+       POINTARRAY *segmentized = ptarray_segmentize2d(line->points, dist);
+       if ( ! segmentized ) return NULL;
+       return lwline_construct(line->srid, NULL, segmentized);
 }
 
 /* check coordinate equality  */
index de475793ced449004050a1fc4effb8da66eb0405..4954a35514d9571f824883e35dc921bcfb132941 100644 (file)
@@ -216,6 +216,11 @@ lwpoly_segmentize2d(LWPOLY *poly, double dist)
        for (i=0; i<poly->nrings; i++)
        {
                newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
+               if ( ! newrings[i] ) {
+                       while (i--) ptarray_free(newrings[i]);
+                       lwfree(newrings);
+                       return NULL;
+               }
        }
        return lwpoly_construct(poly->srid, NULL,
                                poly->nrings, newrings);
index af26b4afdbb1838dbead444ba1a5284d0ca7a7d4..55abdf1b35a700d992faa003b6673e86dea58bf6 100644 (file)
@@ -434,6 +434,8 @@ ptarray_segmentize2d(const POINTARRAY *ipa, double dist)
                        p1 = p2;
                        ipoff++;
                }
+
+               LW_ON_INTERRUPT(ptarray_free(opa); return NULL);
        }
 
        return opa;
index 94638c2b3af6be31ec046ff86e5ab30a8595fe01..9de4eaff569144dd1f05201d9d852c29cffb55f0 100644 (file)
@@ -75,6 +75,11 @@ extern void pg_unparser_errhint(LWGEOM_UNPARSER_RESULT *lwg_unparser_result);
                 pg_unparser_errhint(&lwg_unparser_result); \
         } while(0);
 
+/* TODO: only cancel the interrupt if inside an outer call ? */
+#define LWGEOM_INIT() { \
+  lwgeom_cancel_interrupt(); \
+}
+
 
 /*
 ** GSERIALIED prototypes used outside the index functions
index 66767d332dbd038714a317dd9d539e2cc3f66b66..c78c6d61c02882b52720a03fe865bf2f70e426cc 100644 (file)
@@ -1904,15 +1904,22 @@ Datum LWGEOM_segmentize2d(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
        }
 
+       LWGEOM_INIT();
+
        inlwgeom = lwgeom_from_gserialized(ingeom);
-       
        if ( lwgeom_is_empty(inlwgeom) )
        {
+               /* Should only happen on interruption */
                lwgeom_free(inlwgeom);
                PG_RETURN_POINTER(ingeom);
        }
        
        outlwgeom = lwgeom_segmentize2d(inlwgeom, dist);
+       if ( ! outlwgeom ) {
+               /* Should only happen on interruption */
+               PG_FREE_IF_COPY(ingeom, 0);
+               PG_RETURN_NULL();
+       }
 
        /* Copy input bounding box if any */
        if ( inlwgeom->bbox )
index fb425d8bbc6121442d77ec27cac0d0db966a9e3e..b3d749cc4dd9bf6ecdc02ff9d5c17427dead54e0 100644 (file)
@@ -108,6 +108,7 @@ TESTS = \
        in_gml \
        in_kml \
        in_encodedpolyline \
+       interrupt \
        iscollection \
        regress_ogc \
        regress_ogc_cover \
diff --git a/regress/interrupt.sql b/regress/interrupt.sql
new file mode 100644 (file)
index 0000000..16af1e1
--- /dev/null
@@ -0,0 +1,14 @@
+SET statement_timeout TO 100;
+
+select ST_Buffer(g,100) from (
+  select (st_dumppoints(st_buffer(st_makepoint(0,0),10000,100000))).geom g
+) foo;
+
+SELECT
+ST_Segmentize(ST_MakeLine(ST_MakePoint(4,39), ST_MakePoint(1,41)),
+  1e-100);
+
+SET statement_timeout TO 0;
+
+-- Not affected by timeout
+SELECT '1',ST_AsText(ST_Segmentize('LINESTRING(0 0,4 0)'::geometry, 2));
diff --git a/regress/interrupt_expected b/regress/interrupt_expected
new file mode 100644 (file)
index 0000000..d9fa03e
--- /dev/null
@@ -0,0 +1,4 @@
+ERROR:  canceling statement due to statement timeout
+NOTICE:  liblwgeom code interrupted
+ERROR:  canceling statement due to statement timeout
+1|LINESTRING(0 0,2 0,4 0)