Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58e2e7e238 | ||
|
|
25d27263cb | ||
|
|
bbadcc838e | ||
|
|
b1a0904c07 | ||
|
|
399b680b41 | ||
|
|
7c0636c5f9 | ||
|
|
f58f870457 | ||
|
|
a7c8dc04e3 | ||
|
|
90ee56eb35 | ||
|
|
1032737600 | ||
|
|
24639713f1 | ||
|
|
fff7e926c9 | ||
|
|
7d7ecc06f5 | ||
|
|
5992304b47 | ||
|
|
5c52e7564f | ||
|
|
0b7fbdc1cb | ||
|
|
0bfdeae147 | ||
|
|
aa9286eaba | ||
|
|
30cd4cf1f9 | ||
|
|
1356131ec1 | ||
|
|
9731ce38ec | ||
|
|
07892271e5 | ||
|
|
3122a0479d | ||
|
|
956e56cd37 | ||
|
|
b19a5fc3dc | ||
|
|
0ecbbd8e71 |
6
Makefile
6
Makefile
@@ -1,7 +1,7 @@
|
||||
# cartodb/Makefile
|
||||
|
||||
EXTENSION = cartodb
|
||||
EXTVERSION = 0.18.1
|
||||
EXTVERSION = 0.18.5
|
||||
|
||||
SED = sed
|
||||
|
||||
@@ -75,6 +75,10 @@ UPGRADABLE = \
|
||||
0.17.1 \
|
||||
0.18.0 \
|
||||
0.18.1 \
|
||||
0.18.2 \
|
||||
0.18.3 \
|
||||
0.18.4 \
|
||||
0.18.5 \
|
||||
$(EXTVERSION)dev \
|
||||
$(EXTVERSION)next \
|
||||
$(END)
|
||||
|
||||
24
NEWS.md
24
NEWS.md
@@ -1,3 +1,25 @@
|
||||
0.18.5 (2016-11-30)
|
||||
|
||||
* Add to new overview creation strategies #290
|
||||
* Fix tests: race condition with publicuser #157
|
||||
* Fix: CDB_Stats divisions by zero #181
|
||||
* Better implementation of `CDB_EqualIntervalBins` #244
|
||||
* New tests for binning functions #249
|
||||
|
||||
0.18.4 (2016-11-04)
|
||||
|
||||
* No functional changes; fixes the migration from previous versions #288
|
||||
|
||||
0.18.3 (2016-11-03)
|
||||
|
||||
* Exclude analysis cache tables from the quota #281
|
||||
|
||||
0.18.2 (2016-10-20)
|
||||
-------------------
|
||||
|
||||
* Fix: cleanup inconsistent position of `username` column in analysis catalog after upgrades
|
||||
[#285](https://github.com/cartodb/cartodb-postgresql/pull/285)
|
||||
|
||||
0.18.1 (2016-10-19)
|
||||
-------------------
|
||||
|
||||
@@ -8,8 +30,6 @@
|
||||
|
||||
* Fix: exclude NULL geometries when creating Overviews #269
|
||||
* Function to check analysis tables limits #279
|
||||
* Exclude analysis cache tables from the quota #281
|
||||
|
||||
|
||||
0.17.1 (2016-08-16)
|
||||
-------------------
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
-- Table to register analysis nodes from https://github.com/cartodb/camshaft
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
cartodb.cdb_analysis_catalog (
|
||||
-- useful for multi account deployments
|
||||
username text,
|
||||
-- md5 hex hash
|
||||
node_id char(40) CONSTRAINT cdb_analysis_catalog_pkey PRIMARY KEY,
|
||||
-- being json allows to do queries like analysis_def->>'type' = 'buffer'
|
||||
@@ -28,7 +26,9 @@ cartodb.cdb_analysis_catalog (
|
||||
-- store error message for failures
|
||||
last_error_message text,
|
||||
-- cached tables involved in the analysis
|
||||
cache_tables regclass[] NOT NULL DEFAULT '{}'
|
||||
cache_tables regclass[] NOT NULL DEFAULT '{}',
|
||||
-- useful for multi account deployments
|
||||
username text
|
||||
);
|
||||
|
||||
-- This can only be called from an SQL script executed by CREATE EXTENSION
|
||||
@@ -38,14 +38,9 @@ BEGIN
|
||||
END
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
ALTER TABLE cartodb.cdb_analysis_catalog ADD COLUMN username text;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN END;
|
||||
END;
|
||||
$$;
|
||||
-- Migrations to add new columns from old versions.
|
||||
-- IMPORTANT: Those columns will be added in order of creation. To be consistent
|
||||
-- in column order, ensure that new columns are added at the end and in the same order.
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
@@ -73,3 +68,28 @@ DO $$
|
||||
WHEN duplicate_column THEN END;
|
||||
END;
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
ALTER TABLE cartodb.cdb_analysis_catalog ADD COLUMN username text;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN END;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- We want the "username" column to be moved to the last position if it was on a position from other versions
|
||||
-- see https://github.com/CartoDB/cartodb-postgresql/issues/276
|
||||
DO LANGUAGE 'plpgsql' $$
|
||||
DECLARE
|
||||
column_index int;
|
||||
BEGIN
|
||||
SELECT ordinal_position FROM information_schema.columns WHERE table_name='cdb_analysis_catalog' AND table_schema='cartodb' AND column_name='username' INTO column_index;
|
||||
IF column_index = 1 OR column_index = 10 THEN
|
||||
ALTER TABLE cartodb.cdb_analysis_catalog ADD COLUMN username_final text;
|
||||
UPDATE cartodb.cdb_analysis_catalog SET username_final = username;
|
||||
ALTER TABLE cartodb.cdb_analysis_catalog DROP COLUMN username;
|
||||
ALTER TABLE cartodb.cdb_analysis_catalog RENAME COLUMN username_final TO username;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
--
|
||||
-- Calculate the equal interval bins for a given column
|
||||
--
|
||||
-- @param in_array A numeric array of numbers to determine the best
|
||||
-- to determine the bin boundary
|
||||
-- @param in_array An array of numbers to determine the best
|
||||
-- bin boundary
|
||||
--
|
||||
-- @param breaks The number of bins you want to find.
|
||||
--
|
||||
@@ -11,27 +11,14 @@
|
||||
--
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_EqualIntervalBins ( in_array NUMERIC[], breaks INT ) RETURNS NUMERIC[] as $$
|
||||
DECLARE
|
||||
diff numeric;
|
||||
min_val numeric;
|
||||
max_val numeric;
|
||||
tmp_val numeric;
|
||||
i INT := 1;
|
||||
reply numeric[];
|
||||
BEGIN
|
||||
SELECT min(e), max(e) INTO min_val, max_val FROM ( SELECT unnest(in_array) e ) x WHERE e IS NOT NULL;
|
||||
diff = (max_val - min_val) / breaks::numeric;
|
||||
LOOP
|
||||
IF i < breaks THEN
|
||||
tmp_val = min_val + i::numeric * diff;
|
||||
reply = array_append(reply, tmp_val);
|
||||
i := i+1;
|
||||
ELSE
|
||||
reply = array_append(reply, max_val);
|
||||
EXIT;
|
||||
END IF;
|
||||
END LOOP;
|
||||
RETURN reply;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
CREATE OR REPLACE FUNCTION CDB_EqualIntervalBins ( in_array anyarray, breaks INT ) RETURNS anyarray as $$
|
||||
WITH stats AS (
|
||||
SELECT min(e), (max(e)-min(e))/breaks AS del
|
||||
FROM (SELECT unnest(in_array) e) AS p)
|
||||
SELECT array_agg(bins)
|
||||
FROM (
|
||||
SELECT min + generate_series(1,breaks)*del AS bins
|
||||
FROM stats) q;
|
||||
$$ LANGUAGE SQL IMMUTABLE;
|
||||
|
||||
DROP FUNCTION IF EXISTS CDB_EqualIntervalBins( numeric[], integer);
|
||||
|
||||
@@ -697,6 +697,356 @@ AS $$
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION _CDB_GridCluster_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER, grid_px FLOAT8 DEFAULT NULL)
|
||||
RETURNS REGCLASS
|
||||
AS $$
|
||||
DECLARE
|
||||
overview_rel TEXT;
|
||||
reduction FLOAT8;
|
||||
base_name TEXT;
|
||||
pixel_m FLOAT8;
|
||||
grid_m FLOAT8;
|
||||
offset_m FLOAT8;
|
||||
offset_x TEXT;
|
||||
offset_y TEXT;
|
||||
cell_x TEXT;
|
||||
cell_y TEXT;
|
||||
aggr_attributes TEXT;
|
||||
attributes TEXT;
|
||||
columns TEXT;
|
||||
gtypes TEXT[];
|
||||
schema_name TEXT;
|
||||
table_name TEXT;
|
||||
point_geom TEXT;
|
||||
BEGIN
|
||||
SELECT _CDB_GeometryTypes(reloid) INTO gtypes;
|
||||
IF gtypes IS NULL OR array_upper(gtypes, 1) <> 1 OR gtypes[1] <> 'ST_Point' THEN
|
||||
-- This strategy only supports datasets with point geomety
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
--TODO: check applicability: geometry type, minimum number of points...
|
||||
|
||||
overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z);
|
||||
|
||||
-- Grid size in pixels at Z level overview_z
|
||||
IF grid_px IS NULL THEN
|
||||
grid_px := 1.0;
|
||||
END IF;
|
||||
|
||||
SELECT * FROM _cdb_split_table_name(reloid) INTO schema_name, table_name;
|
||||
|
||||
-- pixel_m: size of a pixel in webmercator units (meters)
|
||||
SELECT CDB_XYZ_Resolution(overview_z) INTO pixel_m;
|
||||
-- grid size in meters
|
||||
grid_m = grid_px * pixel_m;
|
||||
|
||||
attributes := _CDB_Aggregable_Attributes_Expression(reloid);
|
||||
aggr_attributes := _CDB_Aggregated_Attributes_Expression(reloid);
|
||||
IF attributes <> '' THEN
|
||||
attributes := ', ' || attributes;
|
||||
END IF;
|
||||
IF aggr_attributes <> '' THEN
|
||||
aggr_attributes := aggr_attributes || ', ';
|
||||
END IF;
|
||||
|
||||
-- Center of each cell:
|
||||
cell_x := Format('gx*%1$s + %2$s', grid_m, grid_m/2);
|
||||
cell_y := Format('gy*%1$s + %2$s', grid_m, grid_m/2);
|
||||
|
||||
-- Displacement to the nearest pixel center:
|
||||
IF MOD(grid_px::numeric, 1.0::numeric) = 0 THEN
|
||||
offset_m := pixel_m/2 - MOD((grid_m/2)::numeric, pixel_m::numeric)::float8;
|
||||
offset_x := Format('%s', offset_m);
|
||||
offset_y := Format('%s', offset_m);
|
||||
ELSE
|
||||
offset_x := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_x, pixel_m);
|
||||
offset_y := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_y, pixel_m);
|
||||
END IF;
|
||||
|
||||
point_geom := Format('ST_SetSRID(ST_MakePoint(%1$s + %3$s, %2$s + %4$s), 3857)', cell_x, cell_y, offset_x, offset_y);
|
||||
|
||||
-- compute the resulting columns in the same order as in the base table
|
||||
WITH cols AS (
|
||||
SELECT
|
||||
CASE c
|
||||
WHEN 'cartodb_id' THEN 'cartodb_id'
|
||||
WHEN 'the_geom' THEN
|
||||
Format('ST_Transform(%s, 4326) AS the_geom', point_geom)
|
||||
WHEN 'the_geom_webmercator' THEN
|
||||
Format('%s AS the_geom_webmercator', point_geom)
|
||||
ELSE c
|
||||
END AS column
|
||||
FROM CDB_ColumnNames(reloid) c
|
||||
)
|
||||
SELECT string_agg(s.column, ',') FROM (
|
||||
SELECT * FROM cols
|
||||
) AS s INTO columns;
|
||||
|
||||
IF NOT columns LIKE '%_feature_count%' THEN
|
||||
columns := columns || ', n AS _feature_count';
|
||||
END IF;
|
||||
|
||||
EXECUTE Format('DROP TABLE IF EXISTS %I.%I CASCADE;', schema_name, overview_rel);
|
||||
|
||||
-- Now we cluster the data using a grid of size grid_m
|
||||
-- and selecte the centroid (average coordinates) of each cluster.
|
||||
-- If we had a selected numeric attribute of interest we could use it
|
||||
-- as a weight for the average coordinates.
|
||||
EXECUTE Format('
|
||||
CREATE TABLE %7$I.%3$I AS
|
||||
WITH clusters AS (
|
||||
SELECT
|
||||
%5$s
|
||||
count(*) AS n,
|
||||
Floor(ST_X(f.the_geom_webmercator)/%2$s)::int AS gx,
|
||||
Floor(ST_Y(f.the_geom_webmercator)/%2$s)::int AS gy,
|
||||
MIN(cartodb_id) AS cartodb_id
|
||||
FROM %1$s f
|
||||
GROUP BY gx, gy
|
||||
)
|
||||
SELECT %6$s FROM clusters
|
||||
', reloid::text, grid_m, overview_rel, attributes, aggr_attributes, columns, schema_name);
|
||||
|
||||
RETURN Format('%I.%I', schema_name, overview_rel)::regclass;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
-- This strategy places the aggregation of each cluster at the centroid of the cluster members.
|
||||
CREATE OR REPLACE FUNCTION _CDB_GridClusterCentroid_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER, grid_px FLOAT8 DEFAULT NULL)
|
||||
RETURNS REGCLASS
|
||||
AS $$
|
||||
DECLARE
|
||||
overview_rel TEXT;
|
||||
reduction FLOAT8;
|
||||
base_name TEXT;
|
||||
pixel_m FLOAT8;
|
||||
grid_m FLOAT8;
|
||||
offset_m FLOAT8;
|
||||
offset_x TEXT;
|
||||
offset_y TEXT;
|
||||
cell_x TEXT;
|
||||
cell_y TEXT;
|
||||
aggr_attributes TEXT;
|
||||
attributes TEXT;
|
||||
columns TEXT;
|
||||
gtypes TEXT[];
|
||||
schema_name TEXT;
|
||||
table_name TEXT;
|
||||
point_geom TEXT;
|
||||
BEGIN
|
||||
SELECT _CDB_GeometryTypes(reloid) INTO gtypes;
|
||||
IF gtypes IS NULL OR array_upper(gtypes, 1) <> 1 OR gtypes[1] <> 'ST_Point' THEN
|
||||
-- This strategy only supports datasets with point geomety
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
--TODO: check applicability: geometry type, minimum number of points...
|
||||
|
||||
overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z);
|
||||
|
||||
-- Grid size in pixels at Z level overview_z
|
||||
IF grid_px IS NULL THEN
|
||||
grid_px := 1.0;
|
||||
END IF;
|
||||
|
||||
SELECT * FROM _cdb_split_table_name(reloid) INTO schema_name, table_name;
|
||||
|
||||
-- pixel_m: size of a pixel in webmercator units (meters)
|
||||
SELECT CDB_XYZ_Resolution(overview_z) INTO pixel_m;
|
||||
-- grid size in meters
|
||||
grid_m = grid_px * pixel_m;
|
||||
|
||||
attributes := _CDB_Aggregable_Attributes_Expression(reloid);
|
||||
aggr_attributes := _CDB_Aggregated_Attributes_Expression(reloid);
|
||||
IF attributes <> '' THEN
|
||||
attributes := ', ' || attributes;
|
||||
END IF;
|
||||
IF aggr_attributes <> '' THEN
|
||||
aggr_attributes := aggr_attributes || ', ';
|
||||
END IF;
|
||||
|
||||
-- Center of each cell:
|
||||
cell_x := Format('gx*%1$s + %2$s', grid_m, grid_m/2);
|
||||
cell_y := Format('gy*%1$s + %2$s', grid_m, grid_m/2);
|
||||
|
||||
-- Displacement to the nearest pixel center:
|
||||
IF MOD(grid_px::numeric, 1.0::numeric) = 0 THEN
|
||||
offset_m := pixel_m/2 - MOD((grid_m/2)::numeric, pixel_m::numeric)::float8;
|
||||
offset_x := Format('%s', offset_m);
|
||||
offset_y := Format('%s', offset_m);
|
||||
ELSE
|
||||
offset_x := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_x, pixel_m);
|
||||
offset_y := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_y, pixel_m);
|
||||
END IF;
|
||||
|
||||
point_geom := Format('ST_SetSRID(ST_MakePoint(%1$s + %3$s, %2$s + %4$s), 3857)', cell_x, cell_y, offset_x, offset_y);
|
||||
|
||||
-- compute the resulting columns in the same order as in the base table
|
||||
WITH cols AS (
|
||||
SELECT
|
||||
CASE c
|
||||
WHEN 'cartodb_id' THEN 'cartodb_id'
|
||||
WHEN 'the_geom' THEN
|
||||
'ST_Transform(ST_SetSRID(ST_MakePoint(_sum_of_x/n, _sum_of_y/n), 3857), 4326) AS the_geom'
|
||||
WHEN 'the_geom_webmercator' THEN
|
||||
'ST_SetSRID(ST_MakePoint(_sum_of_x/n, _sum_of_y/n), 3857) AS the_geom_webmercator'
|
||||
ELSE c
|
||||
END AS column
|
||||
FROM CDB_ColumnNames(reloid) c
|
||||
)
|
||||
SELECT string_agg(s.column, ',') FROM (
|
||||
SELECT * FROM cols
|
||||
) AS s INTO columns;
|
||||
|
||||
IF NOT columns LIKE '%_feature_count%' THEN
|
||||
columns := columns || ', n AS _feature_count';
|
||||
END IF;
|
||||
|
||||
EXECUTE Format('DROP TABLE IF EXISTS %I.%I CASCADE;', schema_name, overview_rel);
|
||||
|
||||
-- Now we cluster the data using a grid of size grid_m
|
||||
-- and selecte the centroid (average coordinates) of each cluster.
|
||||
-- If we had a selected numeric attribute of interest we could use it
|
||||
-- as a weight for the average coordinates.
|
||||
EXECUTE Format('
|
||||
CREATE TABLE %7$I.%3$I AS
|
||||
WITH clusters AS (
|
||||
SELECT
|
||||
%5$s
|
||||
count(*) AS n,
|
||||
SUM(ST_X(f.the_geom_webmercator)) AS _sum_of_x,
|
||||
SUM(ST_Y(f.the_geom_webmercator)) AS _sum_of_y,
|
||||
Floor(ST_Y(f.the_geom_webmercator)/%2$s)::int AS gy,
|
||||
Floor(ST_X(f.the_geom_webmercator)/%2$s)::int AS gx,
|
||||
MIN(cartodb_id) AS cartodb_id
|
||||
FROM %1$s f
|
||||
GROUP BY gx, gy
|
||||
)
|
||||
SELECT %6$s FROM clusters
|
||||
', reloid::text, grid_m, overview_rel, attributes, aggr_attributes, columns, schema_name);
|
||||
|
||||
RETURN Format('%I.%I', schema_name, overview_rel)::regclass;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
-- This strategy places the aggregation of each cluster at the position of one of the cluster members.
|
||||
CREATE OR REPLACE FUNCTION _CDB_GridClusterSample_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER, grid_px FLOAT8 DEFAULT NULL)
|
||||
RETURNS REGCLASS
|
||||
AS $$
|
||||
DECLARE
|
||||
overview_rel TEXT;
|
||||
reduction FLOAT8;
|
||||
base_name TEXT;
|
||||
pixel_m FLOAT8;
|
||||
grid_m FLOAT8;
|
||||
offset_m FLOAT8;
|
||||
offset_x TEXT;
|
||||
offset_y TEXT;
|
||||
cell_x TEXT;
|
||||
cell_y TEXT;
|
||||
aggr_attributes TEXT;
|
||||
attributes TEXT;
|
||||
columns TEXT;
|
||||
gtypes TEXT[];
|
||||
schema_name TEXT;
|
||||
table_name TEXT;
|
||||
point_geom TEXT;
|
||||
BEGIN
|
||||
SELECT _CDB_GeometryTypes(reloid) INTO gtypes;
|
||||
IF gtypes IS NULL OR array_upper(gtypes, 1) <> 1 OR gtypes[1] <> 'ST_Point' THEN
|
||||
-- This strategy only supports datasets with point geomety
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
--TODO: check applicability: geometry type, minimum number of points...
|
||||
|
||||
overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z);
|
||||
|
||||
-- Grid size in pixels at Z level overview_z
|
||||
IF grid_px IS NULL THEN
|
||||
grid_px := 1.0;
|
||||
END IF;
|
||||
|
||||
SELECT * FROM _cdb_split_table_name(reloid) INTO schema_name, table_name;
|
||||
|
||||
-- pixel_m: size of a pixel in webmercator units (meters)
|
||||
SELECT CDB_XYZ_Resolution(overview_z) INTO pixel_m;
|
||||
-- grid size in meters
|
||||
grid_m = grid_px * pixel_m;
|
||||
|
||||
attributes := _CDB_Aggregable_Attributes_Expression(reloid);
|
||||
aggr_attributes := _CDB_Aggregated_Attributes_Expression(reloid);
|
||||
IF attributes <> '' THEN
|
||||
attributes := ', ' || attributes;
|
||||
END IF;
|
||||
IF aggr_attributes <> '' THEN
|
||||
aggr_attributes := aggr_attributes || ', ';
|
||||
END IF;
|
||||
|
||||
-- Center of each cell:
|
||||
cell_x := Format('gx*%1$s + %2$s', grid_m, grid_m/2);
|
||||
cell_y := Format('gy*%1$s + %2$s', grid_m, grid_m/2);
|
||||
|
||||
-- Displacement to the nearest pixel center:
|
||||
IF MOD(grid_px::numeric, 1.0::numeric) = 0 THEN
|
||||
offset_m := pixel_m/2 - MOD((grid_m/2)::numeric, pixel_m::numeric)::float8;
|
||||
offset_x := Format('%s', offset_m);
|
||||
offset_y := Format('%s', offset_m);
|
||||
ELSE
|
||||
offset_x := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_x, pixel_m);
|
||||
offset_y := Format('%2$s/2 - MOD((%1$s)::numeric, (%2$s)::numeric)::float8', cell_y, pixel_m);
|
||||
END IF;
|
||||
|
||||
point_geom := Format('ST_SetSRID(ST_MakePoint(%1$s + %3$s, %2$s + %4$s), 3857)', cell_x, cell_y, offset_x, offset_y);
|
||||
|
||||
-- compute the resulting columns in the same order as in the base table
|
||||
WITH cols AS (
|
||||
SELECT
|
||||
CASE c
|
||||
WHEN 'cartodb_id' THEN 'cartodb_id'
|
||||
ELSE c
|
||||
END AS column
|
||||
FROM CDB_ColumnNames(reloid) c
|
||||
)
|
||||
SELECT string_agg(s.column, ',') FROM (
|
||||
SELECT * FROM cols
|
||||
) AS s INTO columns;
|
||||
|
||||
IF NOT columns LIKE '%_feature_count%' THEN
|
||||
columns := columns || ', n AS _feature_count';
|
||||
END IF;
|
||||
|
||||
EXECUTE Format('DROP TABLE IF EXISTS %I.%I CASCADE;', schema_name, overview_rel);
|
||||
|
||||
-- Now we cluster the data using a grid of size grid_m
|
||||
-- and select the centroid (average coordinates) of each cluster.
|
||||
-- If we had a selected numeric attribute of interest we could use it
|
||||
-- as a weight for the average coordinates.
|
||||
EXECUTE Format('
|
||||
CREATE TABLE %7$I.%3$I AS
|
||||
WITH clusters AS (
|
||||
SELECT
|
||||
%5$s
|
||||
count(*) AS n,
|
||||
Floor(ST_X(_f.the_geom_webmercator)/%2$s)::int AS gx,
|
||||
Floor(ST_Y(_f.the_geom_webmercator)/%2$s)::int AS gy,
|
||||
MIN(cartodb_id) AS cartodb_id
|
||||
FROM %1$s _f
|
||||
GROUP BY gx, gy
|
||||
),
|
||||
cluster_geom AS (
|
||||
SELECT the_geom, the_geom_webmercator, clusters.*
|
||||
FROM clusters INNER JOIN %1$s _g ON (clusters.cartodb_id = _g.cartodb_id)
|
||||
)
|
||||
SELECT %6$s FROM cluster_geom
|
||||
', reloid::text, grid_m, overview_rel, attributes, aggr_attributes, columns, schema_name);
|
||||
|
||||
RETURN Format('%I.%I', schema_name, overview_rel)::regclass;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
-- Create overview tables for a dataset.
|
||||
-- Scope: public
|
||||
-- Parameters:
|
||||
|
||||
@@ -41,7 +41,7 @@ AS $$
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind = 'r'
|
||||
AND c.relname NOT IN ('cdb_tablemetadata', 'spatial_ref_sys')
|
||||
AND c.relname NOT IN ('cdb_tablemetadata', 'cdb_analysis_catalog', 'cdb_conf', 'spatial_ref_sys')
|
||||
AND CASE WHEN schema_name IS NULL
|
||||
THEN n.nspname NOT IN ('pg_catalog', 'information_schema', 'topology', 'cartodb')
|
||||
ELSE n.nspname = schema_name
|
||||
|
||||
@@ -26,19 +26,14 @@ BEGIN
|
||||
WHERE o_table_schema = schema_name AND o_table_catalog = current_database()
|
||||
),
|
||||
user_tables AS (
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_catalog = current_database() AND table_schema = schema_name
|
||||
AND table_name != 'spatial_ref_sys'
|
||||
AND table_name != 'cdb_tablemetadata'
|
||||
AND table_type = 'BASE TABLE'
|
||||
SELECT table_name FROM _CDB_NonAnalysisTablesInSchema(schema_name)
|
||||
),
|
||||
table_cat AS (
|
||||
SELECT
|
||||
table_name,
|
||||
(
|
||||
EXISTS(select * from raster_tables where o_table_name = table_name)
|
||||
OR
|
||||
table_name SIMILAR TO _CDB_OverviewTableDiscriminator() || '[\w\d]*'
|
||||
OR table_name SIMILAR TO _CDB_OverviewTableDiscriminator() || '[\w\d]*'
|
||||
) AS is_overview,
|
||||
EXISTS(SELECT * FROM raster_tables WHERE r_table_name = table_name) AS is_raster
|
||||
FROM user_tables
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
-- @param in_array A numeric array of numbers
|
||||
--
|
||||
-- Returns: statistical quantity chosen
|
||||
--
|
||||
--
|
||||
-- References: http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
|
||||
--
|
||||
|
||||
@@ -13,17 +13,21 @@ CREATE OR REPLACE FUNCTION CDB_Kurtosis ( in_array NUMERIC[] ) RETURNS NUMERIC a
|
||||
DECLARE
|
||||
a numeric;
|
||||
c numeric;
|
||||
s numeric;
|
||||
k numeric;
|
||||
BEGIN
|
||||
SELECT AVG(e), COUNT(e)::numeric, stddev(e) INTO a, c, s FROM ( SELECT unnest(in_array) e ) x;
|
||||
SELECT AVG(e), COUNT(e)::numeric * power(stddev(e),4) INTO a, c FROM ( SELECT unnest(in_array) e ) x;
|
||||
|
||||
EXECUTE 'SELECT sum(power($1 - e, 4)) / ( $2 * power($3, 4)) - 3
|
||||
FROM (SELECT unnest($4) e ) x'
|
||||
INTO k
|
||||
USING a, c, s, in_array;
|
||||
IF c=0 THEN
|
||||
RETURN 0;
|
||||
ELSE
|
||||
|
||||
RETURN k;
|
||||
EXECUTE 'SELECT sum(power($1 - e, 4)) / ($2 ) - 3
|
||||
FROM (SELECT unnest($3) e ) x'
|
||||
INTO k
|
||||
USING a, c, in_array;
|
||||
|
||||
RETURN k;
|
||||
END IF;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
|
||||
@@ -32,16 +36,18 @@ CREATE OR REPLACE FUNCTION CDB_Skewness ( in_array NUMERIC[] ) RETURNS NUMERIC a
|
||||
DECLARE
|
||||
a numeric;
|
||||
c numeric;
|
||||
s numeric;
|
||||
sk numeric;
|
||||
BEGIN
|
||||
SELECT AVG(e), COUNT(e)::numeric, stddev(e) INTO a, c, s FROM ( SELECT unnest(in_array) e ) x;
|
||||
SELECT AVG(e), COUNT(e)::numeric * power(stddev(e),3) INTO a, c FROM ( SELECT unnest(in_array) e ) x;
|
||||
IF c=0 THEN
|
||||
RETURN 0;
|
||||
ELSE
|
||||
EXECUTE 'SELECT sum(power($1 - e, 3)) / ( $2 )
|
||||
FROM (SELECT unnest($3) e ) x'
|
||||
INTO sk
|
||||
USING a, c, in_array;
|
||||
|
||||
EXECUTE 'SELECT sum(power($1 - e, 3)) / ( $2 * power($3, 3))
|
||||
FROM (SELECT unnest($4) e ) x'
|
||||
INTO sk
|
||||
USING a, c, s, in_array;
|
||||
|
||||
RETURN sk;
|
||||
RETURN sk;
|
||||
END IF;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
|
||||
@@ -14,7 +14,7 @@ SELECT c.relname
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind = 'r'
|
||||
AND c.relname NOT IN ('cdb_tablemetadata', 'spatial_ref_sys')
|
||||
AND c.relname NOT IN ('cdb_tablemetadata', 'cdb_analysis_catalog', 'cdb_conf', 'spatial_ref_sys')
|
||||
AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'topology', 'cartodb')
|
||||
AND CASE WHEN perm = 'public' THEN has_table_privilege('publicuser', c.oid, 'SELECT')
|
||||
WHEN perm = 'private' THEN has_table_privilege(current_user, c.oid, 'SELECT') AND NOT has_table_privilege('publicuser', c.oid, 'SELECT')
|
||||
|
||||
@@ -2,4 +2,10 @@ WITH data AS (
|
||||
SELECT array_agg(x::numeric) s FROM generate_series(1,300) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT round(unnest(CDB_EqualIntervalBins(s, 7)),7) FROM data
|
||||
SELECT round(unnest(CDB_EqualIntervalBins(s, 7)),7) FROM data;
|
||||
|
||||
WITH data_nulls AS (
|
||||
SELECT array_agg(CASE WHEN x % 2 != 0 THEN x ELSE NULL END::numeric) s FROM generate_series(1,100) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT round(unnest(CDB_EqualIntervalBins(s, 7)),7) FROM data_nulls;
|
||||
|
||||
@@ -5,3 +5,10 @@
|
||||
213.8571429
|
||||
256.4285714
|
||||
299.0000000
|
||||
15.0000000
|
||||
29.0000000
|
||||
43.0000000
|
||||
57.0000000
|
||||
71.0000000
|
||||
85.0000000
|
||||
99.0000000
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
WITH data AS (
|
||||
SELECT array_agg(x) x FROM generate_series(1,100) x
|
||||
SELECT array_agg(x::numeric) s FROM generate_series(1,100) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT round(unnest(CDB_HeadsTailsBins(x, 7)),2) FROM data
|
||||
)
|
||||
SELECT round(unnest(CDB_HeadsTailsBins(s, 7)),2) FROM data;
|
||||
|
||||
WITH data_nulls AS (
|
||||
SELECT array_agg(CASE WHEN x % 2 != 0 THEN x ELSE NULL END::numeric) s FROM generate_series(1,100) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT round(unnest(CDB_HeadsTailsBins(s, 7)),2) FROM data_nulls;
|
||||
|
||||
@@ -5,3 +5,9 @@
|
||||
96.50
|
||||
98.00
|
||||
99.00
|
||||
49.76
|
||||
74.65
|
||||
88.50
|
||||
94.50
|
||||
98.00
|
||||
99.00
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
WITH data AS (
|
||||
SELECT array_agg(x) x FROM generate_series(1,100) x
|
||||
SELECT array_agg(x::numeric) s FROM generate_series(1,300) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT unnest(CDB_JenksBins(x, 7)) FROM data
|
||||
SELECT unnest(CDB_JenksBins(s, 7)) FROM data;
|
||||
|
||||
WITH data_nulls AS (
|
||||
SELECT array_agg(CASE WHEN x % 2 != 0 THEN x ELSE NULL END::numeric) s FROM generate_series(1,300) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT unnest(CDB_JenksBins(s, 7)) FROM data_nulls;
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
13
|
||||
29
|
||||
43
|
||||
57
|
||||
71
|
||||
83
|
||||
99
|
||||
86
|
||||
129
|
||||
172
|
||||
213
|
||||
257
|
||||
299
|
||||
37
|
||||
51
|
||||
97
|
||||
157
|
||||
213
|
||||
241
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
WITH data AS (
|
||||
SELECT array_agg(x) x FROM generate_series(1,100) x
|
||||
SELECT array_agg(x::numeric) s FROM generate_series(1,100) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT unnest(CDB_QuantileBins(x, 7)) FROM data
|
||||
SELECT unnest(CDB_QuantileBins(s, 7)) FROM data;
|
||||
|
||||
WITH data_nulls AS (
|
||||
SELECT array_agg(CASE WHEN x % 2 != 0 THEN x ELSE NULL END::numeric) s FROM generate_series(1,100) x
|
||||
WHERE x % 5 != 0 AND x % 7 != 0
|
||||
)
|
||||
SELECT unnest(CDB_QuantileBins(s, 7)) FROM data_nulls;
|
||||
|
||||
@@ -4,4 +4,11 @@
|
||||
57
|
||||
71
|
||||
86
|
||||
99
|
||||
29
|
||||
57
|
||||
87
|
||||
|
||||
|
||||
|
||||
99
|
||||
|
||||
@@ -27,5 +27,21 @@ INSERT INTO big VALUES (8193);
|
||||
SELECT CDB_SetUserQuotaInBytes(0);
|
||||
INSERT INTO big VALUES (8194);
|
||||
DROP TABLE big;
|
||||
|
||||
|
||||
--analysis tables should be excluded from quota:
|
||||
CREATE TABLE big(a int);
|
||||
CREATE TRIGGER test_quota BEFORE UPDATE OR INSERT ON big
|
||||
EXECUTE PROCEDURE CDB_CheckQuota(1, 1, 'public');
|
||||
SELECT CDB_SetUserQuotaInBytes(1);
|
||||
CREATE TABLE analysis_2f13a3dbd7_41bd92976fc6dd97072afe4ee450054f4c0715d4(id int);
|
||||
INSERT INTO analysis_2f13a3dbd7_41bd92976fc6dd97072afe4ee450054f4c0715d4(id) VALUES (1),(2),(3),(4),(5);
|
||||
INSERT INTO big VALUES (1); -- allowed, check runs before
|
||||
DROP TABLE analysis_2f13a3dbd7_41bd92976fc6dd97072afe4ee450054f4c0715d4;
|
||||
INSERT INTO big VALUES (2); -- disallowed, quota exceeds before
|
||||
DROP TABLE big;
|
||||
SELECT CDB_SetUserQuotaInBytes(0);
|
||||
|
||||
|
||||
set client_min_messages to NOTICE;
|
||||
DROP FUNCTION _CDB_UserQuotaInBytes();
|
||||
|
||||
@@ -18,5 +18,15 @@ ERROR: Quota exceeded by 443.998046875KB
|
||||
0
|
||||
INSERT 0 1
|
||||
DROP TABLE
|
||||
CREATE TABLE
|
||||
CREATE TRIGGER
|
||||
1
|
||||
CREATE TABLE
|
||||
INSERT 0 5
|
||||
INSERT 0 1
|
||||
DROP TABLE
|
||||
ERROR: Quota exceeded by 3.9990234375KB
|
||||
DROP TABLE
|
||||
0
|
||||
SET
|
||||
DROP FUNCTION
|
||||
|
||||
@@ -182,6 +182,7 @@ function setup_database() {
|
||||
log_info "########################### BOOTSTRAP ###########################"
|
||||
${CMD} -d ${DATABASE} -f scripts-available/CDB_Organizations.sql
|
||||
${CMD} -d ${DATABASE} -f scripts-available/CDB_OverviewsSupport.sql
|
||||
${CMD} -d ${DATABASE} -f scripts-available/CDB_AnalysisSupport.sql
|
||||
# trick to allow forcing a schema when loading SQL files (see: http://bit.ly/1HeLnhL)
|
||||
${CMD} -d ${DATABASE} -f test/extension/run_at_cartodb_schema.sql
|
||||
}
|
||||
@@ -227,6 +228,7 @@ function tear_down() {
|
||||
sql 'DROP ROLE cdb_testmember_2;'
|
||||
|
||||
tear_down_database
|
||||
DATABASE=postgres sql postgres 'DROP ROLE IF EXISTS publicuser';
|
||||
}
|
||||
|
||||
|
||||
@@ -485,6 +487,18 @@ function test_foreign_tables() {
|
||||
${CMD} -d fdw_target -f scripts-available/CDB_QueryTables.sql
|
||||
${CMD} -d fdw_target -f scripts-available/CDB_TableMetadata.sql
|
||||
|
||||
DATABASE=fdw_target sql postgres "DO
|
||||
\$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT *
|
||||
FROM pg_catalog.pg_user
|
||||
WHERE usename = 'publicuser') THEN
|
||||
|
||||
CREATE ROLE publicuser LOGIN;
|
||||
END IF;
|
||||
END
|
||||
\$\$;"
|
||||
DATABASE=fdw_target sql postgres 'CREATE SCHEMA test_fdw;'
|
||||
DATABASE=fdw_target sql postgres 'CREATE TABLE test_fdw.foo (a int);'
|
||||
DATABASE=fdw_target sql postgres 'INSERT INTO test_fdw.foo (a) values (42);'
|
||||
|
||||
Reference in New Issue
Block a user