Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e80ea92c57 | ||
|
|
61804187c8 | ||
|
|
9114d4e463 | ||
|
|
5db9dc6a9f | ||
|
|
0a3d08edc3 | ||
|
|
b913defebb | ||
|
|
978742f868 | ||
|
|
5080e3d985 | ||
|
|
cb61fd8747 | ||
|
|
ebcca141bd | ||
|
|
9d679614c8 | ||
|
|
bebebc255a | ||
|
|
11bf7f6fdf | ||
|
|
05617382a9 | ||
|
|
f16f53ceab | ||
|
|
27aec0d4b4 | ||
|
|
f18232037d | ||
|
|
da7b3b7080 | ||
|
|
38fe98d983 | ||
|
|
39e16ebc59 | ||
|
|
dbc0e069c5 | ||
|
|
6c7706672f | ||
|
|
d43e141291 | ||
|
|
0d5a1c3e49 | ||
|
|
519ea075d6 | ||
|
|
0223d00a54 | ||
|
|
3cf62ecd2e | ||
|
|
ee8a031ea0 | ||
|
|
f0bf8a85a5 | ||
|
|
693b147ef1 | ||
|
|
73232b8802 | ||
|
|
a4e42571cd | ||
|
|
bf622ae5a6 | ||
|
|
dbb6f42b99 | ||
|
|
626b883cfc | ||
|
|
cd9e44b266 | ||
|
|
fd9d79372f | ||
|
|
61b47617b8 | ||
|
|
3b5c1f65cb | ||
|
|
b7c2336ae0 | ||
|
|
6f80b52c92 | ||
|
|
dc6ac7f56b | ||
|
|
68e132ade5 | ||
|
|
c9ff282b17 | ||
|
|
f251e12d35 | ||
|
|
5a3b93fd6b | ||
|
|
eaee6d3d70 | ||
|
|
7840e7c50b | ||
|
|
5b0a7bf9ad | ||
|
|
2ef6d5901e | ||
|
|
3d37b3646e | ||
|
|
51d48c7629 | ||
|
|
25a0e5ec68 | ||
|
|
daa61a6aa8 | ||
|
|
723a08e814 | ||
|
|
41a2c7363e | ||
|
|
45d07bc5a8 | ||
|
|
55615e1a32 | ||
|
|
4b397d6bc0 |
@@ -19,7 +19,7 @@ in which those scripts are loaded.
|
||||
|
||||
Scripts would be best coded in a way to be usable both for creation
|
||||
and upgrade of the objects. This means using CREATE OR REPLACE for
|
||||
the functions, and whatever it takes to check existance of any previous
|
||||
the functions, and whatever it takes to check existence of any previous
|
||||
version of objects in other cases.
|
||||
|
||||
When used as an extension (probably always from version 0.2.0 onwards)
|
||||
@@ -27,8 +27,8 @@ all the objects will be installed in a "cartodb" schema. Take this into
|
||||
account to fully-qualify internal calls to avoid (possibly dangerous)
|
||||
name clashes.
|
||||
|
||||
Every new feature (as well as bugfixes) should come with a testcase,
|
||||
see next session.
|
||||
Every new feature (as well as bugfixes) should come with a test case,
|
||||
see next section.
|
||||
|
||||
Writing testcases
|
||||
-----------------
|
||||
@@ -58,4 +58,3 @@ Starting with 0.2.0, the in-place reload can be done with an ad-hoc function:
|
||||
```sql
|
||||
SELECT cartodb.cdb_extension_reload();
|
||||
```
|
||||
|
||||
25
Makefile
25
Makefile
@@ -1,7 +1,7 @@
|
||||
# cartodb/Makefile
|
||||
|
||||
EXTENSION = cartodb
|
||||
EXTVERSION = 0.3.5
|
||||
EXTVERSION = 0.7.2
|
||||
|
||||
SED = sed
|
||||
|
||||
@@ -25,6 +25,17 @@ UPGRADABLE = \
|
||||
0.3.2 \
|
||||
0.3.3 \
|
||||
0.3.4 \
|
||||
0.3.5 \
|
||||
0.3.6 \
|
||||
0.4.0 \
|
||||
0.4.1 \
|
||||
0.5.0 \
|
||||
0.5.1 \
|
||||
0.5.2 \
|
||||
0.5.3 \
|
||||
0.6.0 \
|
||||
0.7.0 \
|
||||
0.7.1 \
|
||||
$(EXTVERSION)dev \
|
||||
$(EXTVERSION)next \
|
||||
$(END)
|
||||
@@ -35,7 +46,6 @@ UPGRADES = \
|
||||
$(SED) 's/$$/--$(EXTVERSION).sql/' | \
|
||||
$(SED) 's/ /--$(EXTVERSION).sql $(EXTENSION)--/g')
|
||||
|
||||
REV=$(shell git describe)
|
||||
GITDIR=$(shell test -d .git && echo '.git' || cat .git | $(SED) 's/^gitdir: //')
|
||||
|
||||
DATA_built = \
|
||||
@@ -77,7 +87,7 @@ $(EXTENSION).control: $(EXTENSION).control.in Makefile
|
||||
$(SED) -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
|
||||
|
||||
cartodb_version.sql: cartodb_version.sql.in Makefile $(GITDIR)/index
|
||||
$(SED) -e 's/@@VERSION@@/$(EXTVERSION) $(REV)/' $< > $@
|
||||
$(SED) -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
|
||||
|
||||
legacy_regress: $(REGRESS_OLD) Makefile
|
||||
mkdir -p sql/test/
|
||||
@@ -86,21 +96,24 @@ legacy_regress: $(REGRESS_OLD) Makefile
|
||||
for f in $(REGRESS_OLD); do \
|
||||
tn=`basename $${f} .sql`; \
|
||||
of=sql/test/$${tn}.sql; \
|
||||
echo '\\set ECHO off' > $${of}; \
|
||||
echo '\\set ECHO none' > $${of}; \
|
||||
echo '\\a' >> $${of}; \
|
||||
echo '\\t' >> $${of}; \
|
||||
echo '\\set QUIET off' >> $${of}; \
|
||||
cat $${f} | \
|
||||
$(SED) -e 's/public\./cartodb./g' >> $${of}; \
|
||||
exp=expected/test/$${tn}.out; \
|
||||
echo '\\set ECHO off' > $${exp}; \
|
||||
echo '\\set ECHO none' > $${exp}; \
|
||||
cat test/$${tn}_expect >> $${exp}; \
|
||||
done
|
||||
|
||||
test_organization:
|
||||
bash test/organization/test.sh
|
||||
|
||||
test_extension_new:
|
||||
bash test/extension/test.sh
|
||||
|
||||
legacy_tests: legacy_regress
|
||||
|
||||
installcheck: legacy_tests test_organization
|
||||
installcheck: legacy_tests test_extension_new test_organization
|
||||
|
||||
|
||||
@@ -1,3 +1,52 @@
|
||||
0.7.2 (2015-03-03)
|
||||
------------------
|
||||
* Fix conversion of strings to datetime
|
||||
|
||||
0.7.1 (2015-02-27)
|
||||
------------------
|
||||
* Revert quota checks to `pg_total_relation_size`
|
||||
|
||||
0.7.0 (2015-02-19)
|
||||
------------------
|
||||
* Adds CDB_ZoomFromScale function
|
||||
|
||||
0.6.0 (2015-02-19)
|
||||
------------------
|
||||
* Select permission in CDB_TableMetadata no longer granted to public
|
||||
* New function to upsert the updated_at in CDB_TableMetadata for a regclass
|
||||
|
||||
0.5.3 (2015-02-17)
|
||||
------------------
|
||||
* Fixed security problem related with system tables
|
||||
* Changed quota checks to use `pg_relation_size` instead of `pg_total_relation_size`
|
||||
|
||||
0.5.2 (2015-01-29)
|
||||
------------------
|
||||
* Improvement: make CDB_UserDataSize functions much faster.
|
||||
|
||||
0.5.1 (2014-11-21)
|
||||
------------------
|
||||
* Bugfix: Quota check and some organization permissions functions were not properly escaping table name.
|
||||
|
||||
0.5.0 (2014-11-03)
|
||||
------------------
|
||||
* Support of raster tables for cartodbfication
|
||||
* Modified quota functions: vector tables stay the same, raster tables count as full size (as have no
|
||||
the_geom + the_geom_webmercator combo) and raster overviews are not counted
|
||||
|
||||
0.4.1 (2014-09-21)
|
||||
------------------
|
||||
* Bugfix for Cartodbfication: Set primary key of the table if not already present (e.g. tables created from SQL API)
|
||||
|
||||
0.4.0 (2014-08-27)
|
||||
------------------
|
||||
Added CDB_Math_Mode function
|
||||
Changes in versioning: no revision is attached so it no longer uses `git describe` for the version.
|
||||
|
||||
0.3.6 (2014-08-11)
|
||||
------------------
|
||||
Dummy release to solve some issues with cdb branch/tag
|
||||
|
||||
0.3.5 (2014-08-11)
|
||||
------------------
|
||||
Inverting priority of CDB_CheckQuota qmax so gies more priority to existing user quota function over parameter value.
|
||||
@@ -20,12 +20,16 @@ Dependencies
|
||||
Install
|
||||
-------
|
||||
|
||||
make all install
|
||||
```sh
|
||||
make all install
|
||||
```
|
||||
|
||||
Test installation
|
||||
-----------------
|
||||
|
||||
make installcheck
|
||||
```sh
|
||||
make installcheck
|
||||
```
|
||||
|
||||
NOTE: if ``test_ddl_triggers`` fails it's likely due to an incomplete
|
||||
installation of schema_triggers: you need to add ``schema_triggers.so``
|
||||
|
||||
@@ -19,6 +19,12 @@ NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
|
||||
(1 row)
|
||||
|
||||
create schema c;
|
||||
SELECT CDB_SetUserQuotaInBytes('c', 0);
|
||||
cdb_setuserquotainbytes
|
||||
-------------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
CREATE USER cartodb_postgresql_unpriv_user;
|
||||
GRANT ALL ON SCHEMA c to cartodb_postgresql_unpriv_user;
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
@@ -26,6 +32,7 @@ SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
----------------------
|
||||
-- CREATE TABLE
|
||||
----------------------
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select 1 as i INTO c.t3;
|
||||
NOTICE: trigger "track_updates" for table "c.t3" does not exist, skipping
|
||||
NOTICE: trigger "update_the_geom_webmercator_trigger" for table "c.t3" does not exist, skipping
|
||||
@@ -49,6 +56,7 @@ from c.t3;
|
||||
1 | t | t | | | 1
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)) as age
|
||||
@@ -58,6 +66,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
c.t3 | 0
|
||||
(1 row)
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
-- Table with cartodb_id field, see
|
||||
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
|
||||
select 1 as cartodb_id INTO c.t4;
|
||||
@@ -85,6 +94,7 @@ from c.t4;
|
||||
1 | t | t | |
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)) as age
|
||||
@@ -97,6 +107,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t4'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE RENAME COLUMN
|
||||
----------------------------
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
pg_sleep
|
||||
----------
|
||||
@@ -125,6 +136,7 @@ from c.t3;
|
||||
1 | t | t | | | 1 |
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -134,6 +146,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
c.t3 | 0
|
||||
(1 row)
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
pg_sleep
|
||||
----------
|
||||
@@ -162,6 +175,7 @@ from c.t3;
|
||||
1 | t | t | | | 1 | |
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -174,6 +188,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE DROP COLUMN
|
||||
----------------------------
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
pg_sleep
|
||||
----------
|
||||
@@ -202,6 +217,7 @@ from c.t3;
|
||||
1 | t | t | | | 1 | |
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -214,6 +230,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE ADD COLUMN
|
||||
----------------------------
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
pg_sleep
|
||||
----------
|
||||
@@ -233,6 +250,7 @@ from c.t3;
|
||||
1 | t | t | | | 1 | | |
|
||||
(1 row)
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -247,7 +265,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
----------------------------
|
||||
RESET SESSION AUTHORIZATION;
|
||||
drop schema c cascade;
|
||||
NOTICE: drop cascades to 2 other objects
|
||||
NOTICE: drop cascades to 3 other objects
|
||||
select count(*) from CDB_TableMetadata;
|
||||
count
|
||||
-------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
-- Depends on:
|
||||
-- * CDB_ExtensionUtils.sql
|
||||
-- * CDB_TransformToWebmercator.sql
|
||||
-- * CDB_TableMetadata.sql
|
||||
-- * CDB_Quota.sql
|
||||
-- * _CDB_UserQuotaInBytes() function, installed by rails
|
||||
-- (user.rebuild_quota_trigger, called by rake task
|
||||
-- cartodb:db:update_test_quota_trigger)
|
||||
-- (user.rebuild_quota_trigger, called by rake task cartodb:db:update_test_quota_trigger)
|
||||
|
||||
-- 1) Required checks before running cartodbfication
|
||||
-- Either will pass silenty or raise an exception
|
||||
@@ -22,7 +22,7 @@ BEGIN
|
||||
BEGIN
|
||||
EXECUTE FORMAT('SELECT %I._CDB_UserQuotaInBytes();', schema_name::text) INTO sql;
|
||||
EXCEPTION WHEN undefined_function THEN
|
||||
RAISE EXCEPTION 'Please set user quota before cartodbfying tables.';
|
||||
RAISE EXCEPTION 'Please set user quota before cartodbfying tables.';
|
||||
END;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
@@ -67,6 +67,7 @@ DECLARE
|
||||
had_column BOOLEAN;
|
||||
i INTEGER;
|
||||
new_name TEXT;
|
||||
cartodb_id_name TEXT;
|
||||
BEGIN
|
||||
<< cartodb_id_setup >>
|
||||
LOOP --{
|
||||
@@ -75,6 +76,7 @@ BEGIN
|
||||
sql := 'ALTER TABLE ' || reloid::text || ' ADD cartodb_id SERIAL NOT NULL UNIQUE';
|
||||
RAISE DEBUG 'Running %', sql;
|
||||
EXECUTE sql;
|
||||
cartodb_id_name := 'cartodb_id';
|
||||
EXIT cartodb_id_setup;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN
|
||||
@@ -114,6 +116,7 @@ BEGIN
|
||||
BEGIN
|
||||
RAISE DEBUG 'Running %', sql;
|
||||
EXECUTE sql;
|
||||
cartodb_id_name := 'cartodb_id';
|
||||
EXIT cartodb_id_setup;
|
||||
EXCEPTION
|
||||
WHEN unique_violation OR not_null_violation THEN
|
||||
@@ -139,13 +142,14 @@ BEGIN
|
||||
WHEN others THEN
|
||||
RAISE EXCEPTION 'Cartodbfying % (renaming cartodb_id): % (%)', reloid, SQLERRM, SQLSTATE;
|
||||
END;
|
||||
cartodb_id_name := new_name;
|
||||
EXIT rename_column;
|
||||
END LOOP; --}
|
||||
CONTINUE cartodb_id_setup;
|
||||
END IF;
|
||||
END LOOP; -- }
|
||||
|
||||
-- Try to copy data from new name if possible
|
||||
-- Try to copy data from new name if possible
|
||||
IF new_name IS NOT NULL THEN
|
||||
RAISE NOTICE 'Trying to recover data from % column', new_name;
|
||||
BEGIN
|
||||
@@ -185,6 +189,18 @@ BEGIN
|
||||
END;
|
||||
END IF;
|
||||
|
||||
-- Set primary key of the table if not already present (e.g. tables created from SQL API)
|
||||
IF cartodb_id_name IS NULL THEN
|
||||
RAISE EXCEPTION 'Cartodbfying % (Didnt get cartodb_id field name)', reloid;
|
||||
END IF;
|
||||
BEGIN
|
||||
sql := 'ALTER TABLE ' || reloid::text || ' ADD PRIMARY KEY (cartodb_id)';
|
||||
EXECUTE sql;
|
||||
EXCEPTION
|
||||
WHEN others THEN
|
||||
RAISE DEBUG 'Table % Already had PRIMARY KEY', reloid;
|
||||
END;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
@@ -450,7 +466,7 @@ END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
|
||||
-- 8) Create all triggers
|
||||
-- 8.a) Create all triggers
|
||||
-- NOTE: drop/create has the side-effect of re-enabling disabled triggers
|
||||
CREATE OR REPLACE FUNCTION _CDB_create_triggers(schema_name TEXT, reloid REGCLASS)
|
||||
RETURNS void
|
||||
@@ -496,6 +512,46 @@ BEGIN
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
-- 8.b) Create all raster triggers
|
||||
-- NOTE: drop/create has the side-effect of re-enabling disabled triggers
|
||||
CREATE OR REPLACE FUNCTION _CDB_create_raster_triggers(schema_name TEXT, reloid REGCLASS)
|
||||
RETURNS void
|
||||
AS $$
|
||||
DECLARE
|
||||
sql TEXT;
|
||||
BEGIN
|
||||
-- "track_updates"
|
||||
sql := 'CREATE trigger track_updates AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON '
|
||||
|| reloid::text
|
||||
|| ' FOR EACH STATEMENT EXECUTE PROCEDURE public.cdb_tablemetadata_trigger()';
|
||||
EXECUTE sql;
|
||||
|
||||
-- "update_updated_at"
|
||||
-- TODO: why _before_ and not after ?
|
||||
sql := 'CREATE trigger update_updated_at_trigger BEFORE UPDATE ON '
|
||||
|| reloid::text
|
||||
|| ' FOR EACH ROW EXECUTE PROCEDURE public._CDB_update_updated_at()';
|
||||
EXECUTE sql;
|
||||
|
||||
-- "test_quota" and "test_quota_per_row"
|
||||
|
||||
sql := 'CREATE TRIGGER test_quota BEFORE UPDATE OR INSERT ON '
|
||||
|| reloid::text
|
||||
|| ' EXECUTE PROCEDURE public.CDB_CheckQuota(1, ''-1'', '''
|
||||
|| schema_name::text
|
||||
|| ''')';
|
||||
EXECUTE sql;
|
||||
|
||||
sql := 'CREATE TRIGGER test_quota_per_row BEFORE UPDATE OR INSERT ON '
|
||||
|| reloid::text
|
||||
|| ' FOR EACH ROW EXECUTE PROCEDURE public.CDB_CheckQuota(0.001, ''-1'', '''
|
||||
|| schema_name::text
|
||||
|| ''')';
|
||||
EXECUTE sql;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
|
||||
|
||||
-- Update the_geom_webmercator
|
||||
CREATE OR REPLACE FUNCTION _CDB_update_the_geom_webmercator()
|
||||
@@ -516,15 +572,50 @@ END;
|
||||
$$ LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
|
||||
-- Auxiliary function
|
||||
CREATE OR REPLACE FUNCTION cartodb._CDB_is_raster_table(schema_name TEXT, reloid REGCLASS)
|
||||
RETURNS BOOLEAN
|
||||
AS $$
|
||||
DECLARE
|
||||
sql TEXT;
|
||||
is_raster BOOLEAN;
|
||||
rel_name TEXT;
|
||||
BEGIN
|
||||
IF cartodb.schema_exists(schema_name) = FALSE THEN
|
||||
RAISE EXCEPTION 'Invalid schema name "%"', schema_name;
|
||||
END IF;
|
||||
|
||||
SELECT relname FROM pg_class WHERE oid=reloid INTO rel_name;
|
||||
|
||||
BEGIN
|
||||
sql := 'SELECT the_raster_webmercator FROM '
|
||||
|| quote_ident(schema_name::TEXT)
|
||||
|| '.'
|
||||
|| quote_ident(rel_name::TEXT)
|
||||
|| ' LIMIT 1';
|
||||
is_raster = TRUE;
|
||||
EXECUTE sql;
|
||||
|
||||
EXCEPTION WHEN undefined_column THEN
|
||||
is_raster = FALSE;
|
||||
END;
|
||||
|
||||
RETURN is_raster;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
|
||||
|
||||
-- ////////////////////////////////////////////////////
|
||||
|
||||
-- Ensure a table is a "cartodb" table
|
||||
-- See https://github.com/CartoDB/cartodb/wiki/CartoDB-user-table
|
||||
-- Ensure a table is a "cartodb" table (See https://github.com/CartoDB/cartodb/wiki/CartoDB-user-table)
|
||||
-- Rails code replicates this call at User.cartodbfy()
|
||||
CREATE OR REPLACE FUNCTION CDB_CartodbfyTable(schema_name TEXT, reloid REGCLASS)
|
||||
RETURNS void
|
||||
AS $$
|
||||
DECLARE
|
||||
exists_geom_cols BOOLEAN[];
|
||||
is_raster BOOLEAN;
|
||||
BEGIN
|
||||
|
||||
PERFORM cartodb._CDB_check_prerequisites(schema_name, reloid);
|
||||
@@ -534,13 +625,19 @@ BEGIN
|
||||
-- Ensure required fields exist
|
||||
PERFORM cartodb._CDB_create_cartodb_id_column(reloid);
|
||||
PERFORM cartodb._CDB_create_timestamp_columns(reloid);
|
||||
SELECT cartodb._CDB_create_the_geom_columns(reloid) INTO exists_geom_cols;
|
||||
|
||||
-- Both only populate if proceeds
|
||||
PERFORM cartodb._CDB_populate_the_geom_from_the_geom_webmercator(reloid, exists_geom_cols);
|
||||
PERFORM cartodb._CDB_populate_the_geom_webmercator_from_the_geom(reloid, exists_geom_cols);
|
||||
SELECT cartodb._CDB_is_raster_table(schema_name, reloid) INTO is_raster;
|
||||
IF is_raster THEN
|
||||
PERFORM cartodb._CDB_create_raster_triggers(schema_name, reloid);
|
||||
ELSE
|
||||
SELECT cartodb._CDB_create_the_geom_columns(reloid) INTO exists_geom_cols;
|
||||
|
||||
PERFORM cartodb._CDB_create_triggers(schema_name, reloid);
|
||||
-- Both only populate if proceeds
|
||||
PERFORM cartodb._CDB_populate_the_geom_from_the_geom_webmercator(reloid, exists_geom_cols);
|
||||
PERFORM cartodb._CDB_populate_the_geom_webmercator_from_the_geom(reloid, exists_geom_cols);
|
||||
|
||||
PERFORM cartodb._CDB_create_triggers(schema_name, reloid);
|
||||
END IF;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
|
||||
@@ -4,14 +4,17 @@ CREATE OR REPLACE FUNCTION cartodb.cdb_handle_create_table ()
|
||||
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
event_info RECORD;
|
||||
rel_namespace TEXT;
|
||||
BEGIN
|
||||
event_info := schema_triggers.get_relation_create_eventinfo();
|
||||
|
||||
-- We're only interested in real relations
|
||||
IF (event_info.new).relkind != 'r' THEN RETURN; END IF;
|
||||
|
||||
RAISE DEBUG 'Relation % of kind % created in namespace oid %',
|
||||
event_info.relation, (event_info.new).relkind, (event_info.new).relnamespace;
|
||||
SELECT nspname FROM pg_namespace WHERE oid=(event_info.new).relnamespace INTO rel_namespace;
|
||||
|
||||
RAISE DEBUG 'Relation % of kind % created in table % namespace % (oid %)',
|
||||
event_info.relation, (event_info.new).relkind, (event_info.new).relname::TEXT, rel_namespace, (event_info.new).relnamespace;
|
||||
|
||||
-- We don't want to react to alters triggered by superuser,
|
||||
IF current_setting('is_superuser') = 'on' THEN
|
||||
@@ -22,7 +25,7 @@ BEGIN
|
||||
PERFORM cartodb.cdb_disable_ddl_hooks();
|
||||
|
||||
-- CDB_CartodbfyTable must not create tables, or infinite loop will happen
|
||||
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
|
||||
PERFORM cartodb.CDB_CartodbfyTable(rel_namespace, event_info.relation);
|
||||
|
||||
PERFORM cartodb.cdb_enable_ddl_hooks();
|
||||
|
||||
@@ -63,6 +66,7 @@ RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
event_info RECORD;
|
||||
rel RECORD;
|
||||
rel_namespace TEXT;
|
||||
BEGIN
|
||||
event_info := schema_triggers.get_column_alter_eventinfo();
|
||||
|
||||
@@ -80,9 +84,11 @@ BEGIN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
SELECT nspname FROM pg_namespace WHERE oid = rel.relnamespace INTO rel_namespace;
|
||||
|
||||
PERFORM cartodb.cdb_disable_ddl_hooks();
|
||||
|
||||
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
|
||||
PERFORM cartodb.CDB_CartodbfyTable(rel_namespace, event_info.relation);
|
||||
|
||||
PERFORM cartodb.cdb_enable_ddl_hooks();
|
||||
|
||||
@@ -100,6 +106,7 @@ RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
event_info RECORD;
|
||||
rel RECORD;
|
||||
rel_namespace TEXT;
|
||||
BEGIN
|
||||
event_info := schema_triggers.get_column_drop_eventinfo();
|
||||
|
||||
@@ -117,9 +124,11 @@ BEGIN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
SELECT nspname FROM pg_namespace WHERE oid = rel.relnamespace INTO rel_namespace;
|
||||
|
||||
PERFORM cartodb.cdb_disable_ddl_hooks();
|
||||
|
||||
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
|
||||
PERFORM cartodb.CDB_CartodbfyTable(rel_namespace, event_info.relation);
|
||||
|
||||
PERFORM cartodb.cdb_enable_ddl_hooks();
|
||||
|
||||
|
||||
26
scripts-available/CDB_Math.sql
Normal file
26
scripts-available/CDB_Math.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- CartoDB Math SQL functions
|
||||
|
||||
|
||||
-- Mode
|
||||
-- https://wiki.postgresql.org/wiki/Aggregate_Mode
|
||||
|
||||
CREATE OR REPLACE FUNCTION cartodb._CDB_Math_final_mode(anyarray)
|
||||
RETURNS anyelement AS
|
||||
$BODY$
|
||||
SELECT a
|
||||
FROM unnest($1) a
|
||||
GROUP BY 1
|
||||
ORDER BY COUNT(1) DESC, 1
|
||||
LIMIT 1;
|
||||
$BODY$
|
||||
LANGUAGE 'sql' IMMUTABLE;
|
||||
|
||||
DROP AGGREGATE IF EXISTS cartodb.CDB_Math_Mode(anyelement);
|
||||
|
||||
CREATE AGGREGATE cartodb.CDB_Math_Mode(anyelement) (
|
||||
SFUNC=array_append,
|
||||
STYPE=anyarray,
|
||||
FINALFUNC=_CDB_Math_final_mode,
|
||||
INITCOND='{}'
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@ FUNCTION cartodb.CDB_Organization_Add_Table_Read_Permission(from_schema text, ta
|
||||
AS $$
|
||||
BEGIN
|
||||
EXECUTE 'GRANT USAGE ON SCHEMA "' || from_schema || '" TO "' || to_role_name || '"';
|
||||
EXECUTE 'GRANT SELECT ON "' || from_schema || '".' || table_name || ' TO "' || to_role_name || '"';
|
||||
EXECUTE 'GRANT SELECT ON "' || from_schema || '"."' || table_name || '" TO "' || to_role_name || '"';
|
||||
END
|
||||
$$ LANGUAGE PLPGSQL VOLATILE;
|
||||
|
||||
@@ -54,7 +54,7 @@ FUNCTION cartodb.CDB_Organization_Add_Table_Read_Write_Permission(from_schema te
|
||||
AS $$
|
||||
BEGIN
|
||||
EXECUTE 'GRANT USAGE ON SCHEMA "' || from_schema || '" TO "' || to_role_name || '"';
|
||||
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON "' || from_schema || '".' || table_name || ' TO "' || to_role_name || '"';
|
||||
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON "' || from_schema || '"."' || table_name || '" TO "' || to_role_name || '"';
|
||||
END
|
||||
$$ LANGUAGE PLPGSQL VOLATILE;
|
||||
|
||||
@@ -73,7 +73,7 @@ FUNCTION cartodb.CDB_Organization_Remove_Access_Permission(from_schema text, tab
|
||||
RETURNS void
|
||||
AS $$
|
||||
BEGIN
|
||||
EXECUTE 'REVOKE ALL PRIVILEGES ON TABLE "' || from_schema || '".' || table_name || ' FROM "' || to_role_name || '"';
|
||||
EXECUTE 'REVOKE ALL PRIVILEGES ON TABLE "' || from_schema || '"."' || table_name || '" FROM "' || to_role_name || '"';
|
||||
-- EXECUTE 'REVOKE USAGE ON SCHEMA ' || from_schema || ' FROM "' || to_role_name || '"';
|
||||
-- We need to revoke usage on schema only if we are revoking privileges from the last table where to_role_name has
|
||||
-- any permission granted within the schema from_schema
|
||||
|
||||
@@ -16,9 +16,9 @@ BEGIN
|
||||
|
||||
FOR rec IN SELECT CDB_QueryStatements(query) q LOOP
|
||||
|
||||
IF NOT ( rec.q ilike 'select %' or rec.q ilike 'with %' ) THEN
|
||||
--RAISE WARNING 'Skipping %', rec.q;
|
||||
CONTINUE;
|
||||
IF NOT ( rec.q ilike 'select%' or rec.q ilike 'with%' ) THEN
|
||||
--RAISE WARNING 'Skipping %', rec.q;
|
||||
CONTINUE;
|
||||
END IF;
|
||||
|
||||
BEGIN
|
||||
|
||||
@@ -2,20 +2,45 @@
|
||||
CREATE OR REPLACE FUNCTION CDB_UserDataSize(schema_name TEXT)
|
||||
RETURNS bigint AS
|
||||
$$
|
||||
-- TODO: double check this query. Maybe use CDB_TableMetadata for lookup ?
|
||||
-- also, it's "table_name" sounds sensible to search_path
|
||||
--
|
||||
-- NOTE: division by 2 is an hack for the_geom_webmercator
|
||||
--
|
||||
SELECT coalesce(int8(sum(pg_total_relation_size(schema_name || '.' || table_name)) / 2), 0)
|
||||
AS quota
|
||||
FROM information_schema.tables
|
||||
WHERE table_catalog = current_database() AND table_schema = schema_name
|
||||
DECLARE
|
||||
total_size INT8;
|
||||
BEGIN
|
||||
WITH raster_tables AS (
|
||||
SELECT o_table_name, r_table_name FROM raster_overviews
|
||||
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';
|
||||
AND table_type = 'BASE TABLE'
|
||||
),
|
||||
table_cat AS (
|
||||
SELECT
|
||||
table_name,
|
||||
EXISTS(select * from raster_tables where o_table_name = table_name) AS is_overview,
|
||||
EXISTS(SELECT * FROM raster_tables WHERE r_table_name = table_name) AS is_raster
|
||||
FROM user_tables
|
||||
),
|
||||
sizes AS (
|
||||
SELECT COALESCE(INT8(SUM(pg_total_relation_size('"' || schema_name || '"."' || table_name || '"')))) table_size,
|
||||
CASE
|
||||
WHEN is_overview THEN 0
|
||||
WHEN is_raster THEN 1
|
||||
ELSE 0.5 -- Division by 2 is for not counting the_geom_webmercator
|
||||
END AS multiplier FROM table_cat GROUP BY is_overview, is_raster
|
||||
)
|
||||
SELECT sum(table_size*multiplier)::int8 INTO total_size FROM sizes;
|
||||
|
||||
IF total_size IS NOT NULL THEN
|
||||
RETURN total_size;
|
||||
ELSE
|
||||
RETURN 0;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE 'sql' VOLATILE;
|
||||
LANGUAGE 'plpgsql' VOLATILE;
|
||||
|
||||
|
||||
-- Return the estimated size of user data. Used for quota checking.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- Convert string to date
|
||||
--
|
||||
CREATE OR REPLACE FUNCTION CDB_StringToDate(input character varying)
|
||||
RETURNS date AS $$
|
||||
DECLARE output DATE;
|
||||
RETURNS TIMESTAMP AS $$
|
||||
DECLARE output TIMESTAMP;
|
||||
BEGIN
|
||||
BEGIN
|
||||
output := input::date;
|
||||
|
||||
@@ -5,9 +5,9 @@ CREATE TABLE IF NOT EXISTS
|
||||
updated_at timestamp with time zone not null default now()
|
||||
);
|
||||
|
||||
-- Anyone can see this, but updates are only possible trough
|
||||
-- the security definer trigger
|
||||
GRANT SELECT ON public.CDB_TableMetadata TO public;
|
||||
-- No one can see this
|
||||
-- Updates are only possible trough the security definer trigger
|
||||
-- GRANT SELECT ON public.CDB_TableMetadata TO public;
|
||||
|
||||
--
|
||||
-- Trigger logging updated_at in the CDB_TableMetadata
|
||||
@@ -118,3 +118,21 @@ CREATE TRIGGER table_modified AFTER INSERT OR UPDATE
|
||||
ON CDB_TableMetadata FOR EACH ROW EXECUTE PROCEDURE
|
||||
_CDB_TableMetadata_Updated();
|
||||
|
||||
|
||||
-- similar to TOUCH(1) in unix filesystems but for table in cdb_tablemetadata
|
||||
CREATE OR REPLACE FUNCTION public.CDB_TableMetadataTouch(tablename regclass)
|
||||
RETURNS void AS
|
||||
$$
|
||||
BEGIN
|
||||
WITH upsert AS (
|
||||
UPDATE public.cdb_tablemetadata
|
||||
SET updated_at = NOW()
|
||||
WHERE tabname = tablename
|
||||
RETURNING *
|
||||
)
|
||||
INSERT INTO public.cdb_tablemetadata (tabname, updated_at)
|
||||
SELECT tablename, NOW()
|
||||
WHERE NOT EXISTS (SELECT * FROM upsert);
|
||||
END;
|
||||
$$
|
||||
LANGUAGE 'plpgsql' VOLATILE STRICT;
|
||||
|
||||
31
scripts-available/CDB_ZoomFromScale.sql
Normal file
31
scripts-available/CDB_ZoomFromScale.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
CREATE OR REPLACE FUNCTION cartodb.CDB_ZoomFromScale(scaleDenominator numeric) RETURNS int AS $$
|
||||
BEGIN
|
||||
CASE
|
||||
WHEN scaleDenominator > 1000000000 THEN RETURN 0;
|
||||
WHEN scaleDenominator <= 1000000000 AND scaleDenominator > 500000000 THEN RETURN 1;
|
||||
WHEN scaleDenominator <= 500000000 AND scaleDenominator > 200000000 THEN RETURN 2;
|
||||
WHEN scaleDenominator <= 200000000 AND scaleDenominator > 100000000 THEN RETURN 3;
|
||||
WHEN scaleDenominator <= 100000000 AND scaleDenominator > 50000000 THEN RETURN 3;
|
||||
WHEN scaleDenominator <= 50000000 AND scaleDenominator > 25000000 THEN RETURN 4;
|
||||
WHEN scaleDenominator <= 25000000 AND scaleDenominator > 12500000 THEN RETURN 5;
|
||||
WHEN scaleDenominator <= 12500000 AND scaleDenominator > 6500000 THEN RETURN 6;
|
||||
WHEN scaleDenominator <= 6500000 AND scaleDenominator > 3000000 THEN RETURN 7;
|
||||
WHEN scaleDenominator <= 3000000 AND scaleDenominator > 1500000 THEN RETURN 8;
|
||||
WHEN scaleDenominator <= 1500000 AND scaleDenominator > 750000 THEN RETURN 9;
|
||||
WHEN scaleDenominator <= 750000 AND scaleDenominator > 400000 THEN RETURN 10;
|
||||
WHEN scaleDenominator <= 400000 AND scaleDenominator > 200000 THEN RETURN 11;
|
||||
WHEN scaleDenominator <= 200000 AND scaleDenominator > 100000 THEN RETURN 12;
|
||||
WHEN scaleDenominator <= 100000 AND scaleDenominator > 50000 THEN RETURN 13;
|
||||
WHEN scaleDenominator <= 50000 AND scaleDenominator > 25000 THEN RETURN 14;
|
||||
WHEN scaleDenominator <= 25000 AND scaleDenominator > 12500 THEN RETURN 15;
|
||||
WHEN scaleDenominator <= 12500 AND scaleDenominator > 5000 THEN RETURN 16;
|
||||
WHEN scaleDenominator <= 5000 AND scaleDenominator > 2500 THEN RETURN 17;
|
||||
WHEN scaleDenominator <= 2500 AND scaleDenominator > 1500 THEN RETURN 18;
|
||||
WHEN scaleDenominator <= 1500 AND scaleDenominator > 750 THEN RETURN 19;
|
||||
WHEN scaleDenominator <= 750 AND scaleDenominator > 500 THEN RETURN 20;
|
||||
WHEN scaleDenominator <= 500 AND scaleDenominator > 250 THEN RETURN 21;
|
||||
WHEN scaleDenominator <= 250 AND scaleDenominator > 100 THEN RETURN 22;
|
||||
WHEN scaleDenominator <= 100 THEN RETURN 23;
|
||||
END CASE;
|
||||
END
|
||||
$$ LANGUAGE plpgsql IMMUTABLE;
|
||||
1
scripts-enabled/220-CDB_Math.sql
Symbolic link
1
scripts-enabled/220-CDB_Math.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../scripts-available/CDB_Math.sql
|
||||
1
scripts-enabled/230-CDB_ZoomFromScale.sql
Symbolic link
1
scripts-enabled/230-CDB_ZoomFromScale.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../scripts-available/CDB_ZoomFromScale.sql
|
||||
@@ -8,6 +8,8 @@ SELECT cartodb.cdb_enable_ddl_hooks();
|
||||
|
||||
create schema c;
|
||||
|
||||
SELECT CDB_SetUserQuotaInBytes('c', 0);
|
||||
|
||||
CREATE USER cartodb_postgresql_unpriv_user;
|
||||
GRANT ALL ON SCHEMA c to cartodb_postgresql_unpriv_user;
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
@@ -16,7 +18,7 @@ SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
----------------------
|
||||
-- CREATE TABLE
|
||||
----------------------
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select 1 as i INTO c.t3;
|
||||
|
||||
select
|
||||
@@ -26,11 +28,13 @@ select
|
||||
i
|
||||
from c.t3;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)) as age
|
||||
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
-- Table with cartodb_id field, see
|
||||
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
|
||||
select 1 as cartodb_id INTO c.t4;
|
||||
@@ -39,6 +43,8 @@ select
|
||||
NOW() - updated_at < '1 secs' as "u<1s",
|
||||
the_geom, the_geom_webmercator
|
||||
from c.t4;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)) as age
|
||||
@@ -47,6 +53,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t4'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE RENAME COLUMN
|
||||
----------------------------
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
|
||||
select pg_sleep(.1);
|
||||
alter table c.t3 rename column the_geom_webmercator to webmerc;
|
||||
@@ -58,11 +65,13 @@ select
|
||||
i, webmerc
|
||||
from c.t3;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
alter table c.t3 rename column the_geom_webmercator to webmerc2;
|
||||
|
||||
@@ -73,6 +82,7 @@ select
|
||||
i, webmerc, webmerc2
|
||||
from c.t3;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -81,7 +91,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE DROP COLUMN
|
||||
----------------------------
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
alter table c.t3 drop column the_geom_webmercator;
|
||||
|
||||
@@ -92,6 +102,7 @@ select
|
||||
i, webmerc, webmerc2
|
||||
from c.t3;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
@@ -100,7 +111,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
|
||||
----------------------------
|
||||
-- ALTER TABLE ADD COLUMN
|
||||
----------------------------
|
||||
|
||||
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
|
||||
select pg_sleep(.1);
|
||||
alter table c.t3 add column id2 int;
|
||||
|
||||
@@ -111,6 +122,7 @@ select
|
||||
i, webmerc, webmerc2, id2
|
||||
from c.t3;
|
||||
|
||||
RESET SESSION AUTHORIZATION;
|
||||
select
|
||||
tabname::text,
|
||||
round(extract('secs' from now() - updated_at)*10) as agecs
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SET client_min_messages TO error;
|
||||
\set VERBOSITY terse;
|
||||
\set VERBOSITY default
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_CartodbfyTableCheck(tabname regclass, label text)
|
||||
RETURNS text AS
|
||||
|
||||
@@ -3,7 +3,7 @@ CREATE FUNCTION
|
||||
SELECT 1
|
||||
ERROR: Please set user quota before cartodbfying tables.
|
||||
CONTEXT: SQL statement "SELECT cartodb._CDB_check_prerequisites(schema_name, reloid)"
|
||||
PL/pgSQL function cdb_cartodbfytable(text,regclass) line 6 at PERFORM
|
||||
PL/pgSQL function cdb_cartodbfytable(text,regclass) line 7 at PERFORM
|
||||
0
|
||||
single non-geometrical column cartodbfied fine
|
||||
DROP TABLE
|
||||
|
||||
4
test/CDB_MathTest.sql
Normal file
4
test/CDB_MathTest.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
SELECT cdb_math_mode(a) from unnest(ARRAY[1,2,2,3]) a;
|
||||
SELECT cdb_math_mode(a) from unnest(ARRAY[1,2,3]) a;
|
||||
SELECT cdb_math_mode(a) from unnest(ARRAY[1]) a;
|
||||
3
test/CDB_MathTest_expect
Normal file
3
test/CDB_MathTest_expect
Normal file
@@ -0,0 +1,3 @@
|
||||
2
|
||||
1
|
||||
1
|
||||
@@ -31,3 +31,7 @@ create table sc.test (a int);
|
||||
insert into sc.test values (1);
|
||||
WITH inp AS ( select 'select * from sc.test'::text as q )
|
||||
SELECT q, CDB_QueryTables(q) from inp;
|
||||
|
||||
WITH inp AS ( select 'SELECT
|
||||
* FROM geometry_columns'::text as q )
|
||||
SELECT q, CDB_QueryTables(q) from inp;
|
||||
|
||||
@@ -13,3 +13,5 @@ CREATE SCHEMA
|
||||
CREATE TABLE
|
||||
INSERT 0 1
|
||||
select * from sc.test|{sc.test}
|
||||
SELECT
|
||||
* FROM geometry_columns|{pg_catalog.pg_attribute,pg_catalog.pg_class,pg_catalog.pg_namespace,pg_catalog.pg_type}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
set client_min_messages to ERROR;
|
||||
\set VERBOSITY terse
|
||||
set client_min_messages to error;
|
||||
\set VERBOSITY default
|
||||
|
||||
CREATE TABLE big(a int);
|
||||
-- Try the legacy interface
|
||||
-- See https://github.com/CartoDB/cartodb-postgresql/issues/13
|
||||
@@ -9,8 +10,10 @@ INSERT INTO big VALUES (1); -- allowed, check runs before
|
||||
INSERT INTO big VALUES (1); -- disallowed, quota exceeds before
|
||||
SELECT CDB_SetUserQuotaInBytes(0);
|
||||
SELECT CDB_CartodbfyTable('big');
|
||||
INSERT INTO big SELECT generate_series(1,1024);
|
||||
SELECT CDB_SetUserQuotaInBytes(8);
|
||||
INSERT INTO big SELECT generate_series(1,2048);
|
||||
INSERT INTO big SELECT generate_series(1,2048);
|
||||
INSERT INTO big SELECT generate_series(1,2048);
|
||||
SELECT CDB_SetUserQuotaInBytes(2);
|
||||
INSERT INTO big VALUES (1);
|
||||
SELECT CDB_SetUserQuotaInBytes(0);
|
||||
INSERT INTO big VALUES (1);
|
||||
|
||||
@@ -5,9 +5,11 @@ INSERT 0 1
|
||||
ERROR: Quota exceeded by 3.9990234375KB
|
||||
0
|
||||
|
||||
INSERT 0 1024
|
||||
8
|
||||
ERROR: Quota exceeded by 103.9921875KB
|
||||
INSERT 0 2048
|
||||
INSERT 0 2048
|
||||
INSERT 0 2048
|
||||
2
|
||||
ERROR: Quota exceeded by 567.998046875KB
|
||||
0
|
||||
INSERT 0 1
|
||||
DROP TABLE
|
||||
|
||||
4
test/extension/run_at_cartodb_schema.sql
Normal file
4
test/extension/run_at_cartodb_schema.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
SET SCHEMA 'cartodb';
|
||||
\i scripts-available/CDB_Quota.sql
|
||||
\i scripts-available/CDB_TableMetadata.sql
|
||||
SET SCHEMA 'public';
|
||||
329
test/extension/test.sh
Executable file
329
test/extension/test.sh
Executable file
@@ -0,0 +1,329 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Tests for the extension since version 0.5.0. They don't replace SQL based ones, for now need to run both
|
||||
#
|
||||
|
||||
# It is expected that you run this script as a PostgreSQL superuser, for example:
|
||||
#
|
||||
# PGUSER=postgres bash ./test.sh
|
||||
#
|
||||
|
||||
DATABASE=test_extension
|
||||
CMD='echo psql'
|
||||
CMD=psql
|
||||
|
||||
OK=0
|
||||
PARTIALOK=0
|
||||
|
||||
function set_failed() {
|
||||
OK=1
|
||||
PARTIALOK=1
|
||||
}
|
||||
|
||||
|
||||
function clear_partial_result() {
|
||||
PARTIALOK=0
|
||||
}
|
||||
|
||||
|
||||
function sql() {
|
||||
local ROLE
|
||||
local QUERY
|
||||
if [[ $# -ge 2 ]]
|
||||
then
|
||||
ROLE="$1"
|
||||
QUERY="$2"
|
||||
else
|
||||
QUERY="$1"
|
||||
fi
|
||||
|
||||
if [ -n "${ROLE}" ]; then
|
||||
log_debug "Executing query '${QUERY}' as ${ROLE}"
|
||||
RESULT=`${CMD} -U "${ROLE}" ${DATABASE} -c "${QUERY}" -A -t`
|
||||
else
|
||||
log_debug "Executing query '${QUERY}'"
|
||||
RESULT=`${CMD} ${DATABASE} -c "${QUERY}" -A -t`
|
||||
fi
|
||||
CODERESULT=$?
|
||||
|
||||
echo ${RESULT}
|
||||
echo
|
||||
|
||||
if [[ ${CODERESULT} -ne 0 ]]
|
||||
then
|
||||
echo -n "FAILED TO EXECUTE QUERY: "
|
||||
log_warning "${QUERY}"
|
||||
if [[ "$3" != "fails" ]]
|
||||
then
|
||||
log_error "${QUERY}"
|
||||
set_failed
|
||||
fi
|
||||
else
|
||||
if [[ "$3" == "fails" ]]
|
||||
then
|
||||
log_error "QUERY: '${QUERY}' was expected to fail and it did not fail"
|
||||
set_failed
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$3" == "should" ]]
|
||||
then
|
||||
if [[ "${RESULT}" != "$4" ]]
|
||||
then
|
||||
log_error "QUERY '${QUERY}' expected result '${4}' but got '${RESULT}'"
|
||||
set_failed
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$3" == "should-not" ]]
|
||||
then
|
||||
if [[ "${RESULT}" == "$4" ]]
|
||||
then
|
||||
log_error "QUERY '${QUERY}' did not expect '${RESULT}'"
|
||||
set_failed
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function log_info()
|
||||
{
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
_log "1;34m" "$1"
|
||||
}
|
||||
|
||||
function log_error() {
|
||||
_log "1;31m" "$1"
|
||||
}
|
||||
|
||||
function log_debug() {
|
||||
_log "1;32m" "> $1"
|
||||
}
|
||||
|
||||
function log_warning() {
|
||||
_log "0;33m" "$1"
|
||||
}
|
||||
|
||||
function _log() {
|
||||
echo -e "\033[$1$2\033[0m"
|
||||
}
|
||||
|
||||
# '############################ HELPERS #############################'
|
||||
function create_role_and_schema() {
|
||||
local ROLE=$1
|
||||
sql "CREATE ROLE ${ROLE} LOGIN;"
|
||||
sql "GRANT CONNECT ON DATABASE \"${DATABASE}\" TO ${ROLE};"
|
||||
sql "CREATE SCHEMA ${ROLE} AUTHORIZATION ${ROLE};"
|
||||
sql "SELECT cartodb.CDB_Organization_Create_Member('${ROLE}');"
|
||||
}
|
||||
|
||||
|
||||
function drop_role_and_schema() {
|
||||
local ROLE=$1
|
||||
sql "DROP SCHEMA \"${ROLE}\";"
|
||||
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM \"${ROLE}\";"
|
||||
sql "DROP ROLE \"${ROLE}\";"
|
||||
}
|
||||
|
||||
|
||||
function create_table() {
|
||||
if [[ $# -ne 2 ]]
|
||||
then
|
||||
log_error "create_table requires two arguments: role and table_name"
|
||||
exit 1
|
||||
fi
|
||||
local ROLE="$1"
|
||||
local TABLENAME="$2"
|
||||
sql ${ROLE} "CREATE TABLE ${ROLE}.${TABLENAME} ( a int );"
|
||||
}
|
||||
|
||||
|
||||
function create_raster_table() {
|
||||
if [[ $# -ne 2 ]]
|
||||
then
|
||||
log_error "create_raster_table requires two arguments: role and table_name"
|
||||
exit 1
|
||||
fi
|
||||
local RASTER_COL="the_raster_webmercator"
|
||||
local ROLE="$1"
|
||||
local TABLENAME="$2"
|
||||
local OVERVIEW_TABLENAME="o_2_${TABLENAME}"
|
||||
sql ${ROLE} "CREATE TABLE ${ROLE}.${TABLENAME} (rid serial PRIMARY KEY, ${RASTER_COL} raster);"
|
||||
|
||||
sql ${ROLE} "CREATE TABLE ${ROLE}.${OVERVIEW_TABLENAME} (rid serial PRIMARY KEY, ${RASTER_COL} raster);"
|
||||
|
||||
sql ${ROLE} "SELECT AddOverviewConstraints('${ROLE}','${OVERVIEW_TABLENAME}','${RASTER_COL}','${ROLE}','${TABLENAME}','${RASTER_COL}',2);"
|
||||
}
|
||||
|
||||
function drop_raster_table() {
|
||||
if [[ $# -ne 2 ]]
|
||||
then
|
||||
log_error "drop_raster_table requires two arguments: role and table_name"
|
||||
exit 1
|
||||
fi
|
||||
local ROLE="$1"
|
||||
local TABLENAME="$2"
|
||||
local OVERVIEW_TABLENAME="o_2_${TABLENAME}"
|
||||
|
||||
sql ${ROLE} "DROP TABLE ${ROLE}.${OVERVIEW_TABLENAME};"
|
||||
sql ${ROLE} "DROP TABLE ${ROLE}.${TABLENAME};"
|
||||
}
|
||||
|
||||
|
||||
function setup() {
|
||||
${CMD} -c "CREATE DATABASE ${DATABASE}"
|
||||
sql "CREATE SCHEMA cartodb;"
|
||||
sql "GRANT USAGE ON SCHEMA cartodb TO public;"
|
||||
sql "CREATE EXTENSION postgis;"
|
||||
|
||||
log_info "########################### BOOTSTRAP ###########################"
|
||||
${CMD} -d ${DATABASE} -f scripts-available/CDB_Organizations.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
|
||||
|
||||
|
||||
log_info "############################# SETUP #############################"
|
||||
create_role_and_schema cdb_testmember_1
|
||||
create_role_and_schema cdb_testmember_2
|
||||
|
||||
create_table cdb_testmember_1 foo
|
||||
sql cdb_testmember_1 'INSERT INTO cdb_testmember_1.foo VALUES (1), (2), (3), (4), (5), (6);'
|
||||
sql cdb_testmember_1 'SELECT * FROM cdb_testmember_1.foo;'
|
||||
|
||||
create_table cdb_testmember_2 bar
|
||||
sql cdb_testmember_2 'INSERT INTO bar VALUES (1), (2), (3);'
|
||||
sql cdb_testmember_2 'SELECT * FROM cdb_testmember_2.bar;'
|
||||
}
|
||||
|
||||
function tear_down() {
|
||||
log_info "########################### USER TEAR DOWN ###########################"
|
||||
sql cdb_testmember_1 "SELECT * FROM cartodb.CDB_Organization_Remove_Access_Permission('cdb_testmember_1', 'foo', 'cdb_testmember_2');"
|
||||
sql cdb_testmember_2 "SELECT * FROM cartodb.CDB_Organization_Remove_Access_Permission('cdb_testmember_2', 'bar', 'cdb_testmember_1');"
|
||||
|
||||
sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.foo;'
|
||||
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.bar;'
|
||||
|
||||
sql "DROP SCHEMA cartodb CASCADE"
|
||||
|
||||
log_info "########################### TEAR DOWN ###########################"
|
||||
sql 'DROP SCHEMA cdb_testmember_1;'
|
||||
sql 'DROP SCHEMA cdb_testmember_2;'
|
||||
|
||||
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_1;"
|
||||
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_2;"
|
||||
|
||||
sql 'DROP ROLE cdb_testmember_1;'
|
||||
sql 'DROP ROLE cdb_testmember_2;'
|
||||
|
||||
${CMD} -c "DROP DATABASE ${DATABASE}"
|
||||
}
|
||||
|
||||
function run_tests() {
|
||||
local FAILED_TESTS=()
|
||||
|
||||
local TESTS
|
||||
if [[ $# -ge 1 ]]
|
||||
then
|
||||
TESTS="$@"
|
||||
else
|
||||
TESTS=`cat $0 | perl -n -e'/function (test.*)\(\)/ && print "$1\n"'`
|
||||
fi
|
||||
for t in ${TESTS}
|
||||
do
|
||||
echo "####################################################################"
|
||||
echo "#"
|
||||
echo "# Running: ${t}"
|
||||
echo "#"
|
||||
echo "####################################################################"
|
||||
clear_partial_result
|
||||
setup
|
||||
eval ${t}
|
||||
if [[ ${PARTIALOK} -ne 0 ]]
|
||||
then
|
||||
FAILED_TESTS+=(${t})
|
||||
fi
|
||||
tear_down
|
||||
done
|
||||
if [[ ${OK} -ne 0 ]]
|
||||
then
|
||||
echo
|
||||
log_error "The following tests are failing:"
|
||||
printf -- '\t%s\n' "${FAILED_TESTS[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
#################################################### TESTS GO HERE ####################################################
|
||||
|
||||
|
||||
# Tests quota checking taking into account both geom and raster tables
|
||||
function test_quota_for_each_user() {
|
||||
# Normal tables add 4096 bytes
|
||||
# Raster tables no longer add anything so also count as 4096
|
||||
|
||||
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 4096
|
||||
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 4096
|
||||
|
||||
create_raster_table cdb_testmember_1 raster_1
|
||||
create_raster_table cdb_testmember_2 raster_2
|
||||
|
||||
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 20480
|
||||
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 20480
|
||||
|
||||
create_raster_table cdb_testmember_1 raster_3
|
||||
|
||||
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 36864
|
||||
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 20480
|
||||
|
||||
drop_raster_table cdb_testmember_1 raster_1
|
||||
drop_raster_table cdb_testmember_2 raster_2
|
||||
drop_raster_table cdb_testmember_1 raster_3
|
||||
|
||||
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 4096
|
||||
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 4096
|
||||
}
|
||||
|
||||
function test_cdb_tablemetadatatouch() {
|
||||
sql "CREATE TABLE touch_example (a int)"
|
||||
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should ''
|
||||
sql "SELECT CDB_TableMetadataTouch('touch_example');"
|
||||
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should-not ''
|
||||
|
||||
# Another call doesn't fail
|
||||
sql "SELECT CDB_TableMetadataTouch('touch_example');"
|
||||
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should-not ''
|
||||
|
||||
# Works with qualified tables
|
||||
sql "SELECT CDB_TableMetadataTouch('public.touch_example');"
|
||||
sql "SELECT CDB_TableMetadataTouch('public.\"touch_example\"');"
|
||||
sql "SELECT CDB_TableMetadataTouch('\"public\".touch_example');"
|
||||
sql "SELECT CDB_TableMetadataTouch('\"public\".\"touch_example\"');"
|
||||
|
||||
#### test tear down
|
||||
sql 'DROP TABLE touch_example;'
|
||||
}
|
||||
|
||||
function test_cdb_tablemetadatatouch_fails_for_unexistent_table() {
|
||||
sql postgres "SELECT CDB_TableMetadataTouch('unexistent_example');" fails
|
||||
}
|
||||
|
||||
function test_cdb_tablemetadatatouch_fails_from_user_without_permission() {
|
||||
sql "CREATE TABLE touch_example (a int);"
|
||||
sql postgres "SELECT CDB_TableMetadataTouch('touch_example');"
|
||||
|
||||
sql cdb_testmember_1 "SELECT CDB_TableMetadataTouch('touch_example');" fails
|
||||
|
||||
sql postgres "GRANT ALL ON CDB_TableMetadata TO cdb_testmember_1;"
|
||||
sql cdb_testmember_1 "SELECT CDB_TableMetadataTouch('touch_example');"
|
||||
|
||||
sql postgres "REVOKE ALL ON CDB_TableMetadata FROM cdb_testmember_1;"
|
||||
}
|
||||
|
||||
#################################################### TESTS END HERE ####################################################
|
||||
|
||||
run_tests $@
|
||||
|
||||
exit ${OK}
|
||||
Reference in New Issue
Block a user