-- -- -- OBS_GetMeasure -- -- CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetMeasureResultMetadata(params json) RETURNS cdb_observatory.ds_return_metadata AS $$ DECLARE colnames text[]; -- Array to store the name of the measures to be returned coltypes text[]; -- Array to store the type of the measures to be returned requested_measures text[]; measure_id text; BEGIN -- By definition, all the measure results for the OBS_GetMeasure API are numeric values SELECT ARRAY(SELECT json_array_elements_text(params->'measure_id'))::text[] INTO requested_measures; FOREACH measure_id IN ARRAY requested_measures LOOP SELECT array_append(colnames, measure_id) INTO colnames; SELECT array_append(coltypes, 'numeric'::text) INTO coltypes; END LOOP; RETURN (colnames::text[], coltypes::text[]); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetMeasureQuery(table_schema text, table_name text, params json) RETURNS text AS $$ DECLARE data_query text; measure_ids_arr text[]; measure_id text; measures_list text; measures_query text; normalize text; boundary_id text; time_span text; geom_table_name text; data_table_name text; BEGIN measures_query := ''; -- SELECT table_name from obs_meta WHERE boundary_id = {bound} AND [...] INTO geom_table_name geom_table_name := 'observatory.obs_c6fb99c47d61289fbb8e561ff7773799d3fcc308'; -- SELECT table_name from obs_meta WHERE time_span = {time} AND [...] INTO data_table_name data_table_name := 'observatory.obs_1a098da56badf5f32e336002b0a81708c40d29cd'; -- Get measure_ids array from JSON SELECT ARRAY(SELECT json_array_elements_text(params->'measure_id'))::text[] INTO measure_ids_arr; -- Get a comma-separated list of measures ("total_pop, over_16_pop") to be used in SELECTs SELECT array_to_string(measure_ids_arr, ',') INTO measures_list; FOREACH measure_id IN ARRAY measure_ids_arr LOOP -- Build query to compute each value and normalize -- Assumes the default normalization method, the normalize parameter given in the JSON -- should be checked in order to build the final query SELECT measures_query || ' sum(' || measure_id || '/fraction)::numeric as ' || measure_id || ', ' INTO measures_query; END LOOP; -- Data query should select the measures and the cartodb_id of the user table, in that order. data_query := '(WITH _areas AS(SELECT ST_Area(a.the_geom::geography)' || '/ (1000 * 1000) as fraction, a.geoid, b.cartodb_id FROM ' || geom_table_name || ' as a, ' || table_schema || '.' || table_name || ' AS b ' || 'WHERE b.the_geom && a.the_geom ), values AS (SELECT geoid, ' || measures_list || ' FROM ' || data_table_name || ' ) ' || 'SELECT ' || measures_query || ' cartodb_id::int FROM _areas, values ' || 'WHERE values.geoid = _areas.geoid GROUP BY cartodb_id);'; RETURN data_query; END; $$ LANGUAGE plpgsql;