From 7ea428913aff050ed221fa90f9ccbe0df26c531d Mon Sep 17 00:00:00 2001 From: Javier Goizueta Date: Wed, 14 Feb 2018 17:50:06 +0100 Subject: [PATCH] Add limit to the grid-generating functions This adds an optinal maxcells parameter to the rectangle and hexagonal grids, with a default value of 262144 (2^18). An error occurs when the grids would need more cells. --- scripts-available/CDB_Hexagon.sql | 17 +++++++++++++++-- scripts-available/CDB_RectangleGrid.sql | 16 ++++++++++++++-- test/CDB_HexagonTest.sql | 6 ++++++ test/CDB_HexagonTest_expect | 3 +++ test/CDB_RectangleTest.sql | 5 +++++ test/CDB_RectangleTest_expect | 3 +++ 6 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 test/CDB_RectangleTest.sql create mode 100644 test/CDB_RectangleTest_expect diff --git a/scripts-available/CDB_Hexagon.sql b/scripts-available/CDB_Hexagon.sql index 68430b1..bb2b82d 100644 --- a/scripts-available/CDB_Hexagon.sql +++ b/scripts-available/CDB_Hexagon.sql @@ -10,6 +10,10 @@ AS $$ WHERE path[1] % 2 != 0 $$ LANGUAGE 'sql' IMMUTABLE STRICT PARALLEL SAFE; + +-- In older versions of the extension, CDB_HexagonGrid had a different signature +DROP FUNCTION IF EXISTS cartodb.CDB_HexagonGrid(GEOMETRY, FLOAT8, GEOMETRY); + -- -- Fill given extent with an hexagonal coverage -- @@ -25,10 +29,13 @@ $$ LANGUAGE 'sql' IMMUTABLE STRICT PARALLEL SAFE; -- If omitted the origin will be 0,0. -- The parameter is checked for having the same SRID -- as the extent. --- -- +-- @param maxcells Optional maximum number of grid cells to generate; +-- if the grid requires more cells to cover the extent +-- and exception will occur. +---- -- DROP FUNCTION IF EXISTS CDB_HexagonGrid(ext GEOMETRY, side FLOAT8); -CREATE OR REPLACE FUNCTION CDB_HexagonGrid(ext GEOMETRY, side FLOAT8, origin GEOMETRY DEFAULT NULL) +CREATE OR REPLACE FUNCTION CDB_HexagonGrid(ext GEOMETRY, side FLOAT8, origin GEOMETRY DEFAULT NULL, maxcells INTEGER DEFAULT 512*512) RETURNS SETOF GEOMETRY AS $$ DECLARE @@ -107,6 +114,12 @@ BEGIN vstartary := ARRAY[ vstart - (vstep/2.0), vstart ]; END IF; + If maxcells IS NOT NULL AND maxcells > 0 THEN + IF CEIL((CEIL((vend-vstart)/(vstep/2.0)) * CEIL((hend-hstart)/(hstep*2.0/3.0)))/3.0)::integer > maxcells THEN + RAISE EXCEPTION 'The requested grid is too big to be rendered'; + END IF; + END IF; + vstartidx := abs(hskip)%2; RAISE DEBUG 'vstartary: % : %', vstartary[1], vstartary[2]; diff --git a/scripts-available/CDB_RectangleGrid.sql b/scripts-available/CDB_RectangleGrid.sql index c2bc166..6c01e03 100644 --- a/scripts-available/CDB_RectangleGrid.sql +++ b/scripts-available/CDB_RectangleGrid.sql @@ -1,3 +1,6 @@ +-- In older versions of the extension, CDB_RectangleGrid had a different signature +DROP FUNCTION IF EXISTS cartodb.CDB_RectangleGrid(GEOMETRY, FLOAT8, FLOAT8, GEOMETRY); + -- -- Fill given extent with a rectangular coverage -- @@ -14,9 +17,12 @@ -- If omitted the origin will be 0,0. -- The parameter is checked for having the same SRID -- as the extent. --- -- -CREATE OR REPLACE FUNCTION CDB_RectangleGrid(ext GEOMETRY, width FLOAT8, height FLOAT8, origin GEOMETRY DEFAULT NULL) +-- @param maxcells Optional maximum number of grid cells to generate; +-- if the grid requires more cells to cover the extent +-- and exception will occur. +-- +CREATE OR REPLACE FUNCTION CDB_RectangleGrid(ext GEOMETRY, width FLOAT8, height FLOAT8, origin GEOMETRY DEFAULT NULL, maxcells INTEGER DEFAULT 512*512) RETURNS SETOF GEOMETRY AS $$ DECLARE @@ -79,6 +85,12 @@ BEGIN --RAISE DEBUG 'hend: %', hend; --RAISE DEBUG 'vend: %', vend; + If maxcells IS NOT NULL AND maxcells > 0 THEN + IF ((hend - hstart)/hstep * (vend - vstart)/vstep)::integer > maxcells THEN + RAISE EXCEPTION 'The requested grid is too big to be rendered'; + END IF; + END IF; + x := hstart; WHILE x < hend LOOP -- over X y := vstart; diff --git a/test/CDB_HexagonTest.sql b/test/CDB_HexagonTest.sql index 66b52b1..156a916 100644 --- a/test/CDB_HexagonTest.sql +++ b/test/CDB_HexagonTest.sql @@ -45,3 +45,9 @@ WITH 0.002 as radius ), grid AS ( SELECT CDB_HexagonGrid(env, radius) AS cell from params) SELECT '#160', count(cell) > 23000 from grid; + +-- Check small grids are generated... +SELECT COUNT(*) FROM cartodb.CDB_HexagonGrid(ST_MakeEnvelope(0,0,1000,1000,3857), 10); + +-- But large grids produce an error +SELECT COUNT(*) FROM cartodb.CDB_HexagonGrid(ST_MakeEnvelope(0,0,1000,1000,3857), 1); diff --git a/test/CDB_HexagonTest_expect b/test/CDB_HexagonTest_expect index 08e74f2..a6b6133 100644 --- a/test/CDB_HexagonTest_expect +++ b/test/CDB_HexagonTest_expect @@ -1,2 +1,5 @@ 9|63|count / npoints #160|t +3886 +ERROR: The requested grid is too big to be rendered +CONTEXT: PL/pgSQL function cdb_hexagongrid(geometry,double precision,geometry,integer) line 80 at RAISE diff --git a/test/CDB_RectangleTest.sql b/test/CDB_RectangleTest.sql new file mode 100644 index 0000000..76ec66e --- /dev/null +++ b/test/CDB_RectangleTest.sql @@ -0,0 +1,5 @@ +-- Check small grids are generated... +SELECT COUNT(*) FROM cartodb.CDB_RectangleGrid(ST_MakeEnvelope(0,0,1000,1000,3857), 10, 10); + +-- But large grids produce an error +SELECT COUNT(*) FROM cartodb.CDB_RectangleGrid(ST_MakeEnvelope(0,0,1000,1000,3857), 1, 1); diff --git a/test/CDB_RectangleTest_expect b/test/CDB_RectangleTest_expect new file mode 100644 index 0000000..b2de4df --- /dev/null +++ b/test/CDB_RectangleTest_expect @@ -0,0 +1,3 @@ +10000 +ERROR: The requested grid is too big to be rendered +CONTEXT: PL/pgSQL function cdb_rectanglegrid(geometry,double precision,double precision,geometry,integer) line 64 at RAISE