cartodb-postgresql/scripts-available/CDB_Overviews.sql
2015-12-15 17:36:27 +01:00

93 lines
3.0 KiB
PL/PgSQL

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;