Compare commits

...

136 Commits

Author SHA1 Message Date
Javier Goizueta
40a163f885 Release 0.13.1 2016-02-01 19:23:38 +01:00
Javier Goizueta
01d432c22c Merge pull request #193 from CartoDB/fix-multiline-fn
Fix function declaration for create_from_unpackaged.sh use
2016-02-01 19:16:37 +01:00
Javier Goizueta
5285943dbf Fix function declaration for create_from_unpackaged.sh use
The script create_from_unpackaged.sh does not support
function declarations where the signature (name and parameter list
of the function, including parentheses) is not on a single line.
2016-02-01 18:56:55 +01:00
Javier Goizueta
8414bdff31 Release 0.13.0 2016-01-29 17:53:51 +01:00
Javier Goizueta
5f96908df4 Merge pull request #185 from CartoDB/overviews
Overviews (new feature)
2016-01-29 17:44:47 +01:00
Javier Goizueta
06dd31f4ad Fix: should be floating point divistion, not integer division 2016-01-29 16:51:52 +01:00
Javier Goizueta
6a11698a16 Merge branch 'overviews' into sql_lang 2016-01-29 16:29:23 +01:00
Javier Goizueta
00bd302f01 Avoid creating GridCluster overviews for non-point datasets 2016-01-29 16:19:35 +01:00
Javier Goizueta
93d4a6ead0 Restrict SECURITY DEFINER to overview registration
And check it is applied only overview tables with valid names
2016-01-28 17:04:06 +01:00
Javier Goizueta
66387c2d44 Make CDB_CreateOverviews a SECURITY DEFINER function
So that it can change the permissions of overview tables
(by updating pg_class) even when executed by non-priviledeged users.
2016-01-28 16:32:40 +01:00
Javier Goizueta
26c95347cd Merge branch 'master' into overviews 2016-01-27 16:56:15 +01:00
Javier Goizueta
6a5e4b0460 Fix overviews tests
The aggregation method for strings has changed
2016-01-27 16:54:30 +01:00
Javier Goizueta
b8d50204dd Avoid aggregation which causes out-of-memory crashes in PostgreSQL
The use of multiple string_agg functions, even if applied to groups
of one single record causes out of memory crashes in PG 9.3.4 for
some (large) tables.
2016-01-27 15:24:04 +01:00
Alejandro Martínez
845ac6dc9a Release 0.12.0 2016-01-27 14:28:56 +01:00
Alejandro Martínez
350f101c3d Merge pull request #190 from CartoDB/remove_schema_triggers
Remove schema triggers
2016-01-27 14:19:21 +01:00
Javier Goizueta
474de01757 Change the overview table naming scheme
The scheme is changed from table_ovN to _vovw_N_table for
lower collision probability.
Also future naming changes will be easier by using the functions
_CDB_OverviewTableDiscriminator, _CDB_OverviewTableName,
_CDB_IsOverviewTableOf, etc.
2016-01-26 13:20:28 +01:00
Javier Goizueta
1ebaeb76ac Overload CDB_Overviews to accept either a single table or an array
The result of CDB_Overviews has been expandend with a base_table column
2016-01-26 10:39:26 +01:00
Alejandro Martínez
eb1222729d Remove ddl triggers specs 2016-01-21 11:46:39 +01:00
Javier Goizueta
7033a8d9ac Fixes for table names that require quotes or which include a schema name
Some cases left unsolved, with FIXME comments
2016-01-13 18:49:27 +01:00
Javier Goizueta
46bc774d38 Fix CDB_Overviews for the case that the table name requires quoting 2016-01-13 18:24:06 +01:00
Javier Goizueta
a9e2d19918 Document CDB_DropOverviews 2016-01-12 16:20:11 +01:00
Javier Goizueta
d352e1c463 Update Overviews tests 2016-01-12 15:36:07 +01:00
Javier Goizueta
5b47c51221 Add function to drop overviews 2016-01-12 15:35:50 +01:00
Javier Goizueta
ebaded0c7a Merge branch 'master' into overviews 2016-01-12 13:34:26 +01:00
Javier Goizueta
ccdf8de59e Enhance documentation, update comments 2016-01-12 12:08:41 +01:00
Javier Goizueta
a2f6cb4c04 Fix documentation 2016-01-12 11:59:57 +01:00
Javier Goizueta
02f386be33 Regard the GridCluster reduction strategy as private
The *strategy* parameteriation will be considered an
implementation detail for the time being.
2016-01-12 11:59:42 +01:00
Javier Goizueta
a7c70fe497 Fix: CDB_ZoomFromScale deviation for lowest zoom levels 2016-01-12 11:46:47 +01:00
Javier Goizueta
0a066e0126 Change the default overview reduction strategy to GridCluster 2016-01-11 15:35:04 +01:00
Javier Goizueta
913640e2dc Preserve the column ordering of the base table in overviews 2016-01-11 15:34:10 +01:00
Javier Goizueta
ef7e613d41 Change CDB_ColumnNames to order columns names as in table 2016-01-11 15:28:27 +01:00
Javier Goizueta
fd7a8cff71 Change regular expression for consistency 2016-01-11 15:27:05 +01:00
Javier Goizueta
6ea63af974 Add function to obtain existing overviews of a table 2016-01-11 14:50:10 +01:00
Javier Goizueta
496f079b1c Copy dataset privileges to overview tables 2016-01-04 18:06:56 +01:00
Javier Goizueta
4580c9cd5c Change the cartodb_ids of aggregated overviews
Instead of arbitrary ids, the id of one of the aggregated records
is used, so that if it is used in the UI to query point
the information of one of the records grouped at the point will be
retrieved.
2016-01-04 10:33:39 +01:00
Javier Goizueta
08828b8b7d Set owner of overlays to the owner of the base table 2015-12-29 15:22:12 +01:00
Javier Goizueta
cecba655eb Preserve aggregated attributes of singleton groups 2015-12-29 14:56:47 +01:00
Javier Goizueta
b34a752172 Generate overviews for all Z levels
Skipping levels produces visually inferior results
2015-12-29 14:56:04 +01:00
Javier Goizueta
8ba9e74c4a Order columns of aggregated overlays as in the base table 2015-12-29 13:38:07 +01:00
Alejandro Martínez
045ede6908 Remove schema_triggers from travis.yml 2015-12-29 10:43:37 +01:00
Alejandro Martínez
cd5c8f2904 Remove outdated references to schema triggers and change triggers 2015-12-29 10:43:18 +01:00
Alejandro Martínez
172ca45ea5 Merge remote-tracking branch 'origin/master' into remove_schema_triggers 2015-12-29 10:41:13 +01:00
Javier Goizueta
6a6a5bc96a Fix Sampling reduction to avoid RandomTids problems
The fixed cases will not be common but do occur in tests.
This is an interim fix which should be reverted if CDB_randomTids changes.
2015-12-28 19:41:14 +01:00
Javier Goizueta
2ff686de27 Clean up: remove spurious comment 2015-12-28 19:30:20 +01:00
Javier Goizueta
07326626b7 More efficient sampling strategy
It is also renamed properly.
2015-12-28 19:28:20 +01:00
Javier Goizueta
4afc427008 Rename Ref. Z strategy function
It's not that *dummy* anymore, so choose a more descriptive name
2015-12-28 17:47:57 +01:00
Paul Norman
2ab059460b Merge pull request #189 from pnorman/fix_travis
Fix test errors on Travis
2015-12-23 10:56:56 -08:00
Alejandro Martínez
2a2a7d534a Merge remote-tracking branch 'origin/master' into remove_schema_triggers 2015-12-23 17:09:41 +01:00
Javier Goizueta
8d1bbc63fa Add overview tests 2015-12-23 16:33:34 +01:00
Javier Goizueta
06ca4f74ee Enable Overviews module in the extension 2015-12-23 16:32:44 +01:00
Javier Goizueta
a8a2c04d71 Remove invalid comment 2015-12-23 14:20:57 +01:00
Javier Goizueta
a5bca7d715 Add function for post-processing new overview tables 2015-12-23 14:17:50 +01:00
Javier Goizueta
552206464e Make strategy function public 2015-12-23 12:50:04 +01:00
Javier Goizueta
2af0b9a57f Add function comments 2015-12-23 12:42:40 +01:00
Javier Goizueta
1b5de84c9a Add missing attribute-aggregationto the point reduction strategy 2015-12-23 12:17:37 +01:00
Paul Norman
3b48acf60c Round extent outputs in test
Travis was reporting rounded results, so this should make the behavior more consistent
2015-12-22 16:34:18 -08:00
Paul Norman
efb319074a Add constraint to QueryTablesTest 2015-12-22 16:21:54 -08:00
Javier Goizueta
c36a5d35c3 Merge branch 'overviews' of github.com:CartoDB/cartodb-postgresql into overviews 2015-12-22 18:02:16 +01:00
Javier Goizueta
5a78ee2896 Optimize the gridded clustering strategy
The internal grid_px parameter is adjusted for best results with default symbol size
2015-12-22 17:59:49 +01:00
Rafa de la Torre
480e2d0979 Merge pull request #187 from CartoDB/overviews-rtorre
Overviews rtorre touches
2015-12-22 17:45:14 +01:00
Javier Goizueta
c8a1ef6f68 Slight optimization of gridded clustering 2015-12-22 15:25:21 +01:00
Paul Norman
ea7c16fbaf Convert some simple functions from plpgsql to sql
SQL is a faster language to call, and these are very simple functions.
2015-12-21 23:59:26 -08:00
Rafa de la Torre
564ab75d2d Use _cdb_estimated_extent instead of ST_Extent
With a 3.8M points table, this was a ~30% gain in my local env.
2015-12-21 18:41:50 +01:00
Rafa de la Torre
5010109c7d Add _cdb_estimated_extent to get the extent from stats 2015-12-21 18:41:45 +01:00
Paul Norman
a9f6e26fed Merge pull request #184 from pnorman/readme_url
Update wiki URL
2015-12-21 08:35:01 -08:00
Rafa de la Torre
e60f73a31b A bit of internal documentation 2015-12-21 13:16:57 +01:00
Javier Goizueta
415a09392f Gridded clustering aggregation strategy for overviews 2015-12-16 17:45:36 +01:00
Javier Goizueta
e5cc9ef0bd Fix: typo 2015-12-16 17:26:17 +01:00
Javier Goizueta
f7857945c1 Change feature density computation algorithm
Now parameterize by the number of levels to traverse and
start with the level that covers the extent of the table
with at least N*N tiles (N=4).
2015-12-16 16:39:38 +01:00
Javier Goizueta
554464e43e Use tile-recursive computation of feature density
This is a more adaptive way of estimating the feature density to
determine the base Z level.
Applying technique from http://javisantana.com/2014/10/22/traversing-quadtree.html
2015-12-16 12:14:37 +01:00
Javier Goizueta
d7c8f3d7e8 Fix: overlay generation was not using the proper scale 2015-12-15 19:13:39 +01:00
Javier Goizueta
4c85d7f3ad Compute the reference Z level for a table 2015-12-15 19:12:48 +01:00
Javier Goizueta
d0e66910a0 Sketch for new Overview-creation functionality 2015-12-15 17:36:27 +01:00
Paul Norman
dcf0b684e2 Update wiki URL 2015-12-08 10:08:17 -08:00
Javier Goizueta
a88bfc51a3 Upgrade version to 0.11.5 2015-11-27 17:03:51 +01:00
Javier Goizueta
21d5ee5813 Merge pull request #178 from CartoDB/disable-log-invalidation-time
Disable log invalidation time
2015-11-27 15:03:46 +01:00
Javier Goizueta
9a58c03ac0 Upgrade version to 0.11.4 2015-11-24 17:00:45 +01:00
Rafa de la Torre
53acee4ddb Merge pull request #180 from CartoDB/174_cartodbfy
174 cartodbfy
2015-11-24 16:38:13 +01:00
Javier Goizueta
68099e780c Merge remote-tracking branch 'origin' into 174_cartodbfy 2015-11-24 16:29:32 +01:00
Rafa de la Torre
9dba6fa7c4 Merge pull request #175 from CartoDB/155-fix-wrong-delimiters
Removes extra d in delimiter 155
2015-11-24 15:58:54 +01:00
Rafa de la Torre
bf711d5c9b Merge pull request #171 from CartoDB/great_circle_generator
Adding function to produce a great circle between two points.
2015-11-24 15:54:47 +01:00
Javier Goizueta
f14fc057e2 Add optional parameter for max. great circle segment length 2015-11-23 17:13:17 +01:00
Javier Goizueta
aa81c6a1ab Add comment to CDB_GreatCircle 2015-11-23 17:07:24 +01:00
Javier Goizueta
1b8ced22a5 Fix name of expected results file 2015-11-23 16:57:34 +01:00
Javier Goizueta
2d13903d50 Cleanup coding style 2015-11-23 16:51:34 +01:00
Javier Goizueta
3bc92d4046 Fix CDB_GreatCircle syntax 2015-11-23 16:40:42 +01:00
Carla
a684c37f6d Merge pull request #151 from CartoDB/cartobdfy-requirements-doc
First version of the cartodbfy requirements
2015-11-23 15:51:09 +01:00
Carla Iriberri
bcfe8d8f3b Adds not null constraint for cartodb_id 2015-11-20 17:24:01 +01:00
Carla Iriberri
333a408199 Add Paul and Rafa feedback 2015-11-20 17:15:37 +01:00
Javier Goizueta
83ac8f4502 Fix: Allow dots in column names to be cartodbfied
This fixes #6144 of cartodb
Note that prior commit ea9503bd32
only added the tests for this, but not the actual fix (oops)
2015-11-20 13:05:15 +01:00
Javier Goizueta
a0ca2288f4 Fix: Cartodbfication failed with existing PK
This fixes #174
When a unique index and a primary key contraint existed for a column
named cartodb_id cartodbfy tried to add another PK constraint
2015-11-20 12:56:52 +01:00
Javier Goizueta
ea9503bd32 Allow dots in column names to be cartodbfied
This fixes #6144 of cartodb
2015-11-20 12:24:46 +01:00
Stuart Lynn
d597f0fe6d removing comments 2015-11-18 15:56:31 +00:00
Stuart Lynn
f43d1cc3c4 Merge branch 'master' into great_circle_generator 2015-11-18 15:36:51 +00:00
Stuart Lynn
f36f1ab536 formatting 2015-11-18 15:30:16 +00:00
Luis Bosque
d39a032024 Revert "Write invalidation duration in postgresql log"
This reverts commit 37160c7b35.
2015-11-17 13:10:19 +01:00
Luis Bosque
4cceb2a21f Revert "Optimize invalidation time logging"
This reverts commit d1d5ed6df3.
2015-11-17 13:10:15 +01:00
Guido Fioravantti
4803abf365 Fix typo in expected 155 2015-11-06 16:32:56 +01:00
Guido Fioravantti
cce63f0eae Adds ::integer cast for USING 155 2015-11-06 16:26:03 +01:00
Guido Fioravantti
7cf0d02935 Fixes expected 155 2015-11-06 15:11:08 +01:00
Guido Fioravantti
545196811f Changes logger level to error 155 2015-11-06 14:41:12 +01:00
Guido Fioravantti
6252907de2 Rises verbosity level before tests for _CDB_create_cartodb_id_column 155 2015-11-05 17:11:27 +01:00
Alejandro Martínez
2a8d467949 Merge remote-tracking branch 'origin/master' into remove_schema_triggers 2015-11-05 14:49:46 +01:00
Alejandro Martínez
8895d9f3af Remove DDL from Makefile 2015-11-04 17:26:38 +01:00
Alejandro Martínez
ef376fd243 Remove schema_triggers 2015-11-04 17:06:54 +01:00
Guido Fioravantti
081ed36aae Fixes NULL max in rec 155 2015-11-02 11:47:14 +01:00
Guido Fioravantti
453b3af872 Removes extra d in delimiter 155 2015-10-30 17:49:27 +01:00
Guido Fioravantti
e99231252e Merge pull request #173 from CartoDB/better-unique-identifiers
Better unique identifiers
2015-10-27 14:19:50 +01:00
Guido Fioravantti
d171afb9f4 Increase version number and update NEWS.md 2015-10-27 14:16:17 +01:00
Guido Fioravantti
fdfbe8e62c Typo fixing 173 2015-10-27 12:11:00 +01:00
Guido Fioravantti
32c729e464 Refactors code 173 2015-10-27 10:33:15 +01:00
Guido Fioravantti
58b2705383 Rename relname to colname in _CDB_Unique_Column_Identifier 2015-10-26 18:35:12 +01:00
Guido Fioravantti
8734608792 Removes unnecessary salt 173 2015-10-26 18:25:48 +01:00
Guido Fioravantti
bb54eb83c1 Drops CDB_Trim_Octets for CDB_Octet_Truncate 2015-10-26 18:01:03 +01:00
Guido Fioravantti
2e701f73ba Reworks _CDB_Octet_Trim 173 2015-10-26 16:35:33 +01:00
Guido Fioravantti
710a3c9672 Removes ability to examine all relations for _CDB_Unique_Column_Identifier 173 2015-10-26 16:17:25 +01:00
Guido Fioravantti
bb18d71995 Adds comment for magic number and constant for maxlen 173 2015-10-26 16:15:55 +01:00
Guido Fioravantti
629214f32f Adds explanation for SCHEMA DEFAULT NULL 173 2015-10-26 15:54:08 +01:00
Guido Fioravantti
270d5b3146 Remove code from deprecated methods 173 2015-10-26 15:50:19 +01:00
Guido Fioravantti
89f5987f53 Fix CDB_HelperTest_expect 173 2015-10-26 12:02:54 +01:00
Guido Fioravantti
cf8c5e5a33 Fixes CDB_HelperTest_expect 173 2015-10-23 12:11:40 +02:00
Guido Fioravantti
b4acfeca22 Fixes Typo in throwing exception 173 2015-10-23 10:38:24 +02:00
Guido Fioravantti
9850399693 Adds test for CDB_Unique_Column_Identifier 173 2015-10-22 19:23:38 +02:00
Guido Fioravantti
aed8671e77 Uses underscore prefix for private tables 173 2015-10-22 19:00:18 +02:00
Guido Fioravantti
58deeb088d Raises error on deprecated methods. 2015-10-22 18:56:50 +02:00
Guido Fioravantti
d14436da6c Renames test file 173 2015-10-22 17:14:13 +02:00
Guido Fioravantti
974f7f9899 Fixes tests 173 2015-10-22 17:08:23 +02:00
Guido Fioravantti
8479c3375b Adds CDB_Unique_Column_Identifier for columns 173 2015-10-22 17:01:47 +02:00
Guido Fioravantti
0d1ba2538b Adds test for new CDB_Helper 173 2015-10-22 16:18:46 +02:00
Guido Fioravantti
5dfe56a664 Moves new CDB_Unique_Identifier and _CDB_Octet_Trim to CDB_Helper.sql file 2015-10-22 12:38:00 +02:00
Guido Fioravantti
5f46ff10e9 Doc change 172 2015-10-21 17:35:13 +02:00
Guido Fioravantti
7c14dd8212 Adds new functions to generate length aware identifiers 172 2015-10-21 17:33:01 +02:00
Stuart Lynn
66249843e8 making some text lowercase 2015-10-14 12:12:12 -04:00
Stuart Lynn
2908c270b3 Fixing typo with symlink 2015-10-14 11:57:36 -04:00
Stuart Lynn
eb475fe55f Adding function to produce a great circle between two points. 2015-10-14 11:36:48 -04:00
Rafa de la Torre
fc0e883c20 First version of the cartodbfy requirements 2015-09-15 11:51:27 +02:00
38 changed files with 3791 additions and 724 deletions

View File

@@ -9,14 +9,6 @@ before_install:
- sudo apt-get update
- 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 -
# Preload schema_triggers module
# NOTE: might change if we make it part of the installcheck instead
- echo "shared_preload_libraries = 'schema_triggers.so'" |
sudo tee -a /etc/postgresql/9.3/main/postgresql.conf &&
sudo service postgresql restart
script:
- make

View File

@@ -1,16 +1,16 @@
# cartodb/Makefile
EXTENSION = cartodb
EXTVERSION = 0.11.2
EXTVERSION = 0.13.1
SED = sed
CDBSCRIPTS = \
scripts-enabled/*.sql \
scripts-available/CDB_SearchPath.sql \
scripts-available/CDB_DDLTriggers.sql \
scripts-available/CDB_ExtensionPost.sql \
scripts-available/CDB_ExtensionUtils.sql \
scripts-available/CDB_Helper.sql \
$(END)
UPGRADABLE = \
@@ -53,6 +53,12 @@ UPGRADABLE = \
0.11.0 \
0.11.1 \
0.11.2 \
0.11.3 \
0.11.4 \
0.11.5 \
0.12.0 \
0.13.0 \
0.13.1 \
$(EXTVERSION)dev \
$(EXTVERSION)next \
$(END)
@@ -74,10 +80,9 @@ DATA_built = \
EXTRA_CLEAN = cartodb_version.sql
DOCS = README.md
REGRESS_NEW = test_ddl_triggers
REGRESS_OLD = $(wildcard test/*.sql)
REGRESS_LEGACY = $(REGRESS_OLD:.sql=)
REGRESS = test_setup $(REGRESS_NEW) $(REGRESS_LEGACY)
REGRESS = test_setup $(REGRESS_LEGACY)
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)

31
NEWS.md
View File

@@ -1,5 +1,32 @@
next (2015-mm-dd)
-----------------
0.13.0 (2016-02-01)
* Fix migration fron unpackaged. [193](https://github.com/CartoDB/cartodb-postgresql/pull/193)
0.13.0 (2016-01-29)
* Add CDB_CreateOverviews, CDB_DropOverviews and CDB_Overviews for vector overviews support. [185](https://github.com/CartoDB/cartodb-postgresql/pull/185)
* Convert some simple functions from plpgsql to sql. [188](https://github.com/CartoDB/cartodb-postgresql/pull/188)
0.12.0 (2016-01-27)
-------------------
* Remove schema_triggers extension dependency, to ensure compatibility with PostgreSQL 9.5. [#190](https://github.com/CartoDB/cartodb-postgresql/pull/190)
* Remove DDL trigger functions (unused by CartoDB).
0.11.5 (2015-11-27)
-------------------
* Disable log invalidation time [#178](https://github.com/CartoDB/cartodb-postgresql/pull/178)
0.11.4 (2015-11-24)
-------------------
* Fix for existing PK cartodb_id problem [#174](https://github.com/CartoDB/cartodb-postgresql/issues/174)
* Add cartodbfication support for column names with embedded points to fix [#6114](https://github.com/CartoDB/cartodb/issues/6114)
* Add CDB_GreatCircle for creating great circle routes between two points [#171](https://github.com/CartoDB/cartodb-postgresql/pull/171)
* Fix to prevent cartodbfication problems [#155](https://github.com/CartoDB/cartodb-postgresql/issues/155)
0.11.3 (2015-10-27)
-------------------
* Added CDB_Helper.sql [#173](https://github.com/CartoDB/cartodb-postgresql/pull/173)
* Added `_CDB_Unique_Identifier` for creating UTF8 aware unique identifiers
* Added `_CDB_Unique_Column_Identifier` for creating UTF8 aware unique identifiers for columns
* Added `_CDB_Octet_Truncate` that truncates text to a certain amount of octets.
0.11.2 (2015-10-19)
-------------------

View File

@@ -6,16 +6,13 @@ cartodb-postgresql
PostgreSQL extension for CartoDB
See https://github.com/CartoDB/cartodb/wiki/CartoDB-PostgreSQL-extension
See [the cartodb-postgresql wiki](https://github.com/CartoDB/cartodb-postgresql/wiki).
Dependencies
------------
* PostgreSQL 9.3+ (with plpythonu extension and xml support)
* [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
-------
@@ -31,10 +28,6 @@ Test installation
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``
to the ``shared_preload_libraries`` setting in postgresql.conf !
NOTE: you need to run the installcheck as a superuser, use PGUSER
env variable if needed, like: PGUSER=postgres make installcheck
@@ -47,7 +40,6 @@ In a database that needs to be turned into a "cartodb" user database, run:
```sql
CREATE EXTENSION postgis;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION cartodb;
```
@@ -63,7 +55,6 @@ be in the "cartodb" schema.
```sql
CREATE EXTENSION postgis FROM unpackaged;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION cartodb FROM unpackaged;
```

View File

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

16
doc/CDB_GreatCircle.md Normal file
View File

@@ -0,0 +1,16 @@
Based on Paul Ramsey's [blog post](http://blog.cartodb.com/jets-and-datelines/).
#### Using the function
Creates a great circle line.
```sql
SELECT CDB_GreatCircle(start_point, end_point) FROM table_name
-- Results a line reprsenting the great circle between the two points
```
#### Arguments
CDB_GreatCircle(start_point, end_point)
* **start_point** ST_Point indicating the start of the line.
* **end_point** ST_point indicating the end of the line.

105
doc/CDB_Overviews.md Normal file
View File

@@ -0,0 +1,105 @@
Overviews are tables that represent a *reduced* version of a dataset intended
for efficient rendering at certain zoom levels while preserving the
general visual appearance of the complete dataset.
The *reduction* consists in a fewer number of records
(while each overview record may represent an aggregation of multiple records)
and/or simplified record geometries.
Overviews are created through the `CDB_CreateOverviews`.
The statement timeout may need to be adjusted before using this function,
as overview creation for large tables is a time-consuming operation.
The `CDB_Overviews` function can be used determine what overview tables
exist for a given dataset table and which zoom levels correspond to it.
The `CDB_DropOverviews` remove a dataset's existing overviews.
### CDB_CreateOverviews
Create overviews for vector dataset.
#### Using the function
The table for which overviews will be generated should be
a Cartodbfied dataset with vector geometry.
```sql
SELECT CDB_CreateOverviews('table_name');
--- Generates overview tables for the dataset
```
#### Arguments
CDB_CreateOverviews(table_name, ref_z_strategy, reduction_strategy)
* **table_name** regclass, table for which overviews will be generated
* **ref_z_strategy** regproc, optional function that provides
the Z-scale strategy.
It returns the base Z level for the dataset.
It should have these arguments:
- **table_name** regclass, table to compute the reference Z scale for
* **reduction_strategy** regproc, optional function that provides
the reduction strategy to generate an overview table from a table
for a smaller scale (higher Z number).
It returns the name of the generated table.
It should have these arguments:
- **base_table_name** regclass, base table to be reduced.
- **base_z** integer, base Z level assigned to the base table.
- **overview_z** integer, Z level for which to generate the overview.
### CDB_Overviews
Obtain overview metadata for a given table (existing overviews).
The returned relation will be empty if the table has no overviews.
The function can be applied to a single table:
```sql
SELECT CDB_Overviews('table_name');
--- Return existing overview Z levels and corresponding tables
```
Or to multiple tables passed as an array; this can be used
to obtain the overviews that can be applied to a query by
combining it with `CDB_QueryTablesText`:
```sql
SELECT CDB_Overviews(CDB_QueryTablesText('SELECT * FROM table1, table2'));
--- Return existing overview Z levels and corresponding tables
```
The result of `CDB_Overviews` has three columns:
| base_table | z | overview_table |
|------------+---+----------------|
| table1 | 1 | table1_ov1 |
| table1 | 2 | table1_ov2 |
| table1 | 4 | table1_ov4 |
| table2 | 1 | table1_ov1 |
| table2 | 2 | table1_ov2 |
#### Arguments
CDB_Overviews(table_name)
* **table_name** regclass, oid of table to obtain existing overviews for
CDB_Overviews(table_names)
* **table_names** regclass[], array of table oids
### CDB_DropOverviews
Remove the overviews of a table, if present.
```sql
SELECT CDB_DropOverviews('table_name');
```
#### Arguments
CDB_Overviews(table_name)
* **table_name** regclass, table for which to drop existing overviews.

View File

@@ -20,29 +20,4 @@ The CartoDB PostgreSQL extension is a module to load into each CartoDB user data
# Checks
No user other than the superuser should be allowed to change `statement_timeout` for the session (SET statement_timeout disallowed).
User tables need to match certain structure criteria (See [[CartoDB-user-table]]) so the extension should provide a mean to enforce such structure everytime an attempt to change structure is encountered.
# Events
The events we want some function to be called upon are:
| event | arguments to handler function | function duty | OK* |
|------------------------|--------------------------------------|----------------------------------|-----|
| SET variable | name of variable | forbid changing some vars | |
| RENAME table | old and new name + oid of the table | flush cache | |
| ADD/DROP/ALTER column | oid of the table | flush cache, cartodbfy, upd meta | Y |
| DISABLE/DROP trigger | oid of table, name of trigger | cartodbfy or forbid | |
| DROP table | oid of the table | flush cache and metadata | Y |
| CREATE table | oid of the table | cartodby, upd metadata | Y |
| GRANT | oid of table, privilege, role | flush cache, upd metadata |
| REVOKE | oid of table, privilege, role | flush cache, upd metadata |
* event available by installing https://github.com/CartoDB/pg_schema_triggers
At this stage we don't need more than this, but the number of events and the number of arguments passed to the handler function may expand in the future, so the extension should be written in a way to easily allow that.
Some of the handler will need to act _after_ the statement is completed (CREATE TABLE, for example).

View File

@@ -0,0 +1,59 @@
Introduction
============
This document aims at describing what cartodbfy is and what its formal requirements are, with the following goals in mind:
- clarify what are the expectations of the "cartodbfycation process".
- define an important part of what should be a stable, public API
- allow for better testing, which should in turn...
- ...ease modifications and increase quality of the code
What is the cartodbfycation
===========================
The cartodbfycation is the process of converting an arbitrary postgres table into a valid CartoDB table, and register it in the system so that it can be used in the CartoDB editor and platform to generate maps and analysis.
Valid CartoDB tables
====================
A valid CartoDB table shall meet the following conditions:
- Have a ``cartodb_id`` integer column as primary key with a sequence as default value
- Have a ``the_geom`` column of type ``Geometry`` with SRID 4326
- Have a ``the_geom_webmercator`` column of type ``Geometry`` with SRID 3857
- The columns ``the_geom`` and ``the_geom_webmercator`` shall be in sync
Additionally, a CartoDB table can contain other columns.
High level requirements
=======================
Here is a list of high level requirments for the public function ``CDB_CartodbfyTable()``:
- A call to ``CDB_CartodbfyTable()`` shall modify/rewrite the table and produce a valid CartoDB table with the same name.
- A call to ``CDB_CartodbfyTable()`` shall cause the registration of the table into the platform
- It shall be idempotent, meaning that successive calls to ``CDB_CartodbfyTable()`` shall not produce any visible effect in the system.
- If there's a column containing a geometry, it shall be used to generate ``the_geom`` and the ``the_geom_webmercator`` columns.
- Exporting and re-importing the same table in CartoDB shall produce equivalent tables, with the same features associated to the same ``cartodb_id``'s.
Note that there should be only one feature per row in the source table. If there's more than one, then which one is used for ``the_geom`` and ``the_geom_webmercator`` fields is not determined.
Low-level requirements
======================
- If the original table contains a valid (unique and not null) ``cartodb_id`` column, it shall be used
- If the original table contains a ``the_geom`` column or a ``the_geom_webmercator`` column in the expected projection (EPSG 4326 and EPSG 3857, respectively) they shall be used.
- A modification of a cartodbfy'ed table shall insert or update a row in ``CDB_TableMetadata``
- A cartodbfy'ed table shall have a ``btree`` index on ``cartodb_id``
- A cartodbfy'ed table shall have ``gist`` indices on ``the_geom`` and ``the_geom_webmercator``
- Cartodbfy shall deal with text columns for imports, regarding CartoDB columns

View File

@@ -1,199 +0,0 @@
\set VERBOSITY terse
-- Set user quota to infinite
SELECT CDB_SetUserQuotaInBytes(0);
cdb_setuserquotainbytes
-------------------------
0
(1 row)
-- Enable ddl triggers
SELECT cartodb.cdb_enable_ddl_hooks();
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
cdb_enable_ddl_hooks
----------------------
(1 row)
create schema c;
SELECT CDB_SetUserQuotaInBytes('c', 0);
cdb_setuserquotainbytes
-------------------------
0
(1 row)
DROP USER IF EXISTS cartodb_postgresql_unpriv_user;
NOTICE: role "cartodb_postgresql_unpriv_user" does not exist, skipping
CREATE USER cartodb_postgresql_unpriv_user;
GRANT ALL ON SCHEMA c to cartodb_postgresql_unpriv_user;
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
--SELECT session_user, current_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
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
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | age
---------+-----
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;
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 "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: 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
RESET SESSION AUTHORIZATION;
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
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
(1 row)
alter table c.t3 rename column the_geom_webmercator to webmerc;
NOTICE: column "the_geom_webmercator" of relation "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
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
(1 row)
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
(1 row)
alter table c.t3 rename column the_geom_webmercator to webmerc2;
NOTICE: column "the_geom_webmercator" of relation "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
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
(1 row)
----------------------------
-- ALTER TABLE DROP COLUMN
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
(1 row)
alter table c.t3 drop column the_geom_webmercator;
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
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
(1 row)
----------------------------
-- ALTER TABLE ADD COLUMN
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
(1 row)
alter table c.t3 add column id2 int;
NOTICE: cdb_invalidate_varnish(c.t3) called
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
tabname | agecs
---------+-------
c.t3 | 0
(1 row)
----------------------------
-- DROP TABLE
----------------------------
RESET SESSION AUTHORIZATION;
drop schema c cascade;
NOTICE: drop cascades to 3 other objects
select count(*) from CDB_TableMetadata;
count
-------
0
(1 row)
DROP OWNED BY cartodb_postgresql_unpriv_user;
DROP ROLE cartodb_postgresql_unpriv_user;
DROP FUNCTION _CDB_UserQuotaInBytes();

View File

@@ -1,5 +1,4 @@
CREATE EXTENSION postgis;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION plpythonu;
CREATE EXTENSION cartodb;
CREATE FUNCTION public.cdb_invalidate_varnish(table_name text)

View File

@@ -1,4 +1,5 @@
-- Depends on:
-- * CDB_Helper.sql
-- * CDB_ExtensionUtils.sql
-- * CDB_TransformToWebmercator.sql
-- * CDB_TableMetadata.sql
@@ -151,12 +152,12 @@ BEGIN
-- Copy existing values to new field
-- 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 := Format('ALTER TABLE %s ALTER cartodb_id TYPE int USING %I', reloid::text, new_name);
sql := Format('ALTER TABLE %s ALTER cartodb_id TYPE int USING %I::integer', reloid::text, new_name);
RAISE DEBUG 'Running %', sql;
EXECUTE sql;
-- Find max value
sql := Format('SELECT max(cartodb_id) FROM %s', reloid::text);
sql := Format('SELECT coalesce(max(cartodb_id), 0) as max FROM %s', reloid::text);
RAISE DEBUG 'Running %', sql;
EXECUTE sql INTO rec;
@@ -165,7 +166,7 @@ BEGIN
AS seq INTO rec2;
-- Reset sequence name
sql := Format('ALTER SEQUENCE %s RESTART WITH %d', rec2.seq::text, rec.max + 1);
sql := Format('ALTER SEQUENCE %s RESTART WITH %s', rec2.seq::text, rec.max + 1);
RAISE DEBUG 'Running %', sql;
EXECUTE sql;
@@ -427,8 +428,9 @@ END;
$$ LANGUAGE 'plpgsql';
-- Find a unique relation name in the given schema, starting from the
-- template given. If the template is already unique, just return it;
-- DEPRECATED: Use _CDB_Unique_Identifier since it's UTF8 Safe and length
-- aware. Find a unique relation name in the given schema, starting from the
-- template given. If the template is already unique, just return it;
-- otherwise, append an increasing integer until you find a unique variant.
CREATE OR REPLACE FUNCTION _CDB_Unique_Relation_Name(schemaname TEXT, relationname TEXT)
RETURNS TEXT
@@ -439,36 +441,15 @@ DECLARE
newrelname TEXT;
BEGIN
i := 0;
newrelname := relationname;
LOOP
RAISE EXCEPTION '_CDB_Unique_Relation_Name is DEPRECATED. Use _CDB_Unique_Identifier(prefix TEXT, relname TEXT, suffix TEXT, schema TEXT DEFAULT NULL)';
SELECT c.relname, n.nspname
INTO rec
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = newrelname
AND n.nspname = schemaname;
IF NOT FOUND THEN
RETURN newrelname;
END IF;
i := i + 1;
newrelname := relationname || '_' || i;
IF i > 100 THEN
PERFORM _CDB_Error('looping too far', '_CDB_Unique_Relation_Name');
END IF;
END LOOP;
END;
$$ LANGUAGE 'plpgsql';
-- Find a unique column name in the given relation, starting from the
-- column name given. If the column name is already unique, just return it;
-- DEPRECATED: Use _CDB_Unique_Column_Identifier since it's UTF8 Safe and length
-- aware. Find a unique column name in the given relation, starting from the
-- column name given. If the column name is already unique, just return it;
-- otherwise, append an increasing integer until you find a unique variant.
CREATE OR REPLACE FUNCTION _CDB_Unique_Column_Name(reloid REGCLASS, columnname TEXT)
RETURNS TEXT
@@ -479,32 +460,8 @@ DECLARE
newcolname TEXT;
BEGIN
i := 0;
newcolname := columnname;
LOOP
RAISE EXCEPTION '_CDB_Unique_Column_Name is DEPRECATED. Use _CDB_Unique_Column_Identifier(prefix TEXT, relname TEXT, suffix TEXT, reloid REGCLASS DEFAULT NULL)';
SELECT a.attname
INTO rec
FROM pg_class c
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE NOT a.attisdropped
AND a.attnum > 0
AND c.oid = reloid
AND a.attname = newcolname;
IF NOT FOUND THEN
RETURN newcolname;
END IF;
i := i + 1;
newcolname := columnname || '_' || i;
IF i > 100 THEN
PERFORM _CDB_Error('looping too far', '_CDB_Unique_Column_Name');
END IF;
END LOOP;
END;
$$ LANGUAGE 'plpgsql';
@@ -547,7 +504,7 @@ BEGIN
IF rec.atttypid IN (20,21,23) THEN
-- And it's a unique primary key! Done!
IF rec.indisprimary AND rec.indisunique AND rec.attnotnull THEN
IF (rec.indisprimary OR rec.indisunique) AND rec.attnotnull THEN
RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('found good ''%s''', const.pkey);
RETURN true;
@@ -589,7 +546,7 @@ BEGIN
PERFORM _CDB_SQL(
Format('ALTER TABLE %s RENAME COLUMN %s TO %I',
reloid::text, rec.attname,
_CDB_Unique_Column_Name(reloid, const.pkey)),
cartodb._CDB_Unique_Column_Identifier(NULL, const.pkey, NULL, reloid)),
'_CDB_Has_Usable_Primary_ID');
END IF;
@@ -606,7 +563,7 @@ BEGIN
PERFORM _CDB_SQL(
Format('ALTER TABLE %s RENAME COLUMN %s TO %I',
reloid::text, rec.attname, _CDB_Unique_Column_Name(reloid, const.pkey)),
reloid::text, rec.attname, cartodb._CDB_Unique_Column_Identifier(NULL, const.pkey, NULL, reloid)),
'_CDB_Has_Usable_Primary_ID');
END IF;
@@ -772,7 +729,7 @@ BEGIN
WHEN others THEN
IF SQLERRM = 'parse error - invalid geometry' THEN
text_geom_column := false;
str := _CDB_Unique_Column_Name(reloid, r1.attname);
str := cartodb._CDB_Unique_Column_Identifier(NULL, r1.attname, NULL, reloid);
sql := Format('ALTER TABLE %s RENAME COLUMN %s TO %I', reloid::text, r1.attname, str);
PERFORM _CDB_SQL(sql,'_CDB_Has_Usable_Geom');
RAISE DEBUG 'CDB(_CDB_Has_Usable_Geom): %',
@@ -784,7 +741,7 @@ BEGIN
-- Just change its name so we can write a new column into that name.
ELSE
str := _CDB_Unique_Column_Name(reloid, r1.attname);
str := cartodb._CDB_Unique_Column_Identifier(NULL, r1.attname, NULL, reloid);
sql := Format('ALTER TABLE %s RENAME COLUMN %s TO %I', reloid::text, r1.attname, str);
PERFORM _CDB_SQL(sql,'_CDB_Has_Usable_Geom');
RAISE DEBUG 'CDB(_CDB_Has_Usable_Geom): %',
@@ -854,8 +811,7 @@ DECLARE
destname TEXT;
destseq TEXT;
destseqmax INTEGER;
salt TEXT := md5(random()::text || now());
copyname TEXT;
column_name_sql TEXT;
@@ -961,19 +917,18 @@ BEGIN
-- Put the primary key sequence in the right schema
-- If the new table is not moving, better ensure the sequence name
-- is unique
destseq := relname || '_' || const.pkey || '_seq';
destseq := _CDB_Unique_Relation_Name(destschema, destseq);
destseq := cartodb._CDB_Unique_Identifier(NULL, relname, '_' || const.pkey || '_seq', destschema);
destseq := Format('%I.%I', destschema, destseq);
PERFORM _CDB_SQL(Format('CREATE SEQUENCE %s', destseq), '_CDB_Rewrite_Table');
-- Salt a temporary table name if we are re-writing in place
-- Temporary table name if we are re-writing in place
-- Note copyname is already escaped and safe to use as identifier
IF destschema = relschema THEN
copyname := Format('%I.%I', destschema, Format('%s_%s', destname, salt));
copyname := Format('%I.%I', destschema, cartodb._CDB_Unique_Identifier(NULL, destname, NULL), destschema);
ELSE
copyname := Format('%I.%I', destschema, destname);
END IF;
-- Start building the SQL!
sql := Format('CREATE TABLE %s AS SELECT ', copyname);
@@ -1113,8 +1068,8 @@ BEGIN
-- Add now add all the rest of the columns
-- by selecting their names into an array and
-- joining the array with a comma
SELECT
',' || array_to_string(array_agg(a.attname),',') AS column_name_sql,
SELECT
',' || array_to_string(array_agg(Format('%I',a.attname)),',') AS column_name_sql,
Count(*) AS count
INTO rec
FROM pg_class c

View File

@@ -8,8 +8,9 @@ AS $$
WHERE table_name = _tn.relname
AND table_schema = _sn.nspname
AND _tn.oid = $1::oid
AND _sn.oid = _tn.relnamespace;
AND _sn.oid = _tn.relnamespace
ORDER BY ordinal_position;
$$ LANGUAGE SQL;
-- This is to migrate from pre-0.2.0 version

View File

@@ -1,214 +0,0 @@
-- Table creation
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_create_table ()
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
DECLARE
event_info RECORD;
rel RECORD;
newtable REGCLASS;
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;
SELECT c.relname, c.relnamespace, c.relkind, n.nspname
FROM pg_class c
JOIN pg_namespace n
ON c.relnamespace = n.oid
WHERE c.oid = event_info.relation
INTO rel;
RAISE DEBUG 'Relation % of kind % created in table % namespace % (oid %)',
event_info.relation, rel.relkind, rel.relname, rel.nspname, rel.relnamespace;
-- We don't want to react to alters triggered by superuser,
IF current_setting('is_superuser') = 'on' THEN
RAISE DEBUG 'no ddl trigger for superuser';
RETURN;
END IF;
PERFORM cartodb.cdb_disable_ddl_hooks();
-- CDB_CartodbfyTable must not create tables, or infinite loop will happen
newtable := cartodb.CDB_CartodbfyTable(rel.nspname, 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?)
INSERT INTO cartodb.CDB_TableMetadata(tabname, updated_at)
VALUES (newtable, now());
END; $$;
-- }
-- Table drop
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_drop_table ()
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
DECLARE
event_info RECORD;
BEGIN
event_info := schema_triggers.get_relation_drop_eventinfo();
-- We're only interested in real relations
IF (event_info.old).relkind != 'r' THEN RETURN; END IF;
RAISE DEBUG 'Relation % of kind % dropped from namespace oid %',
event_info.old_relation_oid, (event_info.old).relkind, (event_info.old).relnamespace;
-- delete record from CDB_TableMetadata (should invalidate varnish)
DELETE FROM cartodb.CDB_TableMetadata WHERE tabname = event_info.old_relation_oid;
END; $$;
-- }
-- Column alter
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_alter_column ()
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
DECLARE
event_info RECORD;
rel RECORD;
newtable REGCLASS;
BEGIN
event_info := schema_triggers.get_column_alter_eventinfo();
SELECT c.relname, c.relnamespace, c.relkind, n.nspname
FROM pg_class c
JOIN pg_namespace n
ON c.relnamespace = n.oid
WHERE c.oid = event_info.relation
INTO rel;
RAISE DEBUG 'Column % altered by % (superuser? %) in relation % of kind %',
(event_info.old).attname, current_user, current_setting('is_superuser'), rel.relname, rel.relkind;
-- We're only interested in real relations
IF rel.relkind != 'r' THEN RETURN; END IF;
-- We don't want to react to alters triggered by superuser,
IF current_setting('is_superuser') = 'on' THEN
RAISE DEBUG 'no ddl trigger for superuser';
RETURN;
END IF;
PERFORM cartodb.cdb_disable_ddl_hooks();
newtable := cartodb.CDB_CartodbfyTable(rel.nspname, event_info.relation);
PERFORM cartodb.cdb_enable_ddl_hooks();
-- update CDB_TableMetadata.updated_at (should invalidate varnish)
UPDATE cartodb.CDB_TableMetadata SET updated_at = NOW(), tabname = newtable
WHERE tabname = event_info.relation;
END; $$;
-- }
-- Column drop
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_drop_column ()
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
DECLARE
event_info RECORD;
rel RECORD;
newtable REGCLASS;
BEGIN
event_info := schema_triggers.get_column_drop_eventinfo();
SELECT c.relname, c.relnamespace, c.relkind, n.nspname
FROM pg_class c
JOIN pg_namespace n
ON c.relnamespace = n.oid
WHERE c.oid = event_info.relation
INTO rel;
RAISE DEBUG 'Column % drop by % (superuser? %) in relation % of kind %',
(event_info.old).attname, current_user, current_setting('is_superuser'), rel.relname, rel.relkind;
-- We're only interested in real relations
IF rel.relkind != 'r' THEN RETURN; END IF;
-- We don't want to react to drops triggered by superuser,
IF current_setting('is_superuser') = 'on' THEN
RAISE DEBUG 'no ddl trigger for superuser';
RETURN;
END IF;
PERFORM cartodb.cdb_disable_ddl_hooks();
newtable := cartodb.CDB_CartodbfyTable(rel.nspname, event_info.relation);
PERFORM cartodb.cdb_enable_ddl_hooks();
-- update CDB_TableMetadata.updated_at (should invalidate varnish)
UPDATE cartodb.CDB_TableMetadata SET updated_at = NOW(), tabname = newtable
WHERE tabname = event_info.relation;
END; $$;
-- }
-- Column add
-- {
CREATE OR REPLACE FUNCTION cartodb.cdb_handle_add_column ()
RETURNS event_trigger SECURITY DEFINER LANGUAGE plpgsql AS $$
DECLARE
event_info RECORD;
rel RECORD;
BEGIN
event_info := schema_triggers.get_column_add_eventinfo();
SELECT c.relname, c.relnamespace, c.relkind, n.nspname
FROM pg_class c
JOIN pg_namespace n
ON c.relnamespace = n.oid
WHERE c.oid = event_info.relation
INTO rel;
RAISE DEBUG 'Column % added by % (superuser? %) in relation % of kind %',
(event_info.new).attname, current_user, current_setting('is_superuser'), rel.relname, rel.relkind;
-- We're only interested in real relations
IF rel.relkind != 'r' THEN RETURN; END IF;
-- We don't want to react to drops triggered by superuser,
IF current_setting('is_superuser') = 'on' THEN
RAISE DEBUG 'no ddl trigger for superuser';
RETURN;
END IF;
-- update CDB_TableMetadata.updated_at (should invalidate varnish)
UPDATE cartodb.CDB_TableMetadata SET updated_at = NOW()
WHERE tabname = event_info.relation;
END; $$;
-- }
CREATE OR REPLACE FUNCTION cartodb.cdb_disable_ddl_hooks() returns void AS $$
DROP EVENT TRIGGER IF EXISTS cdb_on_relation_create;
DROP EVENT TRIGGER IF EXISTS cdb_on_relation_drop;
DROP EVENT TRIGGER IF EXISTS cdb_on_alter_column;
DROP EVENT TRIGGER IF EXISTS cdb_on_drop_column;
DROP EVENT TRIGGER IF EXISTS cdb_on_add_column;
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION cartodb.cdb_enable_ddl_hooks() returns void AS $$
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
ON "relation_drop" EXECUTE PROCEDURE cartodb.cdb_handle_drop_table();
CREATE EVENT TRIGGER cdb_on_alter_column
ON "column_alter" EXECUTE PROCEDURE cartodb.cdb_handle_alter_column();
CREATE EVENT TRIGGER cdb_on_drop_column
ON "column_drop" EXECUTE PROCEDURE cartodb.cdb_handle_drop_column();
CREATE EVENT TRIGGER cdb_on_add_column
ON "column_add" EXECUTE PROCEDURE cartodb.cdb_handle_add_column();
$$ LANGUAGE sql;
-- Do not enable hooks by default
--SELECT cartodb.cdb_enable_ddl_hooks();

View File

@@ -0,0 +1,26 @@
-- Great circle point-to-point routes, based on:
-- http://blog.cartodb.com/jets-and-datelines/
--
CREATE OR REPLACE FUNCTION CDB_GreatCircle(start_point geometry, end_point geometry, max_segment_length NUMERIC DEFAULT 100000)
RETURNS geometry AS $$
DECLARE
line geometry;
BEGIN
line = ST_Segmentize(
ST_Makeline(
start_point,
end_point
)::geography,
max_segment_length
)::geometry;
IF ST_XMax(line) - ST_XMin(line) > 180 THEN
line = ST_Difference(
ST_Shift_Longitude(line),
ST_Buffer(ST_GeomFromText('LINESTRING(180 90, 180 -90)', 4326), 0.00001)
);
END IF;
RETURN line;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -0,0 +1,156 @@
-- UTF8 safe and length aware. Find a unique identifier with a given prefix
-- and/or suffix and withing a schema. If a schema is not specified, the identifier
-- is guaranteed to be unique for all schemas.
CREATE OR REPLACE FUNCTION cartodb._CDB_Unique_Identifier(prefix TEXT, relname TEXT, suffix TEXT, schema TEXT DEFAULT NULL)
RETURNS TEXT
AS $$
DECLARE
maxlen CONSTANT INTEGER := 63;
rec RECORD;
usedspace INTEGER;
ident TEXT;
origident TEXT;
candrelname TEXT;
i INTEGER;
BEGIN
-- Accounts for the _XX incremental suffix in case the identifier is taken
usedspace := 3;
usedspace := usedspace + coalesce(octet_length(prefix), 0);
usedspace := usedspace + coalesce(octet_length(suffix), 0);
candrelname := _CDB_Octet_Truncate(relname, maxlen - usedspace);
IF candrelname = '' THEN
PERFORM _CDB_Error('prefixes are to long to generate a valid identifier', '_CDB_Unique_Identifier');
END IF;
ident := coalesce(prefix, '') || candrelname || coalesce(suffix, '');
i := 0;
origident := ident;
WHILE i < 100 LOOP
IF schema IS NOT NULL THEN
SELECT c.relname, n.nspname
INTO rec
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = ident
AND n.nspname = schema;
ELSE
SELECT c.relname, n.nspname
INTO rec
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = ident;
END IF;
IF NOT FOUND THEN
RETURN ident;
END IF;
ident := origident || '_' || i;
i := i + 1;
END LOOP;
PERFORM _CDB_Error('looping too far', '_CDB_Unique_Identifier');
END;
$$ LANGUAGE 'plpgsql';
-- UTF8 safe and length aware. Find a unique identifier for a column with a given prefix
-- and/or suffix based on colname and within a relation specified via reloid.
CREATE OR REPLACE FUNCTION cartodb._CDB_Unique_Column_Identifier(prefix TEXT, colname TEXT, suffix TEXT, reloid REGCLASS)
RETURNS TEXT
AS $$
DECLARE
maxlen CONSTANT INTEGER := 63;
rec RECORD;
candcolname TEXT;
usedspace INTEGER;
ident TEXT;
origident TEXT;
i INTEGER;
BEGIN
-- Accounts for the _XX incremental suffix in case the identifier is taken
usedspace := 3;
usedspace := usedspace + coalesce(octet_length(prefix), 0);
usedspace := usedspace + coalesce(octet_length(suffix), 0);
candcolname := _CDB_Octet_Truncate(colname, maxlen - usedspace);
IF candcolname = '' THEN
PERFORM _CDB_Error('prefixes are to long to generate a valid identifier', '_CDB_Unique_Column_Identifier');
END IF;
ident := coalesce(prefix, '') || candcolname || coalesce(suffix, '');
i := 0;
origident := ident;
WHILE i < 100 LOOP
SELECT a.attname
INTO rec
FROM pg_class c
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE NOT a.attisdropped
AND a.attnum > 0
AND c.oid = reloid
AND a.attname = ident;
IF NOT FOUND THEN
RETURN ident;
END IF;
ident := origident || '_' || i;
i := i + 1;
END LOOP;
PERFORM _CDB_Error('looping too far', '_CDB_Unique_Column_Identifier');
END;
$$ LANGUAGE 'plpgsql';
-- Truncates a given string to a max_octets octets taking care
-- not to leave characters in half. UTF8 safe.
CREATE OR REPLACE FUNCTION cartodb._CDB_Octet_Truncate(string TEXT, max_octets INTEGER)
RETURNS TEXT
AS $$
DECLARE
extcharlen CONSTANT INTEGER := octet_length('ñ');
expected INTEGER;
examined INTEGER;
strlen INTEGER;
i INTEGER;
BEGIN
IF max_octets <= 0 THEN
RETURN '';
ELSIF max_octets >= octet_length(string) THEN
RETURN string;
END IF;
strlen := char_length(string);
expected := char_length(string);
examined := octet_length(string);
IF expected = examined THEN
RETURN left(string, max_octets);
END IF;
i := max_octets / extcharlen;
WHILE octet_length(left(string, i)) <= max_octets LOOP
i := i + 1;
END LOOP;
RETURN left(string, (i - 1));
END;
$$ LANGUAGE 'plpgsql';

View File

@@ -8,16 +8,12 @@
--
CREATE OR REPLACE FUNCTION CDB_LatLng (lat NUMERIC, lng NUMERIC) RETURNS geometry as $$
BEGIN
-- this function is silly
RETURN ST_SetSRID(ST_MakePoint(lng,lat),4326);
END;
$$ language plpgsql IMMUTABLE;
SELECT ST_SetSRID(ST_MakePoint(lng,lat),4326);
$$ language SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION CDB_LatLng (lat FLOAT8, lng FLOAT8) RETURNS geometry as $$
BEGIN
-- this function is silly
RETURN ST_SetSRID(ST_MakePoint(lng,lat),4326);
END;
$$ language plpgsql IMMUTABLE;
SELECT ST_SetSRID(ST_MakePoint(lng,lat),4326);
$$ language SQL IMMUTABLE;

View File

@@ -0,0 +1,683 @@
-- security definer
-- Pattern that can be used to detect overview tables and Extract
-- the intended zoom level from the table name.
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_OverviewTableDiscriminator()
RETURNS TEXT
AS $$
BEGIN
RETURN '\A_vovw_(\d+)_';
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- substring(tablename from _CDB_OverviewTableDiscriminator())
-- Pattern matched by the overview tables of a given base table name.
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_OverviewTablePattern(base_table TEXT)
RETURNS TEXT
AS $$
BEGIN
RETURN _CDB_OverviewTableDiscriminator() || base_table;
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- tablename SIMILAR TO _CDB_OverviewTablePattern(base_table)
-- Name of an overview table, given the base table name and the Z level
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_OverviewTableName(base_table TEXT, z INTEGER)
RETURNS TEXT
AS $$
BEGIN
RETURN '_vovw_' || z::text || '_' || base_table;
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Condition to check if a tabla is an overview table of some base table
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_IsOverviewTableOf(base_table TEXT, otable TEXT)
RETURNS BOOLEAN
AS $$
BEGIN
RETURN otable SIMILAR TO _CDB_OverviewTablePattern(base_table);
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Extract the Z level from an overview table name
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_OverviewTableZ(otable TEXT)
RETURNS INTEGER
AS $$
BEGIN
RETURN substring(otable from _CDB_OverviewTableDiscriminator())::integer;
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Name of the base table corresponding to an overview table
-- Scope: private.
CREATE OR REPLACE FUNCTION _CDB_OverviewBaseTableName(overview_table TEXT)
RETURNS TEXT
AS $$
BEGIN
IF _CDB_OverviewTableZ(overview_table) IS NULL THEN
RETURN overview_table;
ELSE
RETURN regexp_replace(overview_table, _CDB_OverviewTableDiscriminator(), '');
END IF;
END;
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Remove a dataset's existing overview tables.
-- Scope: public
-- Parameters:
-- reloid: oid of the table.
CREATE OR REPLACE FUNCTION CDB_DropOverviews(reloid REGCLASS)
RETURNS void
AS $$
DECLARE
row record;
BEGIN
FOR row IN
SELECT * FROM CDB_Overviews(reloid)
LOOP
EXECUTE Format('DROP TABLE %s;', row.overview_table);
RAISE NOTICE 'Dropped overview for level %: %', row.z, row.overview_table;
END LOOP;
END;
$$ LANGUAGE PLPGSQL VOLATILE;
-- Return existing overviews (if any) for a given dataset table
-- Scope: public
-- Parameters
-- reloid: oid of the input table.
-- Return relation of overviews for the table with
-- the base table oid,
-- z level of the overview and overview table oid, ordered by z.
CREATE OR REPLACE FUNCTION CDB_Overviews(reloid REGCLASS)
RETURNS TABLE(base_table REGCLASS, z integer, overview_table REGCLASS)
AS $$
-- FIXME: this will fail if the overview tables
-- require a explicit schema name
-- possible solutions: return table names as text instead of regclass
-- or add schema of reloid before casting to regclass
SELECT
reloid AS base_table,
_CDB_OverviewTableZ(cdb_usertables) AS z,
cdb_usertables::regclass AS overview_table
FROM CDB_UserTables()
WHERE _CDB_IsOverviewTableOf((SELECT relname FROM pg_class WHERE oid=reloid), cdb_usertables)
ORDER BY z;
$$ LANGUAGE SQL;
-- Return existing overviews (if any) for multiple dataset tables.
-- Scope: public
-- Parameters
-- tables: Array of input tables oids
-- Return relation of overviews for the table with
-- the base table oid,
-- z level of the overview and overview table oid, ordered by z.
-- Note: CDB_Overviews can be applied to the result of CDB_QueryTablesText
-- to obtain the overviews applicable to a query.
CREATE OR REPLACE FUNCTION CDB_Overviews(tables regclass[])
RETURNS TABLE(base_table REGCLASS, z integer, overview_table REGCLASS)
AS $$
SELECT
base_table::regclass AS base_table,
_CDB_OverviewTableZ(cdb_usertables) AS z,
cdb_usertables::regclass AS overview_table
FROM
CDB_UserTables(), unnest(tables) base_table
WHERE _CDB_IsOverviewTableOf((SELECT relname FROM pg_class WHERE oid=base_table), cdb_usertables)
ORDER BY base_table, z;
$$ LANGUAGE SQL;
-- Schema and relation names of a table given its reloid
-- Scope: private.
-- Parameters
-- reloid: oid of the table.
-- Return (schema_name, table_name)
-- note that returned names will be quoted if necessary
CREATE OR REPLACE FUNCTION _cdb_split_table_name(reloid REGCLASS, OUT schema_name TEXT, OUT table_name TEXT)
AS $$
BEGIN
SELECT n.nspname, c.relname
INTO STRICT schema_name, table_name
FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.oid = reloid;
END
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Calculate the estimated extent of a cartodbfy'ed table.
-- Scope: private.
-- Parameters
-- reloid: oid of the input table.
-- Return value A box2d extent in 3857.
CREATE OR REPLACE FUNCTION _cdb_estimated_extent(reloid REGCLASS)
RETURNS box2d
AS $$
DECLARE
ext box2d;
ext_query text;
table_id record;
BEGIN
SELECT n.nspname AS schema_name, c.relname table_name INTO STRICT table_id
FROM pg_class c JOIN pg_namespace n on n.oid = c.relnamespace WHERE c.oid = reloid::oid;
ext_query = format(
'SELECT ST_EstimatedExtent(''%1$I'', ''%2$I'', ''%3$I'');',
table_id.schema_name, table_id.table_name, 'the_geom_webmercator'
);
BEGIN
EXECUTE ext_query INTO ext;
EXCEPTION
-- This is the typical ERROR: stats for "mytable" do not exist
WHEN internal_error THEN
-- Get stats and execute again
EXECUTE format('ANALYZE %1$I', reloid);
EXECUTE ext_query INTO ext;
END;
RETURN ext;
END;
$$ LANGUAGE PLPGSQL VOLATILE;
-- Determine the max feature density of a given dataset.
-- Scope: private.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- nz: number of zoom levels to consider from z0 upward.
-- Return value: feature density (num_features / webmercator_squared_meters).
CREATE OR REPLACE FUNCTION _CDB_Feature_Density(reloid REGCLASS, nz integer)
RETURNS FLOAT8
AS $$
DECLARE
fd FLOAT8;
min_features TEXT;
n integer = 4;
c FLOAT8;
BEGIN
-- TODO: for small total count or extents we could just:
-- EXECUTE 'SELECT Count(*)/ST_Area(ST_Extent(the_geom_webmercator)) FROM ' || reloid::text || ';' INTO fd;
-- min_features is a SQL subexpression which can depend on z and represents
-- the minimum number of features to recursively consider a tile.
-- We can either use a fixed minimum number of features per tile
-- or a minimum feature density by dividing the number of features by
-- the area of tiles at level Z: c*c*power(2, -2*z)
-- with c = CDB_XYZ_Resolution(-8) (earth circumference)
min_features = '500';
SELECT CDB_XYZ_Resolution(-8) INTO c;
-- We first compute a set of *seed* tiles, of the minimum Z level, z0, such that
-- they cover the extent of the table and we have at least n of them in each
-- linear dimension (i.e. at least n*n tiles cover the extent).
-- We compute the number of features in these tiles, and recursively in
-- subtiles up to level z0 + nz. Then we compute the maximum of the feature
-- density (per tile area in webmercator squared meters) for all the
-- considered tiles.
EXECUTE Format('
WITH RECURSIVE t(x, y, z, e) AS (
WITH ext AS (SELECT _cdb_estimated_extent(%6$s) as g),
base AS (
SELECT (-floor(log(2, (greatest(ST_XMax(ext.g)-ST_XMin(ext.g), ST_YMax(ext.g)-ST_YMin(ext.g))/(%4$s*%5$s))::numeric)))::integer z
FROM ext
),
lim AS (
SELECT
FLOOR((ST_XMin(ext.g)+CDB_XYZ_Resolution(0)*128)/(CDB_XYZ_Resolution(base.z)*256))::integer x0,
FLOOR((ST_XMax(ext.g)+CDB_XYZ_Resolution(0)*128)/(CDB_XYZ_Resolution(base.z)*256))::integer x1,
FLOOR((CDB_XYZ_Resolution(0)*128-ST_YMin(ext.g))/(CDB_XYZ_Resolution(base.z)*256))::integer y1,
FLOOR((CDB_XYZ_Resolution(0)*128-ST_YMax(ext.g))/(CDB_XYZ_Resolution(base.z)*256))::integer y0
FROM ext, base
),
seed AS (
SELECT xt, yt, base.z, (
SELECT count(*) FROM %1$s
WHERE the_geom_webmercator && CDB_XYZ_Extent(xt, yt, base.z)
) e
FROM base, lim, generate_series(lim.x0, lim.x1) xt, generate_series(lim.y0, lim.y1) yt
)
SELECT * from seed
UNION ALL
SELECT x*2 + xx, y*2 + yy, t.z+1, (
SELECT count(*) FROM %1$s
WHERE the_geom_webmercator && CDB_XYZ_Extent(x*2 + xx, y*2 + yy, t.z+1)
)
FROM t, base, (VALUES (0, 0), (0, 1), (1, 1), (1, 0)) AS c(xx, yy)
WHERE t.e > %2$s AND t.z < (base.z + %3$s)
)
SELECT MAX(e/ST_Area(CDB_XYZ_Extent(x,y,z))) FROM t where e > 0;
', reloid::text, min_features, nz, n, c, reloid::oid)
INTO fd;
RETURN fd;
END
$$ LANGUAGE PLPGSQL STABLE;
-- Experimental default strategy to assign a reference base Z level
-- to a cartodbfied table. The resulting Z level represents the
-- minimum scale level at which the table data can be rendered
-- without overcrowded results or loss of detail.
-- Parameters:
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- Return value: Z level as an integer
CREATE OR REPLACE FUNCTION _CDB_Feature_Density_Ref_Z_Strategy(reloid REGCLASS)
RETURNS INTEGER
AS $$
DECLARE
lim FLOAT8 := 500; -- TODO: determine/parameterize this
nz integer := 4;
fd FLOAT8;
c FLOAT8;
BEGIN
-- Compute fd as an estimation of the (maximum) number
-- of features per unit of tile area (in webmercator squared meters)
SELECT _CDB_Feature_Density(reloid, nz) INTO fd;
-- lim maximum number of (desiderable) features per tile
-- we have c = 2*Pi*R = CDB_XYZ_Resolution(-8) (earth circumference)
-- ta(z): tile area = power(c*power(2,z), 2) = c*c*power(2,2*z)
-- => fd*ta(z) if the average number of features per tile at level z
-- find minimum z so that fd*ta(z) <= lim
-- compute a rough 'feature density' value
SELECT CDB_XYZ_Resolution(-8) INTO c;
RETURN ceil(log(2.0, (c*c*fd/lim)::numeric)/2);
END;
$$ LANGUAGE PLPGSQL STABLE;
-- Overview table name for a given Z level and base dataset or overview table
-- Scope: private.
-- Parameters:
-- ref reference table (can be the base table of the dataset or an existing
-- overview) from which the overview is being generated.
-- ref_z Z level of the reference table
-- overview_z Z level of the overview to be named, must be smaller than ref_z
-- Return value: the name to be used for the overview. The name is always
-- unqualified (does not include a schema name).
CREATE OR REPLACE FUNCTION _CDB_Overview_Name(ref REGCLASS, ref_z INTEGER, overview_z INTEGER)
RETURNS TEXT
AS $$
DECLARE
schema_name TEXT;
base TEXT;
suffix TEXT;
is_overview BOOLEAN;
BEGIN
SELECT * FROM _cdb_split_table_name(ref) INTO schema_name, base;
SELECT _CDB_OverviewBaseTableName(base) INTO base;
RETURN _CDB_OverviewTableName(base, overview_z);
END
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- Sampling reduction method.
-- Valid for any kind of geometry.
-- Scope: private.
-- reloid original table (can be the base table of the dataset or an existing
-- overview) from which the overview is being generated.
-- ref_z Z level assigned to the original table
-- overview_z Z level of the overview to be generated, must be smaller than ref_z
-- Return value: Name of the generated overview table
CREATE OR REPLACE FUNCTION _CDB_Sampling_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER)
RETURNS REGCLASS
AS $$
DECLARE
overview_rel TEXT;
fraction FLOAT8;
base_name TEXT;
class_info RECORD;
num_samples INTEGER;
BEGIN
overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z);
fraction := power(2, 2*(overview_z - ref_z));
-- FIXME: handle schema name for overview_rel if reloid requires it
EXECUTE Format('DROP TABLE IF EXISTS %I CASCADE;', overview_rel);
-- Estimate number of rows
SELECT reltuples, relpages FROM pg_class INTO STRICT class_info
WHERE oid = reloid::oid;
IF class_info.relpages < 2 OR fraction > 0.5 THEN
-- We'll avoid possible CDB_RandomTids problems
EXECUTE Format('
CREATE TABLE %I AS SELECT * FROM %s WHERE random() < %s;
', overview_rel, reloid, fraction);
ELSE
num_samples := ceil(class_info.reltuples*fraction);
EXECUTE Format('
CREATE TABLE %1$I AS SELECT * FROM %2$s
WHERE ctid = ANY (
ARRAY[
(SELECT CDB_RandomTids(''%2$s'', %3$s))
]
);
', overview_rel, reloid, num_samples);
END IF;
RETURN overview_rel;
END;
$$ LANGUAGE PLPGSQL;
-- Register new overview table (post-creation chores)
-- Scope: private
-- Parameters:
-- dataset: oid of the input dataset table, It must be a cartodbfy'ed table.
-- overview_table: oid of the overview table to be registered.
-- overview_z: intended Z level for the overview table
-- This function is declared SECURITY DEFINER so it executes with the privileges
-- of the function creator to have a chance to alter the privileges of the
-- overview table to match those of the dataset. It will only perform any change
-- if the overview table belgons to the same scheme as the dataset and it
-- matches the scheme naming for overview tables.
CREATE OR REPLACE FUNCTION _CDB_Register_Overview(dataset REGCLASS, overview_table REGCLASS, overview_z INTEGER)
RETURNS VOID
AS $$
DECLARE
sql TEXT;
table_owner TEXT;
dataset_scheme TEXT;
dataset_name TEXT;
overview_scheme TEXT;
overview_name TEXT;
BEGIN
-- This function will only register a table as an overview table if it matches
-- the overviews naming scheme for the dataset and z level and the table belongs
-- to the same scheme as the the dataset
SELECT * FROM _cdb_split_table_name(dataset) INTO dataset_scheme, dataset_name;
SELECT * FROM _cdb_split_table_name(overview_table) INTO overview_scheme, overview_name;
IF dataset_scheme = overview_scheme AND
overview_name = _CDB_OverviewTableName(dataset_name, overview_z) THEN
-- preserve the owner of the base table
SELECT u.usename
FROM pg_catalog.pg_class c JOIN pg_catalog.pg_user u ON (c.relowner=u.usesysid)
WHERE c.relname = dataset::text
INTO table_owner;
EXECUTE Format('ALTER TABLE IF EXISTS %s OWNER TO %I;', overview_table::text, table_owner);
-- preserve the table privileges
UPDATE pg_class c_to
SET relacl = c_from.relacl
FROM pg_class c_from
WHERE c_from.oid = dataset
AND c_to.oid = overview_table;
PERFORM _CDB_Add_Indexes(overview_table);
-- TODO: If metadata about existing overviews is to be stored
-- it should be done here (CDB_Overviews would consume such metadata)
END IF;
END
$$ LANGUAGE PLPGSQL SECURITY DEFINER;
-- Dataset attributes (column names other than the
-- CartoDB primary key and geometry columns) which should be aggregated
-- in aggregated overviews.
-- Scope: private.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- Return value: set of attribute names
CREATE OR REPLACE FUNCTION _CDB_Aggregable_Attributes(reloid REGCLASS)
RETURNS SETOF information_schema.sql_identifier
AS $$
SELECT c FROM CDB_ColumnNames(reloid) c, _CDB_Columns() cdb
WHERE c NOT IN (
cdb.pkey, cdb.geomcol, cdb.mercgeomcol
)
$$ LANGUAGE SQL STABLE;
-- List of dataset attributes to be aggregated in aggregated overview
-- as a comma-separated SQL expression.
-- Scope: private.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- Return value: SQL subexpression as text
CREATE OR REPLACE FUNCTION _CDB_Aggregable_Attributes_Expression(reloid REGCLASS)
RETURNS TEXT
AS $$
DECLARE
attr_list TEXT;
BEGIN
SELECT string_agg(s.c, ',') FROM (
SELECT * FROM _CDB_Aggregable_Attributes(reloid) c
) AS s INTO attr_list;
RETURN attr_list;
END
$$ LANGUAGE PLPGSQL STABLE;
-- SQL Aggregation expression for a datase attribute
-- Scope: private.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- column_name: column to be aggregated
-- table_alias: (optional) table qualifier for the column to be aggregated
-- Return SQL subexpression as text with aggregated attribute aliased
-- with its original name.
CREATE OR REPLACE FUNCTION _CDB_Attribute_Aggregation_Expression(reloid REGCLASS, column_name TEXT, table_alias TEXT DEFAULT '')
RETURNS TEXT
AS $$
DECLARE
column_type TEXT;
qualified_column TEXT;
BEGIN
IF table_alias <> '' THEN
qualified_column := Format('%I.%I', table_alias, column_name);
ELSE
qualified_column := Format('%I', column_name);
END IF;
column_type := CDB_ColumnType(reloid, column_name);
CASE column_type
WHEN 'double precision', 'real', 'integer', 'bigint' THEN
RETURN Format('AVG(%s)::' || column_type, qualified_column);
WHEN 'text' THEN
-- TODO: we could define a new aggregate function that returns distinct
-- separated values with a limit, adding ellipsis if more values existed
-- e.g. with '/' as separator and a limit of three:
-- 'A', 'B', 'A', 'C', 'D' => 'A/B/C/...'
-- Other ideas: if value is unique then use it, otherwise use something
-- like '*' or '(varies)' or '(multiple values)', or NULL
-- Using 'string_agg(' || qualified_column || ',''/'')'
-- here causes
RETURN 'CASE count(*) WHEN 1 THEN MIN(' || qualified_column || ') ELSE NULL END::' || column_type;
ELSE
RETURN 'CASE count(*) WHEN 1 THEN MIN(' || qualified_column || ') ELSE NULL END::' || column_type;
END CASE;
END
$$ LANGUAGE PLPGSQL IMMUTABLE;
-- List of dataset aggregated attributes as a comma-separated SQL expression.
-- Scope: private.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- table_alias: (optional) table qualifier for the columns to be aggregated
-- Return value: SQL subexpression as text
CREATE OR REPLACE FUNCTION _CDB_Aggregated_Attributes_Expression(reloid REGCLASS, table_alias TEXT DEFAULT '')
RETURNS TEXT
AS $$
DECLARE
attr_list TEXT;
BEGIN
SELECT string_agg(_CDB_Attribute_Aggregation_Expression(reloid, s.c, table_alias) || Format(' AS %s', s.c), ',')
FROM (
SELECT * FROM _CDB_Aggregable_Attributes(reloid) c
) AS s INTO attr_list;
RETURN attr_list;
END
$$ LANGUAGE PLPGSQL STABLE;
-- Array of geometry types detected in a cartodbfied table
-- For effciency only look at a limited number of rwos.
-- Parameters
-- reloid: oid of the input table. It must be a cartodbfy'ed table.
-- Return value: array of geometry type names
CREATE OR REPLACE FUNCTION _CDB_GeometryTypes(reloid REGCLASS)
RETURNS TEXT[]
AS $$
DECLARE
gtypes TEXT[];
BEGIN
EXECUTE Format('
SELECT array_agg(DISTINCT ST_GeometryType(the_geom)) FROM (
SELECT the_geom FROM %s
WHERE (the_geom is not null) LIMIT 10
) as geom_types
', reloid)
INTO gtypes;
RETURN gtypes;
END
$$ LANGUAGE PLPGSQL STABLE;
-- Experimental Overview reduction method for point datasets.
-- It clusters the points using a grid, then aggregates the point in each
-- cluster into a point at the centroid of the clustered records.
-- Scope: private.
-- Parameters:
-- reloid original table (can be the base table of the dataset or an existing
-- overview) from which the overview is being generated.
-- ref_z Z level assigned to the original table
-- overview_z Z level of the overview to be generated, must be smaller than ref_z
-- Return value: Name of the generated overview table
CREATE OR REPLACE FUNCTION _CDB_GridCluster_Reduce_Strategy(reloid REGCLASS, ref_z INTEGER, overview_z INTEGER)
RETURNS REGCLASS
AS $$
DECLARE
overview_rel TEXT;
reduction FLOAT8;
base_name TEXT;
grid_px FLOAT8 = 7.5; -- Grid size in pixels at Z level overview_z
grid_m FLOAT8;
aggr_attributes TEXT;
attributes TEXT;
columns TEXT;
gtypes TEXT[];
BEGIN
SELECT _CDB_GeometryTypes(reloid) INTO gtypes;
IF array_upper(gtypes, 1) <> 1 OR gtypes[1] <> 'ST_Point' THEN
-- This strategy only supports datasets with point geomety
RETURN NULL;
RETURN 'x';
END IF;
--TODO: check applicability: geometry type, minimum number of points...
overview_rel := _CDB_Overview_Name(reloid, ref_z, overview_z);
-- compute grid cell size using the overview_z dimension...
SELECT CDB_XYZ_Resolution(overview_z)*grid_px INTO grid_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;
-- compute the resulting columns in the same order as in the base table
-- cartodb_id,
-- ST_Transform(ST_SetSRID(ST_MakePoint(sx/n, sy/n), 3857), 4326) AS the_geom,
-- ST_SetSRID(ST_MakePoint(sx/n, sy/n), 3857) AS the_geom_webmercator
-- %4$s
WITH cols AS (
SELECT
CASE c
WHEN 'cartodb_id' THEN 'cartodb_id'
WHEN 'the_geom' THEN
'ST_Transform(ST_SetSRID(ST_MakePoint(sx/n, sy/n), 3857), 4326) AS the_geom'
WHEN 'the_geom_webmercator' THEN
'ST_SetSRID(ST_MakePoint(sx/n, sy/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;
-- FIXME: handle schema name for overview_rel if reloid requires it
EXECUTE Format('DROP TABLE IF EXISTS %I CASCADE;', 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 %3$I AS
WITH clusters AS (
SELECT
%5$s
count(*) AS n,
SUM(ST_X(f.the_geom_webmercator)) AS sx,
SUM(ST_Y(f.the_geom_webmercator)) AS sy,
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);
RETURN overview_rel;
END;
$$ LANGUAGE PLPGSQL;
-- Create overview tables for a dataset.
-- Scope: public
-- Parameters:
-- reloid: oid of the input table. It must be a cartodbfy'ed table with
-- vector features.
-- refscale_strategy: function that computes the reference Z of the dataset
-- reduce_strategy: function that generates overviews from a base table
-- or higher level overview. The overview tables
-- created by the strategy must have the same columns
-- as the base table and in the same order.
-- Return value: Array with the names of the generated overview tables
CREATE OR REPLACE FUNCTION CDB_CreateOverviews(reloid REGCLASS, refscale_strategy regproc DEFAULT '_CDB_Feature_Density_Ref_Z_Strategy'::regproc, reduce_strategy regproc DEFAULT '_CDB_GridCluster_Reduce_Strategy'::regproc)
RETURNS text[]
AS $$
DECLARE
ref_z integer;
overviews_z integer[];
base_z integer;
base_rel REGCLASS;
overview_z integer;
overview_tables REGCLASS[];
overviews_step integer := 1;
BEGIN
-- Determine the referece zoom level
EXECUTE 'SELECT ' || quote_ident(refscale_strategy::text) || Format('(''%s'');', reloid) INTO ref_z;
-- Determine overlay zoom levels
-- TODO: should be handled by the refscale_strategy?
overview_z := ref_z - 1;
WHILE overview_z >= 0 LOOP
SELECT array_append(overviews_z, overview_z) INTO overviews_z;
overview_z := overview_z - overviews_step;
END LOOP;
-- Create overlay tables
base_z := ref_z;
base_rel := reloid;
FOREACH overview_z IN ARRAY overviews_z LOOP
EXECUTE 'SELECT ' || quote_ident(reduce_strategy::text) || Format('(''%s'', %s, %s);', base_rel, base_z, overview_z) INTO base_rel;
IF base_rel IS NULL THEN
EXIT;
END IF;
base_z := overview_z;
PERFORM _CDB_Register_Overview(reloid, base_rel, base_z);
SELECT array_append(overview_tables, base_rel) INTO overview_tables;
END LOOP;
RETURN overview_tables;
END;
$$ LANGUAGE PLPGSQL;

View File

@@ -64,10 +64,6 @@ DECLARE
tabname TEXT;
rec RECORD;
found BOOL;
function_start timestamptz;
function_end timestamptz;
function_duration float;
log_error_verbosity_value text;
BEGIN
IF TG_OP = 'UPDATE' or TG_OP = 'INSERT' THEN
@@ -76,8 +72,6 @@ BEGIN
tabname = OLD.tabname;
END IF;
function_start := clock_timestamp();
-- Notify table data update
-- This needs a little bit more of research regarding security issues
-- see https://github.com/CartoDB/cartodb/pull/241
@@ -111,14 +105,7 @@ BEGIN
EXIT;
END LOOP;
IF NOT found THEN RAISE WARNING 'Missing cdb_invalidate_varnish()'; END IF;
function_end := clock_timestamp();
SELECT extract(epoch from (function_end - function_start)) INTO function_duration;
SELECT setting INTO log_error_verbosity_value FROM pg_settings WHERE name='log_error_verbosity';
SET log_error_verbosity=TERSE;
RAISE LOG 'invalidation_duration: %', function_duration::text;
PERFORM 'SET log_error_verbosity= ' || log_error_verbosity_value;
RETURN NULL;
END;
$$

View File

@@ -5,24 +5,9 @@
CREATE OR REPLACE FUNCTION CDB_XYZ_Resolution(z INTEGER)
RETURNS FLOAT8
AS $$
DECLARE
earth_circumference FLOAT8;
tile_size INTEGER;
full_resolution FLOAT8;
BEGIN
-- Earth equatorial circumference in meters (according to wikipedia)
earth_circumference := 40075017;
-- Size of each tile in pixels (1:1 aspect ratio)
tile_size := 256;
full_resolution := earth_circumference/tile_size;
RETURN full_resolution / (power(2,z));
END
$$ LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-- circumference divided by 256 is z0 resolution, then divide by 2^z
SELECT 40075017.0 / 256 / power(2, z);
$$ LANGUAGE SQL IMMUTABLE STRICT;
-- }
-- {

View File

@@ -1,10 +1,9 @@
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 > 500000000 THEN RETURN 0;
WHEN scaleDenominator <= 500000000 AND scaleDenominator > 200000000 THEN RETURN 1;
WHEN scaleDenominator <= 200000000 AND scaleDenominator > 100000000 THEN RETURN 2;
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;

View File

@@ -0,0 +1 @@
../scripts-available/CDB_GreatCircle.sql

View File

@@ -0,0 +1 @@
../scripts-available/CDB_Overviews.sql

View File

@@ -1,102 +0,0 @@
\set VERBOSITY terse
-- Set user quota to infinite
SELECT CDB_SetUserQuotaInBytes(0);
-- Enable ddl triggers
SELECT cartodb.cdb_enable_ddl_hooks();
create schema c;
SELECT CDB_SetUserQuotaInBytes('c', 0);
DROP USER IF EXISTS cartodb_postgresql_unpriv_user;
CREATE USER cartodb_postgresql_unpriv_user;
GRANT ALL ON SCHEMA c to cartodb_postgresql_unpriv_user;
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
--SELECT session_user, current_user;
----------------------
-- CREATE TABLE
----------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select 1 as i INTO 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;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
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;
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;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
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;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
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;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- DROP TABLE
----------------------------
RESET SESSION AUTHORIZATION;
drop schema c cascade;
select count(*) from CDB_TableMetadata;
DROP OWNED BY cartodb_postgresql_unpriv_user;
DROP ROLE cartodb_postgresql_unpriv_user;
DROP FUNCTION _CDB_UserQuotaInBytes();

View File

@@ -1,5 +1,4 @@
CREATE EXTENSION postgis;
CREATE EXTENSION schema_triggers;
CREATE EXTENSION plpythonu;
CREATE EXTENSION cartodb;
CREATE FUNCTION public.cdb_invalidate_varnish(table_name text)
@@ -7,4 +6,4 @@ RETURNS void AS $$
BEGIN
RAISE NOTICE 'cdb_invalidate_varnish(%) called', table_name;
END;
$$ LANGUAGE 'plpgsql';
$$ LANGUAGE 'plpgsql';

View File

@@ -16,8 +16,8 @@ DECLARE
BEGIN
-- Save current constraints on geometry columns, if any
ogc_geom = ('','','','',0,0,'GEOMETRY');
ogc_merc = ogc_geom;
ogc_geom = ('','','','',0,0,'GEOMETRY');
ogc_merc = ogc_geom;
sql := 'SELECT gc.* FROM geometry_columns gc, pg_class c, pg_namespace n '
|| 'WHERE c.oid = ' || tabname::oid || ' AND n.oid = c.relnamespace'
|| ' AND gc.f_table_schema = n.nspname AND gc.f_table_name = c.relname'
@@ -66,7 +66,7 @@ BEGIN
ELSE 3857 END as expsrid,
CASE WHEN gc.f_geometry_column = 'the_geom' THEN ogc_geom.type
ELSE ogc_merc.type END as exptype, gc.*
FROM geometry_columns gc, pg_class c, pg_namespace n
FROM geometry_columns gc, pg_class c, pg_namespace n
WHERE c.oid = tabname::oid AND n.oid = c.relnamespace
AND gc.f_table_schema = n.nspname AND gc.f_table_name = c.relname
AND gc.f_geometry_column IN ( 'the_geom', 'the_geom_webmercator')
@@ -88,7 +88,7 @@ BEGIN
RAISE EXCEPTION '% entries found for table % in geometry_columns, expected 2', tmp, tabname;
END IF;
-- Check GiST index
-- Check GiST index
sql := 'SELECT a.attname, count(ri.relname) FROM'
|| ' pg_index i, pg_class c, pg_class ri, pg_attribute a, pg_opclass o'
|| ' WHERE i.indrelid = c.oid AND ri.oid = i.indexrelid'
@@ -181,31 +181,31 @@ 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;
SELECT cartodb_id FROM t;
DROP TABLE t;
-- table with text geometry column
CREATE TABLE t AS SELECT 'SRID=4326;POINT(1 1)'::text AS the_geom, 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text the_geom column');
SELECT cartodb_id FROM t;
SELECT cartodb_id FROM t;
DROP TABLE t;
-- table with text geometry column, no SRS
CREATE TABLE t AS SELECT 'POINT(1 1)'::text AS the_geom, 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text the_geom column, no srs');
SELECT cartodb_id FROM t;
SELECT cartodb_id FROM t;
DROP TABLE t;
-- table with text geometry column, unusual SRS
CREATE TABLE t AS SELECT 'SRID=26910;POINT(1 1)'::text AS the_geom, 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text the_geom column, srs = 26819');
SELECT cartodb_id FROM t;
SELECT cartodb_id FROM t;
DROP TABLE t;
-- table with text unparseable geometry column
CREATE TABLE t AS SELECT 'SRID=26910;PONT(1 1)'::text AS the_geom, 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text the_geom column, unparseable content');
SELECT cartodb_id FROM t;
SELECT cartodb_id FROM t;
DROP TABLE t;
-- table with existing cartodb_id serial primary key
@@ -286,12 +286,12 @@ CREATE TABLE test (
cartodb_id integer
);
INSERT INTO test VALUES
(1),
(2),
(NULL),
(1),
(2),
(NULL),
(3);
SELECT CDB_CartodbfyTableCheck('test', 'Table with null cartodb_id #148');
SELECT cartodb_id, cartodb_id_1 from test;
SELECT cartodb_id, cartodb_id_0 from test;
DROP TABLE test;
-- Table with non unique cartodb_id
@@ -299,11 +299,11 @@ CREATE TABLE test (
cartodb_id integer
);
INSERT INTO test VALUES
(1),
(2),
(1),
(2),
(2);
SELECT CDB_CartodbfyTableCheck('test', 'Table with non unique cartodb_id #148');
SELECT cartodb_id, cartodb_id_1 from test;
SELECT cartodb_id, cartodb_id_0 from test;
DROP TABLE test;
-- Table with non unique and null cartodb_id
@@ -316,9 +316,50 @@ INSERT INTO test VALUES
(NULL),
(2);
SELECT CDB_CartodbfyTableCheck('test', 'Table with non unique and null cartodb_id #148');
SELECT cartodb_id, cartodb_id_1 from test;
SELECT cartodb_id, cartodb_id_0 from test;
DROP TABLE test;
CREATE TABLE test (
cartodb_id integer
);
CREATE UNIQUE INDEX "test_cartodb_id_key" ON test (cartodb_id);
CREATE UNIQUE INDEX "test_cartodb_id_pkey" ON test (cartodb_id);
ALTER TABLE test ADD CONSTRAINT "test_pkey" PRIMARY KEY USING INDEX test_cartodb_id_pkey;
INSERT INTO test VALUES
(1),
(2),
(3);
SELECT CDB_CartodbfyTableCheck('test', 'Table with primary key and unique index on it #174');
SELECT cartodb_id from test;
DROP TABLE test;
CREATE TABLE test (
name varchar,
"first.value" integer,
"second.value" integer
);
INSERT INTO test VALUES ('one', 1, 2), ('two', 3, 4);
SELECT CDB_CartodbfyTableCheck('test', 'Table with dots in name columns (cartodb #6114)');
SELECT name, "first.value" from test;
DROP TABLE test;
SET client_min_messages TO notice;
-- _CDB_create_cartodb_id_column with cartodb_id integer already present
CREATE TABLE test (cartodb_id integer);
SELECT _CDB_Create_Cartodb_ID_Column('test'::regclass);
SELECT column_name FROM information_schema.columns WHERE table_name = 'test' AND column_name = '_cartodb_id0';
DROP TABLE test;
-- _CDB_create_cartodb_id_column with cartodb_id text already present
CREATE TABLE test (cartodb_id text);
SELECT _CDB_Create_Cartodb_ID_Column('test'::regclass);
SELECT column_name FROM information_schema.columns WHERE table_name = 'test' AND column_name = '_cartodb_id0';
DROP TABLE test;
SET client_min_messages TO error;
-- TODO: table with existing custom-triggered the_geom

View File

@@ -102,5 +102,35 @@ Table with non unique and null cartodb_id #148 cartodbfied fine
3|
4|2
DROP TABLE
CREATE TABLE
CREATE INDEX
CREATE INDEX
ALTER TABLE
INSERT 0 3
Table with primary key and unique index on it #174 cartodbfied fine
1
2
3
DROP TABLE
CREATE TABLE
INSERT 0 2
Table with dots in name columns (cartodb #6114) cartodbfied fine
one|1
two|3
DROP TABLE
SET
CREATE TABLE
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
DROP TABLE
CREATE TABLE
NOTICE: Column cartodb_id already exists
NOTICE: Existing cartodb_id field is of invalid type text (need int2, int4 or int8), renaming
NOTICE: Trying to recover data from _cartodb_id0 column
DROP TABLE
SET
DROP FUNCTION
DROP FUNCTION

2
test/CDB_GreatCircle.sql Normal file
View File

@@ -0,0 +1,2 @@
select ST_AsText(CDB_GreatCircle(CDB_LatLng(55.8580,4.2590), CDB_LatLng(40.7127,74.0059)));
select ST_AsText(CDB_GreatCircle(CDB_LatLng(55.8580,4.2590), CDB_LatLng(40.7127,74.0059), 50000));

View File

@@ -0,0 +1,2 @@
LINESTRING(4.259 55.858,5.6692453115051 56.0150275120673,7.10720375678704 56.157400475677,8.5718366560563 56.2842986378254,10.0619272412891 56.3949153508462,11.5760785994189 56.4884642014437,13.1127142001617 56.564185934303,14.6700812655504 56.6213555706215,16.2462571744128 56.6592896061102,17.8391590143095 56.6773531596105,19.4465562981665 56.6749669334121,21.0660867567155 56.6516138405427,22.6952750058883 56.6068451534252,24.3315537765309 56.540286032869,25.9722872888145 56.4516403065472,27.6147962622065 56.3406943817481,29.2563839799455 56.207320197769,30.8943627796619 56.0514771479657,32.5260803224591 55.8732129290618,34.1489450028345 55.6726633044968,35.7604499005266 55.4500507979281,37.3581947399686 55.2056823610616,38.9399054089486 54.9399460854786,40.5034506895044 54.6533070499613,42.0468559644411 54.3463024122038,43.5683137754523 54.0195358662507,45.066191217402 53.673671594382,46.5390342525062 53.3094278446298,47.9855691138079 52.9275702630659,49.4047010366934 52.5289051040742,50.7955106088955 52.1142724327331,52.1572480633875 51.6845394219955,53.4893258557794 51.2405938343407,54.7913098701049 50.7833377637432,56.0629095865715 50.3136816997865,57.3039675245588 49.8325389621027,58.5144482465496 49.3408205404538,59.6944271762829 48.8394303639846,60.8440794494795 48.329261012675,61.9636689799149 47.811189874886,63.0535378889196 47.2860757471582,64.1140964137264 46.7547558660385,65.1458133802427 46.2180433565989,66.1492072992903 45.676725078361,67.1248381223566 45.131559846414,68.0732996734468 44.583277003498,68.9952127576034 44.0325753175597,69.8912189338183 43.4801221786776,70.7619749300985 42.9265530691612,71.6081476710291 42.3724712809595,72.4304098829428 41.8184478551838,73.2294362384225 41.2650217194684,74.0059 40.7127)
LINESTRING(4.259 55.858,4.96060044865294 55.9382939511593,5.6692453115051 56.0150275120673,6.38482117645567 56.0880973218335,7.10720375678705 56.157400475677,7.83625773770865 56.2228347173136,8.5718366560563 56.2842986378254,9.31378281572326 56.3416918804739,10.0619272412891 56.3949153508462,10.8160896721679 56.4438714316548,11.5760785994189 56.4884642014437,12.3416913471456 56.528599656387,13.1127142001617 56.5641859343031,13.8889225793161 56.5951335399513,14.6700812655504 56.6213555706215,15.4559446734179 56.6427679409819,16.2462571744128 56.6592896061102,17.0407534700619 56.6708427815999,17.8391590143095 56.6773531596105,18.6411904842936 56.6787501197174,19.4465562981665 56.6749669334121,20.2549571781681 56.6659409611101,21.0660867567155 56.6516138405428,21.8796322228404 56.6319316654367,22.6952750058883 56.6068451534252,23.5126914929996 56.5763098021872,24.3315537765309 56.5402860328691,25.1515304272452 56.4987393199198,25.9722872888145 56.4516403065472,26.7934882889404 56.3989649050969,27.6147962622065 56.3406943817482,28.4358737796488 56.2768154250305,29.2563839799456 56.207320197769,30.0759913971174 56.1322063721813,30.8943627796619 56.0514771479657,31.7111678961496 55.9651412533344,32.5260803224592 55.8732129290618,33.3387782060384 55.7757118957345,34.1489450028345 55.6726633044969,34.9562701828379 55.5640976716962,35.7604499005266 55.4500507979282,36.5611876268714 55.3305636720814,37.3581947399687 55.2056823610617,38.1511910717861 55.0754578859583,38.9399054089486 54.9399460854787,39.7240759459355 54.7992074675415,40.5034506895044 54.6533070499613,41.277787813601 54.5023141912026,42.0468559644411 54.3463024122039,42.8104345158644 54.1853492102971,43.5683137754524 54.0195358662508,44.3202951422663 53.8489472454711,45.066191217402 53.6736715943821,45.8058258688602 53.4938003329924,46.5390342525062 53.3094278446299,47.2656627911282 53.1206512637978,47.985569113808 52.9275702630661,48.6986219579803 52.7302868398744,49.4047010366934 52.5289051040743,50.1036968736777 52.3235310669909,50.7955106088955 52.1142724327332,51.4800537772815 51.9012383924278,52.1572480633875 51.6845394219956,52.8270250346284 51.4642870840378,53.4893258557795 51.2405938343408,54.1441009873167 51.0135728334539,54.791309870105 50.7833377637434,55.4309205988438 50.5500026522693,56.0629095865715 50.3136816997866,56.6872612224038 50.0744891161178,57.3039675245588 49.8325389621028,57.9130277905821 49.5879449982851,58.5144482465496 49.3408205404539,59.1082416968843 49.091278322122,59.6944271762829 48.8394303639847,60.2730296051101 48.5853878503721,60.8440794494795 48.3292610126751,61.40761238711 48.0711590197009,61.9636689799149 47.8111898748862,62.5122943541616 47.5494603202768,63.0535378889195 47.2860757471584,63.5874529134047 47.0211401132109,64.1140964137264 46.7547558660387,64.6335287494427 46.4870238729191,65.1458133802426 46.2180433565991,65.6510166029904 45.9479118369597,66.1492072992903 45.6767250783612,66.6404566936622 45.4045770424768,67.1248381223566 45.1315598464143,67.6024268127789 44.8577637259253,68.0732996734467 44.5832770034983,68.5375350943572 44.3081860611283,68.9952127576034 44.0325753175599,69.4464134580461 43.7565272097974,69.8912189338183 43.4801221786779,70.3297117064144 43.2034386583077,70.7619749300985 42.9265530691615,71.1880922503468 42.6495398146493,71.6081476710291 42.3724712809597,72.0222254300221 42.0954178399905,72.4304098829428 41.8184478551841,72.8327853946822 41.5416276900883,73.2294362384225 41.2650217194687,73.6204465018146 40.9886923428039,74.0059 40.7127)

128
test/CDB_HelperTest.sql Normal file
View File

@@ -0,0 +1,128 @@
-- Test unique identifier creation with normal length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'relname', NULL);
-- Test unique identifier creation with prefix with normal length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'relname', NULL);
-- Test unique identifier creation with suffix with normal length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'relname', '_suffix');
-- Test unique identifier creation with long length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL);
-- Test unique identifier creation with prefix with long length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL);
-- Test new identifier is found when name is taken from previous case
CREATE TABLE prefix_largolargolargolargolargolargolargolargolargolargolar (name text);
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL);
DROP TABLE prefix_largolargolargolargolargolargolargolargolargolargolar;
-- Test unique identifier creation with suffix with long length normal relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', '_suffix');
-- Test new identifier is found when name is taken from previous case
CREATE TABLE largolargolargolargolargolargolargolargolargolargolar_suffix (name text);
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', '_suffix');
DROP TABLE largolargolargolargolargolargolargolargolargolargolar_suffix;
-- Test unique identifier creation with normal length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'piraña', NULL);
-- Test unique identifier creation with prefix with normal length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'piraña', NULL);
-- Test unique identifier creation with suffix with normal length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'piraña', '_suffix');
-- Test unique identifier creation with long length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL);
-- Test unique identifier creation with prefix with long length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL);
-- Test new identifier is found when name is taken from previous case
CREATE TABLE prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi (name text);
SELECT * FROM cartodb._CDB_Unique_Identifier('prefix_', 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL);
DROP TABLE prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi;
-- Test unique identifier creation with suffix with long length UTF8 relname
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', '_suffix');
-- Test new identifier is found when name is taken from previous case
CREATE TABLE piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix (name text);
SELECT * FROM cartodb._CDB_Unique_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', '_suffix');
DROP TABLE piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix;
CREATE TABLE test (name text);
-- Test unique identifier creation with normal length normal colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'colname', NULL, 'test'::regclass);
-- Test unique identifier creation with prefix with normal length normal colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'colname', NULL, 'test'::regclass);
-- Test unique identifier creation with suffix with normal length normal colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'colname', '_suffix', 'test'::regclass);
-- Test unique identifier creation with long length normal colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL, 'test'::regclass);
-- Test unique identifier creation with prefix with long length normal colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL, 'test'::regclass);
DROP TABLE test;
-- Test new identifier is found when name is taken from previous case
CREATE TABLE test (prefix_largolargolargolargolargolargolargolargolargolargolar text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'largolargolargolargolargolargolargolargolargolargolargolargolar', NULL, 'test'::regclass);
DROP TABLE test;
-- Test unique identifier creation with suffix with long length normal colname
CREATE TABLE test (name text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', '_suffix', 'test'::regclass);
DROP TABLE test;
-- Test new identifier is found when name is taken from previous case
CREATE TABLE test (largolargolargolargolargolargolargolargolargolargolar_suffix text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'largolargolargolargolargolargolargolargolargolargolargolargolar', '_suffix', 'test'::regclass);
DROP TABLE test;
CREATE TABLE test (name text);
-- Test unique identifier creation with normal length UTF8 colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'piraña', NULL, 'test'::regclass);
-- Test unique identifier creation with prefix with normal length UTF8 colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'piraña', NULL, 'test'::regclass);
-- Test unique identifier creation with suffix with normal length UTF8 colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'piraña', '_suffix', 'test'::regclass);
-- Test unique identifier creation with long length UTF8 colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL, 'test'::regclass);
-- Test unique identifier creation with prefix with long length UTF8 colname
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL, 'test'::regclass);
DROP TABLE test;
-- Test new identifier is found when name is taken from previous case
CREATE TABLE test (prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier('prefix_', 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', NULL, 'test'::regclass);
DROP TABLE test;
-- Test unique identifier creation with suffix with long length UTF8 colname
CREATE TABLE test (name text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', '_suffix', 'test'::regclass);
DROP TABLE test;
-- Test new identifier is found when name is taken from previous case
CREATE TABLE test (piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix text);
SELECT * FROM cartodb._CDB_Unique_Column_Identifier(NULL, 'piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácidpin', '_suffix', 'test'::regclass);
DROP TABLE test;
-- Test _CDB_Octet_Truncate simple case
SELECT * FROM cartodb._CDB_Octet_Truncate('piraña', 5);
-- Test _CDB_Octet_Truncate UTF8 case
SELECT * FROM cartodb._CDB_Octet_Truncate('piraña', 6);
-- Test _CDB_Octet_Truncate UTF8 case
SELECT * FROM cartodb._CDB_Octet_Truncate('piraña', 7);

View File

@@ -0,0 +1,59 @@
relname
prefix_relname
relname_suffix
largolargolargolargolargolargolargolargolargolargolargolargo
prefix_largolargolargolargolargolargolargolargolargolargolar
CREATE TABLE
prefix_largolargolargolargolargolargolargolargolargolargolar_0
DROP TABLE
largolargolargolargolargolargolargolargolargolargolar_suffix
CREATE TABLE
largolargolargolargolargolargolargolargolargolargolar_suffix_0
DROP TABLE
piraña
prefix_piraña
piraña_suffix
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácid
prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi
CREATE TABLE
prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_0
DROP TABLE
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix
CREATE TABLE
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix_0
DROP TABLE
CREATE TABLE
colname
prefix_colname
colname_suffix
largolargolargolargolargolargolargolargolargolargolargolargo
prefix_largolargolargolargolargolargolargolargolargolargolar
DROP TABLE
CREATE TABLE
prefix_largolargolargolargolargolargolargolargolargolargolar_0
DROP TABLE
CREATE TABLE
largolargolargolargolargolargolargolargolargolargolar_suffix
DROP TABLE
CREATE TABLE
largolargolargolargolargolargolargolargolargolargolar_suffix_0
DROP TABLE
CREATE TABLE
piraña
prefix_piraña
piraña_suffix
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpiñaácid
prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi
DROP TABLE
CREATE TABLE
prefix_piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_0
DROP TABLE
CREATE TABLE
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix
DROP TABLE
CREATE TABLE
piñaácidpiñaácidpiñaácidpiñaácidpiñaácidpi_suffix_0
DROP TABLE
pira
pirañ
piraña

View File

@@ -0,0 +1,33 @@
SET client_min_messages TO error;
\set VERBOSITY default
\i test/overviews/fixtures.sql
SELECT _CDB_Aggregable_Attributes_Expression('base_bare_t'::regclass);
SELECT _CDB_Aggregated_Attributes_Expression('base_bare_t'::regclass);
SELECT _CDB_Aggregated_Attributes_Expression('base_bare_t'::regclass, 'tab');
SELECT CDB_CreateOverviews('base_bare_t'::regclass);
SELECT count(*) FROM _vovw_5_base_bare_t;
SELECT _CDB_Aggregable_Attributes_Expression('base_t'::regclass);
SELECT _CDB_Aggregated_Attributes_Expression('base_t'::regclass);
SELECT _CDB_Aggregated_Attributes_Expression('base_t'::regclass, 'tab');
SELECT CDB_CreateOverviews('base_t'::regclass);
SELECT count(*) FROM _vovw_5_base_t;
SELECT CDB_CreateOverviews('polyg_t'::regclass);
SELECT CDB_Overviews('base_t'::regclass);
SELECT CDB_Overviews(ARRAY['base_t'::regclass, 'base_bare_t'::regclass]);
SELECT CDB_Overviews('polyg_t'::regclass);
SELECT CDB_DropOverviews('base_bare_t'::regclass);
SELECT CDB_DropOverviews('base_t'::regclass);
SELECT count(*) FROM _vovw_5_base_t;
DROP TABLE base_bare_t;
DROP TABLE base_t;
DROP TABLE polyg_t;

View File

@@ -0,0 +1,44 @@
SET
CREATE TABLE
INSERT 0 1114
CREATE TABLE
INSERT 0 1114
CREATE TABLE
INSERT 0 5
{_vovw_5_base_bare_t,_vovw_4_base_bare_t,_vovw_3_base_bare_t,_vovw_2_base_bare_t,_vovw_1_base_bare_t,_vovw_0_base_bare_t}
125
number,int_number,name,start
AVG(number)::double precision AS number,AVG(int_number)::integer AS int_number,CASE count(*) WHEN 1 THEN MIN(name) ELSE NULL END::text AS name,CASE count(*) WHEN 1 THEN MIN(start) ELSE NULL END::date AS start
AVG(tab.number)::double precision AS number,AVG(tab.int_number)::integer AS int_number,CASE count(*) WHEN 1 THEN MIN(tab.name) ELSE NULL END::text AS name,CASE count(*) WHEN 1 THEN MIN(tab.start) ELSE NULL END::date AS start
{_vovw_5_base_t,_vovw_4_base_t,_vovw_3_base_t,_vovw_2_base_t,_vovw_1_base_t,_vovw_0_base_t}
125
(base_t,0,_vovw_0_base_t)
(base_t,1,_vovw_1_base_t)
(base_t,2,_vovw_2_base_t)
(base_t,3,_vovw_3_base_t)
(base_t,4,_vovw_4_base_t)
(base_t,5,_vovw_5_base_t)
(base_bare_t,0,_vovw_0_base_bare_t)
(base_bare_t,1,_vovw_1_base_bare_t)
(base_bare_t,2,_vovw_2_base_bare_t)
(base_bare_t,3,_vovw_3_base_bare_t)
(base_bare_t,4,_vovw_4_base_bare_t)
(base_bare_t,5,_vovw_5_base_bare_t)
(base_t,0,_vovw_0_base_t)
(base_t,1,_vovw_1_base_t)
(base_t,2,_vovw_2_base_t)
(base_t,3,_vovw_3_base_t)
(base_t,4,_vovw_4_base_t)
(base_t,5,_vovw_5_base_t)
ERROR: relation "_vovw_5_base_t" does not exist
LINE 1: SELECT count(*) FROM _vovw_5_base_t;
^
DROP TABLE
DROP TABLE
DROP TABLE

View File

@@ -1,4 +1,4 @@
SELECT * FROM geometry_columns|{pg_catalog.pg_attribute,pg_catalog.pg_class,pg_catalog.pg_namespace,pg_catalog.pg_type}
SELECT * FROM geometry_columns|{pg_catalog.pg_attribute,pg_catalog.pg_class,pg_catalog.pg_constraint,pg_catalog.pg_namespace,pg_catalog.pg_type}
SELECT a.attname FROM pg_class c JOIN pg_attribute a on (a.attrelid = c.oid)|{pg_catalog.pg_attribute,pg_catalog.pg_class}
CREATE table "my'tab;le" as select 1|{}
SELECT a.oid, b.oid FROM pg_class a, pg_class b|{pg_catalog.pg_class}
@@ -20,4 +20,4 @@ select * from sc.test|{sc.test}
DROP TABLE
DROP SCHEMA
SELECT
* FROM geometry_columns|{pg_catalog.pg_attribute,pg_catalog.pg_class,pg_catalog.pg_namespace,pg_catalog.pg_type}
* FROM geometry_columns|{pg_catalog.pg_attribute,pg_catalog.pg_class,pg_catalog.pg_constraint,pg_catalog.pg_namespace,pg_catalog.pg_type}

View File

@@ -4,6 +4,6 @@ range AS ( select z, generate_series(0, pow(2,z)::int-1) as r FROM zoom),
inp AS ( select z0.z, r1.r as x, r2.r as y FROM zoom z0, range r1, range r2 WHERE z0.z = r1.z and r1.z = r2.z ),
ext AS ( select x,y,z,CDB_XYZ_Extent(x,y,z) as g from inp )
select X::text || ',' || Y::text || ',' || Z::text as xyz,
st_xmin(g), st_xmax(g), st_ymin(g), st_ymax(g)
round(st_xmin(g)), round(st_xmax(g)), round(st_ymin(g)), round(st_ymax(g))
from ext order by xyz;

View File

@@ -1,21 +1,21 @@
0,0,0|-20037508.5|20037508.5|-20037508.5|20037508.5
0,0,1|-20037508.5|0|0|20037508.5
0,0,2|-20037508.5|-10018754.25|10018754.25|20037508.5
0,1,1|-20037508.5|0|-20037508.5|0
0,1,2|-20037508.5|-10018754.25|0|10018754.25
0,2,2|-20037508.5|-10018754.25|-10018754.25|0
0,3,2|-20037508.5|-10018754.25|-20037508.5|-10018754.25
1,0,1|0|20037508.5|0|20037508.5
1,0,2|-10018754.25|0|10018754.25|20037508.5
1,1,1|0|20037508.5|-20037508.5|0
1,1,2|-10018754.25|0|0|10018754.25
1,2,2|-10018754.25|0|-10018754.25|0
1,3,2|-10018754.25|0|-20037508.5|-10018754.25
2,0,2|0|10018754.25|10018754.25|20037508.5
2,1,2|0|10018754.25|0|10018754.25
2,2,2|0|10018754.25|-10018754.25|0
2,3,2|0|10018754.25|-20037508.5|-10018754.25
3,0,2|10018754.25|20037508.5|10018754.25|20037508.5
3,1,2|10018754.25|20037508.5|0|10018754.25
3,2,2|10018754.25|20037508.5|-10018754.25|0
3,3,2|10018754.25|20037508.5|-20037508.5|-10018754.25
0,0,0|-20037508|20037508|-20037508|20037508
0,0,1|-20037508|0|0|20037508
0,0,2|-20037508|-10018754|10018754|20037508
0,1,1|-20037508|0|-20037508|0
0,1,2|-20037508|-10018754|0|10018754
0,2,2|-20037508|-10018754|-10018754|0
0,3,2|-20037508|-10018754|-20037508|-10018754
1,0,1|0|20037508|0|20037508
1,0,2|-10018754|0|10018754|20037508
1,1,1|0|20037508|-20037508|0
1,1,2|-10018754|0|0|10018754
1,2,2|-10018754|0|-10018754|0
1,3,2|-10018754|0|-20037508|-10018754
2,0,2|0|10018754|10018754|20037508
2,1,2|0|10018754|0|10018754
2,2,2|0|10018754|-10018754|0
2,3,2|0|10018754|-20037508|-10018754
3,0,2|10018754|20037508|10018754|20037508
3,1,2|10018754|20037508|0|10018754
3,2,2|10018754|20037508|-10018754|0
3,3,2|10018754|20037508|-20037508|-10018754

2242
test/overviews/fixtures.sql Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
# Ruby script to generate test/overviews/fixtures.sql for testing overviews
# Generated tables:
# * base_bare_t -- points without attributes (only PK, geometries)
NUM_CLUSTERS = 128
MAX_PER_CLUSTER = 16
CLUSTER_RADIUS = 1E-3
MIN_X = -10.0
MAX_X = 10.0
MIN_Y = 30.0
MAX_Y = 40.0
ATTRIBUTES = "number double precision, int_number integer, name text, start date"
id = 0
POINTS = (0...NUM_CLUSTERS).map{
x = MIN_X + rand()*(MAX_X - MIN_X)
y = MIN_Y + rand()*(MAX_Y - MIN_Y)
(0..rand(MAX_PER_CLUSTER)).map{
id += 1
{
id: id,
x: (x + rand()*CLUSTER_RADIUS).round(6),
y: (y + rand()*CLUSTER_RADIUS).round(6)
}
}
}.flatten
values = POINTS.map{ |point|
"#{point[:id]}, 'SRID=4326;POINT(#{point[:x]} #{point[:y]})'::geometry, ST_Transform('SRID=4326;POINT(#{point[:x]} #{point[:y]})'::geometry, 3857)"
}
File.open('fixtures.sql', 'w') do |sql|
sql.puts "-- bare table with no attribute columns"
sql.puts "CREATE TABLE base_bare_t (cartodb_id integer, the_geom geometry, the_geom_webmercator geometry);"
sql.puts "INSERT INTO base_bare_t VALUES"
sql.puts values.map{|v| "(#{v})"}.join(",\n") + ";"
sql.puts "-- table with attributes"
sql.puts "CREATE TABLE base_t (cartodb_id integer, the_geom geometry, the_geom_webmercator geometry, #{ATTRIBUTES});"
sql.puts "INSERT INTO base_t VALUES"
sql.puts values.map{|v| "(#{v})"}.join(",\n") + ";"
end