Compare commits

...

35 Commits

Author SHA1 Message Date
Sandro Santilli
befa7a10c8 Set version to 0.2.0 2014-06-09 12:51:31 +02:00
Sandro Santilli
f75c256b6e Another full qualification of CDB_TransformToWebmercator in CDB_CartodbfyTable 2014-06-06 18:09:41 +02:00
Sandro Santilli
d52556c20e Fully qualify call to CDB_TransformToWebmercator from CDB_CartodbfyTable 2014-06-06 17:28:43 +02:00
Sandro Santilli
85afef40d8 Make git dependency support use as a submodule 2014-06-06 16:15:02 +02:00
Sandro Santilli
1692e792a7 Make .git/index a dependency of cartodb_version.sql
Ensures proper rebuild of version function on git pull/commit
2014-06-06 13:36:21 +02:00
Sandro Santilli
f8180123eb Grant permission to run table-info functions to public
This is needed as a way to migrate from versions < 0.2.0
See #36
2014-06-06 11:36:19 +02:00
Sandro Santilli
01ae7b8c10 Drop role management
Roles are not created anymore, previously private functions for table
information extraction (CDB_UserTables, CDB_TableIndexes, CDB_ColumnNames,
CDB_ColumnType) will now be callable by anyone while only returning
information about tables over which the calling user has SELECT privilege.

Closes #36
2014-06-06 11:02:51 +02:00
Sandro Santilli
edc56e60ee Further increase in test tolerance 2014-06-05 18:21:52 +02:00
Sandro Santilli
f6e0456265 Increase tolerance in floating number based tests (extent) 2014-06-05 18:20:04 +02:00
Sandro Santilli
1f7b8db532 [Travis] install postgresql-plpython-9.3 package, now needed 2014-06-05 15:06:14 +02:00
Sandro Santilli
f9f73d2d62 Fix potential infinite loop in CDB_QueryStatements
This fix was already present at one point in cartodb/lib/sql
(where the code was copied from) but in a different branch than
the one the code was initially copied from.

The fix depends on plpython language which becomes a new dependency.
2014-06-05 15:00:57 +02:00
Sandro Santilli
fba8d3ab84 Do not assume cartodb functions install in "public" schema during testing 2014-06-04 17:03:17 +02:00
Sandro Santilli
ca07c81f13 Make sed usage more compatible
... and a bit less safe

Might close #35
2014-06-04 15:11:30 +02:00
Sandro Santilli
9322cecb3d Make sed command a variable 2014-06-04 12:58:19 +02:00
Sandro Santilli
e932ec3595 Fix formatting 2014-06-04 12:53:14 +02:00
Raul Ochoa
3fb1f69eb1 CDB-3086 adds troubleshooting section to readme with information about mac os x sed 2014-06-04 12:52:51 +02:00
Sandro Santilli
e993f83b8d Rename test to have "Test" suffix 2014-06-04 10:41:34 +02:00
Sandro Santilli
651bb8cdb7 Add instructions about adding a test 2014-06-04 10:40:18 +02:00
Sandro Santilli
a92d7d7d37 Add cdb_extension_reload() utility function 2014-06-04 10:31:03 +02:00
Sandro Santilli
c286727181 Add note about extension needing to be installed before it can be upgraded to 2014-06-04 10:16:42 +02:00
Sandro Santilli
d762da1ca2 Add section about updating cartodb extension
CDB-3049
2014-06-04 10:13:35 +02:00
Sandro Santilli
a650c951c8 Add link to pg_schema_triggers fork 2014-06-03 16:26:05 +02:00
Sandro Santilli
9230ffa925 Include revision info in cdb_version() output
Closes #34

NOTE: it will only work if "make" is run from within a git clone
2014-06-03 13:20:49 +02:00
Sandro Santilli
ce20009fb2 Workaround PostgreSQL bug possibly triggering infinite loops
Implements casting of existing system column values during
cartodbfication using ALTER rather than UPDATE.

It's faster for tables with many rows and works around a
longstanding PostgreSQL bug. See
http://www.postgresql.org/message-id/20140530143150.GA11051@localhost

CDB-3059
2014-05-30 19:24:19 +02:00
Sandro Santilli
cc9cbdb7a7 Typo 2014-05-30 18:35:08 +02:00
Sandro Santilli
ac53d6b000 Formatting only change 2014-05-30 12:22:54 +02:00
Sandro Santilli
f5ad0d0434 Fully qualify call to CDB_UserDataSize from quota trigger 2014-05-28 17:42:11 +02:00
Sandro Santilli
bfd56f0ea6 Fully qualify call to cdb_disable_ddl_hooks from cdb_enable_ddl_hooks 2014-05-28 12:53:22 +02:00
Sandro Santilli
7483f8d10b Update NEWS file (0.1.1 will likely not happen) 2014-05-28 12:32:30 +02:00
Sandro Santilli
004c3c5543 Ensure cartodb_id uses an associated sequence
Closes #33
2014-05-28 10:45:42 +02:00
Sandro Santilli
d1990f1765 Provide upgrade paths
Mainly from 0.1.0 and 0.1.1
Includes 0.2.0dev to next and back
2014-05-28 09:48:32 +02:00
Sandro Santilli
2601364011 Fix recursive DDL trigger on create table
Closes #32
2014-05-28 09:02:02 +02:00
Sandro Santilli
85cc74b4f4 Do not install cartodb_version.sql in system dirs 2014-05-27 15:51:45 +02:00
Sandro Santilli
2ffa13af58 Add tool to create upgrades 2014-05-23 18:16:10 +02:00
Sandro Santilli
09cf368d62 Move DDL triggers and extension postamble under scripts-available
Target 0.2.0
2014-05-23 17:40:14 +02:00
28 changed files with 367 additions and 87 deletions

View File

@@ -6,6 +6,7 @@ addons:
before_install:
#- sudo apt-get install -q postgresql-9.3-postgis-2.1
- sudo apt-get install -q postgresql-server-dev-9.3
- sudo apt-get install -q postgresql-plpython-9.3
# Install schema_triggers
- hg clone https://bitbucket.org/malloclabs/pg_schema_triggers &&
cd pg_schema_triggers && make && sudo make install && cd -

View File

@@ -1,19 +1,42 @@
# cartodb/Makefile
EXTENSION = cartodb
EXTVERSION = 0.1.0
EXTVERSION = 0.2.0
SED = sed
CDBSCRIPTS = \
scripts-available/CDB_Roles.sql \
scripts-enabled/*.sql \
scripts-available/CDB_SearchPath.sql \
scripts-available/CDB_DDLTriggers.sql \
scripts-available/CDB_ExtensionPost.sql \
scripts-available/CDB_ExtensionUtils.sql \
$(END)
UPGRADABLE = \
unpackaged \
0.1.0 \
0.1.1 \
0.2.0dev \
$(EXTVERSION)next \
$(END)
UPGRADES = \
$(shell echo $(UPGRADABLE) | \
$(SED) 's/^/$(EXTENSION)--/' | \
$(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 = \
$(EXTENSION)--$(EXTVERSION).sql \
$(EXTENSION)--unpackaged--$(EXTVERSION).sql \
$(EXTENSION).control \
cartodb_version.sql
$(EXTENSION)--$(EXTVERSION)--$(EXTVERSION)next.sql \
$(UPGRADES) \
$(EXTENSION).control
EXTRA_CLEAN = cartodb_version.sql
DOCS = README.md
REGRESS_NEW = test_ddl_triggers
@@ -25,24 +48,28 @@ PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
$(EXTENSION)--$(EXTVERSION).sql: $(CDBSCRIPTS) cartodb_hooks.sql cartodb_version.sql cartodb_config_dump.sql Makefile
$(EXTENSION)--$(EXTVERSION).sql: $(CDBSCRIPTS) cartodb_version.sql Makefile
echo '\echo Use "CREATE EXTENSION $(EXTENSION)" to load this file. \quit' > $@
cat $(CDBSCRIPTS) | \
sed -e 's/\<public\./cartodb./g' \
$(SED) -e 's/public\./cartodb./g' \
-e 's/:DATABASE_USERNAME/cdb_org_admin/g' >> $@
echo "GRANT USAGE ON SCHEMA cartodb TO public;" >> $@
cat cartodb_hooks.sql >> $@
cat cartodb_version.sql >> $@
cat cartodb_config_dump.sql >> $@
$(EXTENSION)--unpackaged--$(EXTVERSION).sql: $(EXTENSION)--$(EXTVERSION).sql util/create_from_unpackaged.sh Makefile
./util/create_from_unpackaged.sh $(EXTVERSION)
$(EXTENSION).control: $(EXTENSION).control.in Makefile
sed -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
$(EXTENSION)--%--$(EXTVERSION).sql: $(EXTENSION)--$(EXTVERSION).sql
cp $< $@
cartodb_version.sql: cartodb_version.sql.in Makefile
sed -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
$(EXTENSION)--$(EXTVERSION)--$(EXTVERSION)next.sql: $(EXTENSION)--$(EXTVERSION).sql
cp $< $@
$(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)/' $< > $@
legacy_regress: $(REGRESS_OLD) Makefile
mkdir -p sql/test/
@@ -56,7 +83,7 @@ legacy_regress: $(REGRESS_OLD) Makefile
echo '\\t' >> $${of}; \
echo '\\set QUIET off' >> $${of}; \
cat $${f} | \
sed -e 's/\<public\./cartodb./g' >> $${of}; \
$(SED) -e 's/public\./cartodb./g' >> $${of}; \
exp=expected/test/$${tn}.out; \
echo '\\set ECHO off' > $${exp}; \
cat test/$${tn}_expect >> $${exp}; \

31
NEWS
View File

@@ -1,3 +1,34 @@
0.2.0 - 2014-06-09
------------------
Important changes:
- This release adds dependency on "plpythonu" extension
- Roles are not created anymore, previously private functions
for table information extraction (CDB_UserTables, CDB_TableIndexes,
CDB_ColumnNames, CDB_ColumnType) will now be callable by anyone while
only returning information about tables over which the calling user
has SELECT privilege (#36)
Bug fixes:
- Fix recursive trigger on create table (#32)
- Ensure cartodb_id uses an associated sequence (#33)
- Fully qualify call to cdb_disable_ddl_hooks from cdb_enable_ddl_hooks
- Fully qualify call to CDB_UserDataSize from quota trigger
- Fully qualify call to CDB_TransformToWebmercator from CDB_CartodbfyTable
- Fix potential infinite loop in CDB_CartodbfyTable
- Fix potential infinite loop in CDB_QueryStatements
Enhancements:
- Include revision info in cdb_version() output (#34)
New features:
- Add a cdb_extension_reload() function
0.1.0 - 2014-05-23
------------------

View File

@@ -11,9 +11,11 @@ See https://github.com/CartoDB/cartodb/wiki/CartoDB-PostgreSQL-extension
Dependencies
------------
* PostgreSQL 9.3+
* PostgreSQL 9.3+ (with plpythonu extension)
* [PostGIS extension](http://postgis.net)
* [Schema triggers extension]
(https://bitbucket.org/malloclabs/pg_schema_triggers)
(or [fork](https://github.com/CartoDB/pg_schema_triggers))
Install
-------
@@ -56,3 +58,48 @@ CREATE EXTENSION schema_triggers;
CREATE EXTENSION cartodb FROM unpackaged;
```
Update cartodb extension
------------------------
Updating the version of cartodb extension installed in a database
is done using ALTER EXTENSION.
```sql
ALTER EXTENSION cartodb UPDATE TO '0.1.1';
```
The target version needs to be installed on the system first
(see Install section).
If the "TO 'x.y.z'" part is omitted, the extension will be updated to the
latest installed version, which you can find with the following command:
```sh
grep default_version `pg_config --sharedir`/extension/cartodb.control
```
Updates are performed by PostgreSQL by loading one or more migration scripts
as needed to go from the installed version S to the target version T.
All migration scripts are in the "extension" directory of PostgreSQL:
```sh
ls `pg_config --sharedir`/extension/cartodb*
```
During development the cartodb extension version doesn't change with
every commit, so testing latest change requires cheating with PostgreSQL
so to enforce re-load of the scripts. To help with cheating, "make install"
also installs migration scripts to go from "V" to "V"next and from "V"next
to "V". Example to upgrade a 0.2.0dev version:
```sql
ALTER EXTENSION cartodb UPDATE TO '0.2.0devnext';
ALTER EXTENSION cartodb UPDATE TO '0.2.0dev';
```
Starting with 0.2.0, the in-place reload can be done with an ad-hoc function:
```sql
SELECT cartodb.cdb_extension_reload();
```

View File

@@ -3,4 +3,4 @@ comment = 'Turn a database into a cartodb user database.'
superuser = true
relocatable = false
schema = cartodb
requires = 'schema_triggers, postgis'
requires = 'schema_triggers, postgis, plpythonu'

View File

@@ -32,6 +32,11 @@ NOTICE: trigger "update_the_geom_webmercator_trigger" for table "c.t3" does not
NOTICE: trigger "update_updated_at_trigger" for table "c.t3" does not exist, skipping
NOTICE: trigger "test_quota" for table "c.t3" does not exist, skipping
NOTICE: trigger "test_quota_per_row" for table "c.t3" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_create" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_drop" does not exist, skipping
NOTICE: event trigger "cdb_on_alter_column" does not exist, skipping
NOTICE: event trigger "cdb_on_drop_column" does not exist, skipping
NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
NOTICE: cdb_invalidate_varnish(c.t3) called
select
cartodb_id, created_at=updated_at as "c=u",
@@ -47,12 +52,48 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | age
---------+-----
c.t3 | 0
(1 row)
-- Table with cartodb_id field, see
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
select 1 as cartodb_id INTO c.t4;
NOTICE: trigger "track_updates" for table "c.t4" does not exist, skipping
NOTICE: trigger "update_the_geom_webmercator_trigger" for table "c.t4" does not exist, skipping
NOTICE: trigger "update_updated_at_trigger" for table "c.t4" does not exist, skipping
NOTICE: trigger "test_quota" for table "c.t4" does not exist, skipping
NOTICE: trigger "test_quota_per_row" for table "c.t4" does not exist, skipping
NOTICE: Column cartodb_id already exists
NOTICE: Existing cartodb_id field does not have an associated sequence, renaming
NOTICE: Trying to recover data from _cartodb_id0 column
NOTICE: event trigger "cdb_on_relation_create" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_drop" does not exist, skipping
NOTICE: event trigger "cdb_on_alter_column" does not exist, skipping
NOTICE: event trigger "cdb_on_drop_column" does not exist, skipping
NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
NOTICE: cdb_invalidate_varnish(c.t4) called
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator
from c.t4;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator
------------+-----+------+----------+----------------------
1 | t | t | |
(1 row)
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata WHERE tabname = 'c.t4'::regclass;
tabname | age
---------+-----
c.t4 | 0
(1 row)
----------------------------
-- ALTER TABLE RENAME COLUMN
----------------------------
@@ -87,7 +128,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
@@ -124,7 +165,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
@@ -164,7 +205,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
@@ -195,7 +236,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
@@ -206,8 +247,8 @@ FROM CDB_TableMetadata;
----------------------------
RESET SESSION AUTHORIZATION;
drop schema c cascade;
NOTICE: drop cascades to table c.t3
select count(*) from CDB_TableMetadata;
NOTICE: drop cascades to 2 other objects
select count(*) from CDB_TableMetadata;
count
-------
0

View File

@@ -1,5 +1,6 @@
CREATE EXTENSION postgis;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION plpythonu;
CREATE EXTENSION cartodb;
CREATE FUNCTION public.cdb_invalidate_varnish(table_name text)
RETURNS void AS $$

View File

@@ -10,7 +10,7 @@
CREATE OR REPLACE FUNCTION _CDB_update_the_geom_webmercator()
RETURNS trigger AS $$
BEGIN
NEW.the_geom_webmercator := CDB_TransformToWebmercator(NEW.the_geom);
NEW.the_geom_webmercator := public.CDB_TransformToWebmercator(NEW.the_geom);
RETURN NEW;
END;
$$ LANGUAGE plpgsql VOLATILE;
@@ -89,13 +89,21 @@ BEGIN
IF had_column THEN
SELECT pg_catalog.pg_get_serial_sequence(reloid::text, 'cartodb_id')
AS seq INTO rec2;
-- Check data type is an integer
SELECT t.typname, t.oid, a.attnotnull FROM pg_type t, pg_attribute a
SELECT
pg_catalog.pg_get_serial_sequence(reloid::text, 'cartodb_id') as seq,
t.typname, t.oid, a.attnotnull FROM pg_type t, pg_attribute a
WHERE a.atttypid = t.oid AND a.attrelid = reloid AND NOT a.attisdropped
AND a.attname = 'cartodb_id'
INTO STRICT rec;
IF rec.oid NOT IN (20,21,23) THEN -- int2, int4, int8 {
-- 20=int2, 21=int4, 23=int8
IF rec.oid NOT IN (20,21,23) THEN -- {
RAISE NOTICE 'Existing cartodb_id field is of invalid type % (need int2, int4 or int8), renaming', rec.typname;
ELSIF rec.seq IS NULL THEN -- }{
RAISE NOTICE 'Existing cartodb_id field does not have an associated sequence, renaming';
ELSE -- }{
sql := 'ALTER TABLE ' || reloid::text || ' ALTER COLUMN cartodb_id SET NOT NULL';
IF NOT EXISTS ( SELECT c.conname FROM pg_constraint c, pg_attribute a
@@ -147,10 +155,14 @@ BEGIN
-- Try to copy data from new name if possible
IF new_name IS NOT NULL THEN
RAISE NOTICE 'Trying to recover data from % coumn', new_name;
RAISE NOTICE 'Trying to recover data from % column', new_name;
BEGIN
-- Copy existing values to new field
sql := 'UPDATE ' || reloid::text || ' SET cartodb_id = '
-- NOTE: using ALTER is a workaround to a PostgreSQL bug and
-- is also known to be faster for tables with many rows
-- See http://www.postgresql.org/message-id/20140530143150.GA11051@localhost
sql := 'ALTER TABLE ' || reloid::text
|| ' ALTER cartodb_id TYPE int USING '
|| new_name || '::int4';
RAISE DEBUG 'Running %', sql;
EXECUTE sql;
@@ -183,7 +195,8 @@ BEGIN
END IF;
-- We need created_at and updated_at
FOR rec IN SELECT * FROM ( VALUES ('created_at'), ('updated_at') ) t(cname) LOOP --{
FOR rec IN SELECT * FROM ( VALUES ('created_at'), ('updated_at') ) t(cname)
LOOP --{
new_name := null;
<< column_setup >>
LOOP --{
@@ -264,7 +277,11 @@ cname, rec2.typname;
RAISE NOTICE 'Trying to recover data from % coumn', new_name;
BEGIN
-- Copy existing values to new field
sql := 'UPDATE ' || reloid::text || ' SET ' || rec.cname || ' = '
-- NOTE: using ALTER is a workaround to a PostgreSQL bug and
-- is also known to be faster for tables with many rows
-- See http://www.postgresql.org/message-id/20140530143150.GA11051@localhost
sql := 'ALTER TABLE ' || reloid::text || ' ALTER ' || rec.cname
|| ' TYPE TIMESTAMPTZ USING '
|| new_name || '::timestamptz';
RAISE DEBUG 'Running %', sql;
EXECUTE sql;
@@ -401,7 +418,7 @@ cname, rec2.typname;
-- do this only if the_geom was found (not created)
-- _and_ the_geom_webmercator was NOT found.
IF exists_geom_cols[1] AND NOT exists_geom_cols[2] THEN
sql := 'UPDATE ' || reloid::text || ' SET the_geom_webmercator = CDB_TransformToWebmercator(the_geom) ';
sql := 'UPDATE ' || reloid::text || ' SET the_geom_webmercator = public.CDB_TransformToWebmercator(the_geom) ';
EXECUTE sql;
END IF;

View File

@@ -11,6 +11,6 @@ AS $$
$$ LANGUAGE SQL;
-- This is a private function, so only the db owner need privileges
REVOKE ALL ON FUNCTION CDB_ColumnNames(REGCLASS) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION CDB_ColumnNames(REGCLASS) TO ":DATABASE_USERNAME";
-- This is to migrate from pre-0.2.0 version
-- See http://github.com/CartoDB/cartodb-postgresql/issues/36
GRANT EXECUTE ON FUNCTION CDB_ColumnNames(REGCLASS) TO PUBLIC;

View File

@@ -12,6 +12,6 @@ AS $$
$$ LANGUAGE SQL;
-- This is a private function, so only the db owner need privileges
REVOKE ALL ON FUNCTION CDB_ColumnType(REGCLASS, TEXT) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION CDB_ColumnType(REGCLASS, TEXT) TO ":DATABASE_USERNAME";
-- This is to migrate from pre-0.2.0 version
-- See http://github.com/CartoDB/cartodb-postgresql/issues/36
GRANT EXECUTE ON FUNCTION CDB_ColumnType(REGCLASS, TEXT) TO public;

View File

@@ -1,8 +1,3 @@
--LOAD 'schema_triggers.so';
--CREATE EXTENSION IF NOT EXISTS schema_triggers;
--GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_triggers TO public;
-- Table creation
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_create_table ()
@@ -24,9 +19,13 @@ BEGIN
RETURN;
END IF;
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_enable_ddl_hooks();
RAISE DEBUG 'Inserting into cartodb.CDB_TableMetadata';
-- Add entry to CDB_TableMetadata (should CartodbfyTable do this?)
@@ -171,7 +170,7 @@ CREATE OR REPLACE FUNCTION cartodb.cdb_disable_ddl_hooks() returns void AS $$
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION cartodb.cdb_enable_ddl_hooks() returns void AS $$
SELECT cdb_disable_ddl_hooks();
SELECT cartodb.cdb_disable_ddl_hooks();
CREATE EVENT TRIGGER cdb_on_relation_create
ON "relation_create" EXECUTE PROCEDURE cartodb.cdb_handle_create_table();
CREATE EVENT TRIGGER cdb_on_relation_drop

View File

@@ -0,0 +1,13 @@
CREATE OR REPLACE FUNCTION cartodb.cdb_extension_reload() RETURNS void
AS $$
DECLARE
ver TEXT;
sql TEXT;
BEGIN
ver := split_part(cartodb.cdb_version(), ' ', 1);
sql := 'ALTER EXTENSION cartodb UPDATE TO ''' || ver || 'next''';
EXECUTE sql;
sql := 'ALTER EXTENSION cartodb UPDATE TO ''' || ver || '''';
EXECUTE sql;
END;
$$ language 'plpgsql' VOLATILE;

View File

@@ -1,13 +1,14 @@
-- Return an array of statements found in the given query text
--
-- Curtesy of Hubert Lubaczewski (depesz)
-- Regexp curtesy of Hubert Lubaczewski (depesz)
-- Implemented in plpython for performance reasons
--
CREATE OR REPLACE FUNCTION CDB_QueryStatements(query text)
RETURNS SETOF TEXT AS $$
SELECT stmt FROM (
SELECT btrim(q[1], E' \n\t\r;') as stmt FROM (
SELECT regexp_matches( $1, $REG$((?:[^'"$;]+|"[^"]*"|'(?:[^']*|'')*'|(\$[^$]*\$).*?\2)+)$REG$, 'g' ) as q
) i
) j
WHERE stmt <> '';
$$ language sql IMMUTABLE STRICT;
import re
pat = re.compile( r'''((?:[^'"$;]+|"[^"]*"|'[^']*'|(\$[^$]*\$).*?\2)+)''', re.DOTALL )
for match in pat.findall(query):
cleaned = match[0].strip()
if ( cleaned ):
yield cleaned
$$ language 'plpythonu' IMMUTABLE STRICT;

View File

@@ -50,7 +50,7 @@ BEGIN
RETURN NEW;
END IF;
SELECT CDB_UserDataSize() INTO quota;
SELECT public.CDB_UserDataSize() INTO quota;
IF quota > qmax THEN
RAISE EXCEPTION 'Quota exceeded by %KB', (quota-qmax)/1024;
ELSE RAISE DEBUG 'User quota in bytes: % < % (max allowed)', quota, qmax;

View File

@@ -1,13 +0,0 @@
DO LANGUAGE 'plpgsql' $$
BEGIN
IF NOT EXISTS ( SELECT * FROM pg_roles WHERE rolname= 'cdb_org_admin' )
THEN
CREATE ROLE cdb_org_admin NOLOGIN;
END IF;
IF NOT EXISTS ( SELECT * FROM pg_roles WHERE rolname= 'cdb_org_user' )
THEN
CREATE ROLE cdb_org_user NOLOGIN;
END IF;
END
$$;

View File

@@ -17,10 +17,11 @@ AS $$
ON pg_class.oid = idx.indexrelid
WHERE pg_indexes.tablename = '' || $1 || ''
AND '' || $1 || '' IN (SELECT CDB_UserTables())
AND pg_class.relname=pg_indexes.indexname;
AND pg_class.relname=pg_indexes.indexname
;
$$ LANGUAGE SQL;
-- This is a private function, so only the db owner need privileges
REVOKE ALL ON FUNCTION CDB_TableIndexes(REGCLASS) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION CDB_TableIndexes(REGCLASS) TO ":DATABASE_USERNAME";
-- This is to migrate from pre-0.2.0 version
-- See http://github.com/CartoDB/cartodb-postgresql/issues/36
GRANT EXECUTE ON FUNCTION CDB_TableIndexes(REGCLASS) TO public;

View File

@@ -5,7 +5,6 @@
--
-- Currently accepted permissions are: 'public', 'private' or 'all'
--
-- DROP FUNCTION IF EXISTS CDB_UserTables(); -- replaced by:
CREATE OR REPLACE FUNCTION CDB_UserTables(perm text DEFAULT 'all')
RETURNS SETOF information_schema.sql_identifier
AS $$
@@ -26,14 +25,17 @@ AS $$
FROM usertables
)
SELECT t FROM perms
WHERE p = CASE WHEN $1 = 'private' THEN false
WHERE (
p = CASE WHEN $1 = 'private' THEN false
WHEN $1 = 'public' THEN true
ELSE not p -- none
END
OR $1 = 'all'
)
AND has_table_privilege('public'||'.'||t, 'SELECT')
;
$$ LANGUAGE 'sql';
-- This is a private function, so only the db owner need privileges
REVOKE ALL ON FUNCTION CDB_UserTables(text) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION CDB_UserTables(text) TO ":DATABASE_USERNAME";
-- This is to migrate from pre-0.2.0 version
-- See http://github.com/CartoDB/cartodb-postgresql/issues/36
GRANT EXECUTE ON FUNCTION CDB_UserTables(text) TO public;

View File

@@ -29,7 +29,20 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
-- Table with cartodb_id field, see
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
select 1 as cartodb_id INTO c.t4;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator
from c.t4;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata WHERE tabname = 'c.t4'::regclass;
----------------------------
-- ALTER TABLE RENAME COLUMN
@@ -48,7 +61,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
select pg_sleep(.1);
alter table c.t3 rename column the_geom_webmercator to webmerc2;
@@ -63,7 +76,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- ALTER TABLE DROP COLUMN
@@ -82,7 +95,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- ALTER TABLE ADD COLUMN
@@ -101,7 +114,7 @@ from c.t3;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata;
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- DROP TABLE
@@ -109,7 +122,7 @@ FROM CDB_TableMetadata;
RESET SESSION AUTHORIZATION;
drop schema c cascade;
select count(*) from CDB_TableMetadata;
select count(*) from CDB_TableMetadata;
DROP USER cartodb_postgresql_unpriv_user;
DROP FUNCTION _CDB_UserQuotaInBytes();

View File

@@ -1,5 +1,6 @@
CREATE EXTENSION postgis;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION plpythonu;
CREATE EXTENSION cartodb;
CREATE FUNCTION public.cdb_invalidate_varnish(table_name text)
RETURNS void AS $$

View File

@@ -146,28 +146,28 @@ DROP TABLE t;
CREATE TABLE t AS SELECT ST_SetSRID(ST_MakePoint(-1,-1),4326) as the_geom
UNION ALL SELECT ST_SetSRID(ST_MakePoint(0,0),3857);
SELECT CDB_CartodbfyTableCheck('t', 'mixed-srid the_geom');
SELECT 'extent',ST_Extent(the_geom) FROM t;
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.2)) FROM t;
DROP TABLE t;
-- table with wrong srid-constrained the_geom values
CREATE TABLE t AS SELECT 'SRID=3857;LINESTRING(222638.981586547 222684.208505545, 111319.490793274 111325.142866385)'::geometry(geometry,3857) as the_geom;
SELECT CDB_CartodbfyTableCheck('t', 'wrong srid-constrained the_geom');
SELECT 'extent',ST_Extent(the_geom),ST_Extent(ST_SnapToGrid(the_geom_webmercator,1)) FROM t;
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.2)),ST_Extent(ST_SnapToGrid(the_geom_webmercator,1)) FROM t;
DROP TABLE t;
-- table with wrong srid-constrained the_geom_webmercator values (and no the_geom!)
CREATE TABLE t AS SELECT 'SRID=4326;LINESTRING(1 1,2 2)'::geometry(geometry,4326) as the_geom_webmercator;
SELECT CDB_CartodbfyTableCheck('t', 'wrong srid-constrained the_geom_webmercator');
-- expect the_geom to be populated from the_geom_webmercator
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.1)) FROM t;
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.2)) FROM t;
DROP TABLE t;
-- table with existing triggered the_geom
CREATE TABLE t AS SELECT 'SRID=4326;LINESTRING(1 1,2 2)'::geometry(geometry) as the_geom;
CREATE TRIGGER update_the_geom_webmercator_trigger BEFORE UPDATE OF the_geom ON t
FOR EACH ROW EXECUTE PROCEDURE public._CDB_update_the_geom_webmercator();
FOR EACH ROW EXECUTE PROCEDURE _CDB_update_the_geom_webmercator();
SELECT CDB_CartodbfyTableCheck('t', 'trigger-protected the_geom');
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.1)) FROM t;
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.2)) FROM t;
DROP TABLE t;
-- table with existing updated_at and created_at fields ot type text
@@ -182,18 +182,40 @@ SELECT CDB_CartodbfyTableCheck('t', 'cartodbfied with view');
DROP VIEW v;
DROP TABLE t;
-- table with existing cartodb_id field ot type text
-- table with existing cartodb_id field of type text
CREATE TABLE t AS SELECT 10::text as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text cartodb_id');
select cartodb_id/2 FROM t;
DROP TABLE t;
-- table with existing cartodb_id field ot type text not casting
-- table with existing cartodb_id field of type text not casting
CREATE TABLE t AS SELECT 'nan' as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'uncasting text cartodb_id');
select cartodb_id,_cartodb_id0 FROM t;
DROP TABLE t;
-- table with existing cartodb_id field of type int4 not sequenced
CREATE TABLE t AS SELECT 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'unsequenced cartodb_id');
select cartodb_id FROM t;
DROP TABLE t;
-- table with existing the_geom and created_at and containing null values
-- Really, a test for surviving an longstanding PostgreSQL bug:
-- http://www.postgresql.org/message-id/20140530143150.GA11051@localhost
CREATE TABLE t (
the_geom geometry(Geometry,4326),
created_at timestamptz,
updated_at timestamptz
);
COPY t (the_geom, created_at, updated_at) FROM stdin;
0106000020E610000001000000010300000001000000050000009EB8244146435BC017B65E062AD343409EB8244146435BC0F51AF6E2708044400B99891683765AC0F51AF6E2708044400B99891683765AC017B65E062AD343409EB8244146435BC017B65E062AD34340 2012-06-06 21:59:08 2013-06-10 20:17:20
0106000020E61000000100000001030000000100000005000000DA7763431A1A5CC0FBCEE869313C3A40DA7763431A1A5CC09C1B8F55BC494440F9F4A9C7993356C09C1B8F55BC494440F9F4A9C7993356C0FBCEE869313C3A40DA7763431A1A5CC0FBCEE869313C3A40 2012-06-06 21:59:08 2013-06-10 20:17:20
\N \N \N
\.
SELECT CDB_CartodbfyTableCheck('t', 'null geom and timestamp values');
DROP TABLE t;
-- TODO: table with existing custom-triggered the_geom
DROP FUNCTION CDB_CartodbfyTableCheck(regclass, text);

View File

@@ -40,5 +40,12 @@ SELECT 1
uncasting text cartodb_id cartodbfied fine
1|nan
DROP TABLE
SELECT 1
unsequenced cartodb_id cartodbfied fine
1
DROP TABLE
CREATE TABLE
null geom and timestamp values cartodbfied fine
DROP TABLE
DROP FUNCTION
DROP FUNCTION

View File

@@ -26,3 +26,38 @@ INSER INTO "my''""t" values ('''','""'';;');
SELECT $qu;oted$ hi $qu;oted$;
$the_param$) as statement )
SELECT '5', row_number() over (), statement FROM q;
WITH q AS ( SELECT CDB_QueryStatements($the_param$
SELECT
1 ; SELECT
2
$the_param$) as statement )
SELECT '6', row_number() over (), statement FROM q;
-- This is an insane input, illegal sql
-- we are really only testing that it does not
-- take forever to process..
-- The actual result is not correct, so if the function
-- ever gets fixed check if it's better
WITH q AS ( SELECT CDB_QueryStatements($the_param$
/a
$b$
$c$d
;
$the_param$) as statement )
SELECT '7', row_number() over (), statement FROM q;
WITH q AS ( SELECT CDB_QueryStatements($the_param$
SELECT $quoted$ hi
$quoted$;
$the_param$) as statement )
SELECT '8', row_number() over (), statement FROM q;

View File

@@ -7,3 +7,13 @@
4|4|SELECT 5
5|1|INSER INTO "my''""t" values ('''','""'';;')
5|2|SELECT $qu;oted$ hi $qu;oted$
6|1|SELECT
1
6|2|SELECT
2
7|1|/a
7|2|b
7|3|c
7|4|d
8|1|SELECT $quoted$ hi
$quoted$

15
test/README Normal file
View File

@@ -0,0 +1,15 @@
Adding tests consists in adding 2 files in this directory: one file
containing the sql code and another containing the expected output.
Example, to add a test for CDB_Something function, you'd add:
- CDB_SomethingTest.sql
- CDB_SomethingTest_expect
To easy the generation of the expected file you can initially omit it,
then run "make -C .. installcheck" from the top-level dir and copy
../results/test/CDB_SomethingTest.out to CDB_SomethingTest_expect chopping
off the first line:
make -C .. installcheck
tail -n +2 ../results/test/CDB_SomethingTest.out > CDB_SomethingTest_expect

9
util/create_upgrade.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
fromver=$1
ver=$2
input=cartodb--${ver}.sql
output=cartodb--${fromver}--${ver}.sql
cat ${input} | grep -v 'duplicated extension$' > ${output}