From d0e66910a0a1b228552a96d596499fb19e7d5ecb Mon Sep 17 00:00:00 2001 From: Javier Goizueta Date: Tue, 15 Dec 2015 17:36:27 +0100 Subject: [PATCH] Sketch for new Overview-creation functionality --- doc/CDB_Overviews.md | 28 +++++++++ scripts-available/CDB_Overviews.sql | 92 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 doc/CDB_Overviews.md create mode 100644 scripts-available/CDB_Overviews.sql diff --git a/doc/CDB_Overviews.md b/doc/CDB_Overviews.md new file mode 100644 index 0000000..e934b30 --- /dev/null +++ b/doc/CDB_Overviews.md @@ -0,0 +1,28 @@ +Create overviews for vector dataset. + +#### Using the function + +The table for which overviews will be generated should be +a Cartodbfied dataset with vector geometry. + +```sql +SELECT CDB_CreateOverviews('table_name'); +--- Generates overview tables for the dataset +``` + +#### Arguments + +CDB_CreateOverviews(table_name, ref_z_strategy, reduction_strategy) + +* **table_name** regclass, table for which overviews will be generated +* **ref_z_strategy** regproc, function that provides the Z-scale strategy. + It returns the base Z level for the dataset. + It should have these arguments: + - **table_name** regclass, table to compute the reference Z scale for +* **reduction_strategy** regproc, function that provides the reduction strategy + to generate an overview table from a table for a smaller scale (higher Z number). + It returns the name of the generated table. + It should have these arguments: + - **base_table_name** regclass, base table to be reduced. + - **base_z** integer, base Z level assigned to the base table. + - **overview_z** integer, Z level for which to generate the overview. diff --git a/scripts-available/CDB_Overviews.sql b/scripts-available/CDB_Overviews.sql new file mode 100644 index 0000000..6ace4a2 --- /dev/null +++ b/scripts-available/CDB_Overviews.sql @@ -0,0 +1,92 @@ + +CREATE OR REPLACE FUNCTION _CDB_Dummy_Ref_Z_Strategy(reloid REGCLASS) +RETURNS INTEGER +AS $$ + BEGIN + -- TODO: should determine the proper *base* level for the table considering + -- the density of features and precision/detail of the data, + -- so that for Z levels equal or greater than the reference, + -- the data can be represented clearly (without having to render uneccessary + -- detail) + RETURN 9; + END; +$$ LANGUAGE PLPGSQL STABLE; + +CREATE OR REPLACE FUNCTION _CDB_Overview_Name(ref REGCLASS, ref_z INTEGER, overview_z INTEGER) +RETURNS TEXT +AS $$ + DECLARE + base TEXT; + suffix TEXT; + is_overview BOOLEAN; + BEGIN + suffix := Format('_ov%', ref_z); + SELECT ref::text LIKE Format('%%%s', suffix) INTO is_overview; + IF is_overview THEN + SELECT substring(ref::text FROM 1 FOR length(ref::text)-length(suffix)) INTO base; + ELSE + base := ref; + END IF; + RETURN Format('%s_ov%s', base::text, overview_z); + END +$$ LANGUAGE PLPGSQL IMMUTABLE; + +CREATE OR REPLACE FUNCTION _CDB_Dummy_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER) +RETURNS REGCLASS +AS $$ + DECLARE + overview_rel TEXT; + reduction FLOAT8; + base_name TEXT; + BEGIN + overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z); + -- TODO: implement a proper reduction technique. + -- Here we're just inefficiently sampling the data to mantain + -- the approximate visual density of the reference level. + reduction := power(2, 2*(overview_z - ref_z)); + EXECUTE Format('DROP TABLE IF EXISTS %s CASCADE;', overview_rel); + EXECUTE Format('CREATE TABLE %s AS SELECT * FROM %s WHERE random() < %s;', overview_rel, reloid, reduction); + RETURN overview_rel; + END; +$$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE FUNCTION CDB_CreateOverviews( + reloid REGCLASS, + refscale_strategy regproc DEFAULT '_CDB_Dummy_Ref_Z_Strategy'::regproc, + reduce_strategy regproc DEFAULT '_CDB_Dummy_Reduce_Strategy'::regproc +) +RETURNS text[] +AS $$ +DECLARE + ref_z integer; + overviews_z integer[]; + base_z integer; + base_rel REGCLASS; + overview_z integer; + overview_tables REGCLASS[]; +BEGIN + -- Determine the referece zoom level + EXECUTE 'SELECT ' || quote_ident(refscale_strategy::text) || Format('(''%s'');', reloid) INTO ref_z; + + -- Determine overlay zoom levels + -- TODO: should be handled by the refscale_stragegy? + overview_z := ref_z - 1; + WHILE overview_z >= 0 LOOP + SELECT array_append(overviews_z, overview_z) INTO overviews_z; + overview_z := overview_z - 2; + END LOOP; + + -- Create overlay tables + base_z := ref_z; + base_rel := reloid; + FOREACH overview_z IN ARRAY overviews_z LOOP + EXECUTE 'SELECT ' || quote_ident(reduce_strategy::text) || Format('(''%s'', %s, %s);', base_rel, base_z, overview_z) INTO base_rel; + SELECT array_append(overview_tables, base_rel) INTO overview_tables; + END LOOP; + + -- TODO: we'll need to store metadata somewhere to define + -- which overlay levels are available. + + RETURN overview_tables; +END; +$$ LANGUAGE PLPGSQL;