Compare commits

..

188 Commits

Author SHA1 Message Date
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
Alejandro Martínez
eb1222729d Remove ddl triggers specs 2016-01-21 11:46:39 +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
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
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
Paul Norman
a9f6e26fed Merge pull request #184 from pnorman/readme_url
Update wiki URL
2015-12-21 08:35:01 -08: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
Luis Bosque
cf2587ca54 New version 0.11.2 2015-10-19 14:35:10 +02:00
Luis Bosque
d1d5ed6df3 Optimize invalidation time logging 2015-10-19 14:09:52 +02:00
Luis Bosque
37160c7b35 Write invalidation duration in postgresql log 2015-10-16 18:23:18 +02:00
Alejandro Martínez
811c7474de Merge pull request #170 from CartoDB/fix-schema-group-sequence
Fix schema not being specified on pg_get_serial_sequence
2015-10-15 17:39:46 +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
Alejandro Martínez
1f63811383 Fix schema not being specified on pg_get_serial_sequence 2015-10-06 18:09:37 +02:00
Rafa de la Torre
913bfd72f8 New version 0.11.1
- Added CDB_DateToNumber(timestamp with time zone) [#169](https://github.com/CartoDB/cartodb-postgresql/pull/169)
- cartodbfy now discards cartodb_id candidates that contain nulls [#148](https://github.com/CartoDB/cartodb-postgresql/issues/148)
2015-10-06 14:45:35 +02:00
Rafa de la Torre
15dd4935d6 Merge pull request #168 from CartoDB/148-cartodbfy-checks-for-null-cartodb-id
148 cartodbfy checks for null cartodb id
2015-10-06 14:39:00 +02:00
Rafa de la Torre
39e558f494 Merge pull request #169 from CartoDB/2202-DateToNumber-with-time-zones
Changes CDB_DateToNumber() to accept timestamps with time zones 2202
2015-10-06 12:52:52 +02:00
Guido Fioravantti
03636fafc4 Update CONTRIBUTING.md 2015-10-06 11:33:56 +02:00
Guido Fioravantti
6b3b28f01f Makes CDB_DateToNumber() tests more intuitive 2202 2015-10-05 14:56:45 +02:00
Guido Fioravantti
186ed34ee5 Overloads CDB_DateToNumber() and adds test 2015-10-05 13:32:03 +02:00
Guido Fioravantti
e4ce12d1a3 Changes CDB_DateToNumber() to accept timestamps with time zones 2202 2015-10-05 11:51:13 +02:00
Guido Fioravantti
5de395a4a8 Uses CDB_CartodbfyTableCheck() 148 2015-09-29 19:01:30 +02:00
Guido Fioravantti
3429e93979 Makes cartodbfy check for null cartodb_id 2015-09-29 18:04:00 +02:00
Guido Fioravantti
777e8c6e4c Adds test to check cartodbfy works with null cartodb_id 2015-09-29 18:03:20 +02:00
Juan Ignacio Sánchez Lara
bce61c1e43 Merge pull request #104 from CartoDB/103-Extension_Group_API
103 extension group api
2015-09-28 10:30:32 +02:00
Juan Ignacio Sánchez Lara
1f72be0390 Merge branch 'master' into 103-Extension_Group_API 2015-09-28 09:48:46 +02:00
Juan Ignacio Sánchez Lara
a59a95fddc Merge pull request #165 from CartoDB/162-Allow_non_sync_group_permission_management_queries
162 allow non sync group permission management queries
2015-09-28 09:42:54 +02:00
Juan Ignacio Sánchez Lara
0081ec16a9 Sync-flag functions should be private 2015-09-27 18:42:24 +02:00
Juan Ignacio Sánchez Lara
e7008d04ee https support back 2015-09-25 19:13:04 +02:00
Juan Ignacio Sánchez Lara
3330421887 sync parameter at group functions closes #162 2015-09-25 19:02:39 +02:00
Juan Ignacio Sánchez Lara
a0204d50db X-Forwarded-Proto 2015-09-21 19:01:40 +02:00
Juan Ignacio Sánchez Lara
a2ddb76ef3 Shorter admin role name 2015-09-21 16:31:12 +02:00
Juan Ignacio Sánchez Lara
cc1e357caa Removed unnecessary EXECUTEs 2015-09-21 15:47:52 +02:00
Juan Ignacio Sánchez Lara
0e4f3955f6 1108 separator for cleaner SQL 2015-09-21 15:37:10 +02:00
Juan Ignacio Sánchez Lara
8fdf5cb9c4 Merge branch 'master' into 103-Extension_Group_API 2015-09-21 14:52:37 +02:00
Juan Ignacio Sánchez Lara
bf4f30c99d Removed IMMUTABLE for functions depending on current database 2015-09-21 14:35:28 +02:00
Juan Ignacio Sánchez Lara
963f8ea97b #103 0.11.0 version 2015-09-21 12:54:14 +02:00
Juan Ignacio Sánchez Lara
458cbf2a80 Merge branch 'master' into 103-Extension_Group_API 2015-09-21 12:21:58 +02:00
Rafa de la Torre
fc0e883c20 First version of the cartodbfy requirements 2015-09-15 11:51:27 +02:00
Juan Ignacio Sánchez Lara
206cee1647 Deletion operations return 204 2015-09-09 12:24:54 +02:00
Juan Ignacio Sánchez Lara
f70fd1a4c7 Merge branch 'master' into 103-Extension_Group_API 2015-09-07 13:37:21 +02:00
Juan Ignacio Sánchez Lara
7b04267366 Merge pull request #137 from CartoDB/136-Add_support_for_adding_a_batch_of_users_to_a_group
136 add support for adding a batch of users to a group
2015-09-07 11:48:53 +02:00
Juan Ignacio Sánchez Lara
275e5154fd Fixed comment 2015-09-07 11:48:18 +02:00
Juan Ignacio Sánchez Lara
4405ecb466 Multiple users test 2015-09-07 11:43:57 +02:00
Juan Ignacio Sánchez Lara
154eff6d25 Array notation for batch group functions 2015-09-07 11:43:46 +02:00
Juan Ignacio Sánchez Lara
b73eb486a5 Old functions cleanup 2015-09-07 10:35:32 +02:00
Juan Ignacio Sánchez Lara
59d144d91d Batch add/remove users support 2015-09-07 10:35:04 +02:00
Juan Ignacio Sánchez Lara
428a2391ad Refactor Member -> User 2015-09-07 09:56:59 +02:00
Juan Ignacio Sánchez Lara
0896b1451a Spaces support fixes #135 2015-09-03 20:41:19 +02:00
Juan Ignacio Sánchez Lara
dfec191a9a Support for spaces inside group names, fixed 2015-09-03 16:51:06 +02:00
Juan Ignacio Sánchez Lara
1b5b3f741f Support for spaces inside group names 2015-09-03 16:38:12 +02:00
Juan Ignacio Sánchez Lara
a003ab7f6a Merge branch 'master' into 103-Extension_Group_API 2015-08-31 13:27:21 +02:00
Juan Ignacio Sánchez Lara
15aece1fbc Use %s for sequence name, which is already quoted 2015-08-27 17:03:13 +02:00
Juan Ignacio Sánchez Lara
e1f8a65cce Use %s for sequence name, which is already quoted 2015-08-27 17:02:05 +02:00
Juan Ignacio Sánchez Lara
fc32d457eb String interpolation with %I, which includes quoting 2015-08-27 10:25:52 +02:00
Juan Ignacio Sánchez Lara
a4952f6a1e Granting RW permission on a table should also grant permission on default values sequences 2015-08-26 13:33:01 +02:00
Juan Ignacio Sánchez Lara
1f67b52bf7 Documented the need for create extension and separated from cdb_conf creation 2015-08-26 13:23:32 +02:00
Juan Ignacio Sánchez Lara
c6fa292f01 Extension installation ready 2015-08-20 17:39:28 +02:00
Juan Ignacio Sánchez Lara
faa4f203d6 Changed sample config 2015-08-20 17:32:36 +02:00
Juan Ignacio Sánchez Lara
66e2082266 Missing cartodb schema 2015-08-20 13:02:02 +02:00
Juan Ignacio Sánchez Lara
43d41e5c26 Removed cached (won't work between sessions) 2015-08-20 12:55:22 +02:00
Juan Ignacio Sánchez Lara
bd31419e94 Fixed return auth 2015-08-20 12:54:46 +02:00
Juan Ignacio Sánchez Lara
a885f5328e Fix conf tests (json values) 2015-08-20 10:45:24 +02:00
Juan Ignacio Sánchez Lara
600f9159fb {} >> dict() 2015-08-20 10:25:31 +02:00
Juan Ignacio Sánchez Lara
eb912b48bf Removed not needed json import 2015-08-20 10:22:44 +02:00
Juan Ignacio Sánchez Lara
9c70e5f91a Merge branch 'master' into 103-Extension_Group_API 2015-08-20 10:17:00 +02:00
Juan Ignacio Sánchez Lara
551e09ff6f Secured _CDB_Group_API_Request 2015-08-20 10:03:48 +02:00
Juan Ignacio Sánchez Lara
97dd8e5720 Conf value type to json 2015-08-20 08:44:59 +02:00
Juan Ignacio Sánchez Lara
e1d195a21f Merge branch 'master' into 103-Extension_Group_API 2015-08-19 18:51:37 +02:00
Juan Ignacio Sánchez Lara
75c4308ea9 Grant and revoking permissions API sync 2015-08-19 18:43:25 +02:00
Juan Ignacio Sánchez Lara
70fe432102 Secured configuration access 2015-08-19 11:20:06 +02:00
Juan Ignacio Sánchez Lara
e1dde3c36c Removed old code 2015-08-19 11:08:05 +02:00
Juan Ignacio Sánchez Lara
6c1369f2a9 Documentation about roles and functions 2015-08-19 11:05:32 +02:00
Juan Ignacio Sánchez Lara
726f3c31f7 Documentation about roles and functions 2015-08-19 11:03:07 +02:00
Juan Ignacio Sánchez Lara
2245c05b1e Don't allow users to pick database name, keeping group operations inside their org 2015-08-19 10:52:07 +02:00
Juan Ignacio Sánchez Lara
1fe9bb2e84 Don't allow users to pick database name, keeping group operations inside their org 2015-08-19 10:37:52 +02:00
Juan Ignacio Sánchez Lara
0cb55d043a Revoke select on table and add security definer for conf getter 2015-08-19 10:35:23 +02:00
Juan Ignacio Sánchez Lara
8a8d4b5b00 Don't upgrade version until release is planned 2015-08-18 16:09:34 +02:00
Juan Ignacio Sánchez Lara
fd25a02b45 Merge branch 'master' into 103-Extension_Group_API 2015-08-18 16:07:22 +02:00
Juan Ignacio Sánchez Lara
67d7e28684 409 is a valid renaming response 2015-08-18 13:26:23 +02:00
Juan Ignacio Sánchez Lara
a8b9ec345a valid_return_codes parameter 2015-08-18 11:53:38 +02:00
Juan Ignacio Sánchez Lara
a75a337296 _CDB_Conf_Cache SD-based 2015-08-18 10:44:10 +02:00
Juan Ignacio Sánchez Lara
1217b4e4a4 Cache http client with private SD 2015-08-18 08:27:14 +02:00
Juan Ignacio Sánchez Lara
d6410d91bd Cache http client 2015-08-18 08:24:30 +02:00
Juan Ignacio Sánchez Lara
9d03e755b8 _CDB_Group_API_Request refactor 2015-08-18 08:10:02 +02:00
Juan Ignacio Sánchez Lara
87a955b56a Removed cdb_ prefix from local variables 2015-08-17 15:23:39 +02:00
Juan Ignacio Sánchez Lara
653eae21b3 _CDB_Group_RemoveMember_API 2015-08-17 15:20:15 +02:00
Juan Ignacio Sánchez Lara
e4a56371c0 _CDB_Group_AddMember_API 2015-08-17 15:05:09 +02:00
Juan Ignacio Sánchez Lara
00e9cc5a79 Explicit null check for not found role 2015-08-17 15:02:21 +02:00
Juan Ignacio Sánchez Lara
566adfb0ce CDB_Group_RenameGroup_API 2015-08-17 13:37:34 +02:00
Juan Ignacio Sánchez Lara
99641b827c Authorization type moved to function 2015-08-17 12:55:42 +02:00
Juan Ignacio Sánchez Lara
df531e9e37 auth inside param reading 2015-08-17 12:26:38 +02:00
Juan Ignacio Sánchez Lara
6c3555f21a Configuration parameters refactor 2015-08-17 11:49:31 +02:00
Juan Ignacio Sánchez Lara
a08600a1f8 Exclude cartodb schema from CDB_UserTables 2015-08-14 16:31:19 +02:00
Juan Ignacio Sánchez Lara
e11f4ef169 Group name validation delegated to role creation 2015-08-14 15:40:36 +02:00
Juan Ignacio Sánchez Lara
db89bf1a94 Grant select on configuration table to org members 2015-08-14 15:28:19 +02:00
Juan Ignacio Sánchez Lara
466e4d81c6 format instead of string concatenation 2015-08-14 15:22:00 +02:00
Juan Ignacio Sánchez Lara
ae634e7814 Server notification must happen after role creation 2015-08-14 15:04:14 +02:00
Juan Ignacio Sánchez Lara
d1f19a0234 Groups API configuration example 2015-08-14 14:03:53 +02:00
Juan Ignacio Sánchez Lara
d4bcb97f9b CDB_CONF and create and drop group api calls 2015-08-14 14:00:58 +02:00
Juan Ignacio Sánchez Lara
a0aac4e9c9 Info about if not exist log output 2015-08-14 14:00:58 +02:00
Juan Ignacio Sánchez Lara
725453ce2b Configuration table and functions 2015-08-14 14:00:58 +02:00
Juan Ignacio Sánchez Lara
7262d34b06 IMMUTABLE-STABLE-VOLATILE specification 2015-08-14 14:00:58 +02:00
Juan Ignacio Sánchez Lara
3ee4978240 Roles simplification, without md5 and prepending database name 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
2ece2979a6 Drop cartodb schema before dropping publicuser 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
401d3e9066 publicuser back 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
79e1926766 Group management done by organization admin 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
e2dd1e014e test_valid_group_names and test_not_valid_group_names 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
1915e28a0f Cleaner debug output 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
bd46796bb7 Fix spacing 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
898d3c14fd test_group_management_functions_cant_be_used_by_normal_members and warning -> error processing 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
154f6df1dc _CDB_Group_GroupRole based on current database m5 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
9a3fbb668c Dynamic variable binding 2015-08-14 14:00:57 +02:00
Juan Ignacio Sánchez Lara
6baa626756 Groups will be 0.9.0 2015-08-14 14:00:56 +02:00
Juan Ignacio Sánchez Lara
c29733eb87 publicuser uncommenting 2015-08-14 14:00:26 +02:00
Juan Ignacio Sánchez Lara
52f73b1a01 CDB_Group_Table_GrantReadWrite 2015-08-14 14:00:26 +02:00
Juan Ignacio Sánchez Lara
28af048c92 Methods doc 2015-08-14 14:00:26 +02:00
Juan Ignacio Sánchez Lara
1279742e50 CDB_Group_CreateGroup should not return role, since it's an internal implementation detail 2015-08-14 14:00:26 +02:00
Juan Ignacio Sánchez Lara
b633466724 Non-public API method naming 2015-08-14 14:00:26 +02:00
Juan Ignacio Sánchez Lara
e04f0caa6c Permission granting 2015-08-14 14:00:25 +02:00
Juan Ignacio Sánchez Lara
5afdd77dcf Rename group 2015-08-14 14:00:25 +02:00
Juan Ignacio Sánchez Lara
eafb0f4557 Groups API extension version 2015-08-14 14:00:25 +02:00
Juan Ignacio Sánchez Lara
42e72ac9d5 cartodb.CDB_Group_CreateGroup cartodb.CDB_Group_DropGroup 2015-08-14 13:58:10 +02:00
Juan Ignacio Sánchez Lara
2824a9c457 Ignore vim temporal files 2015-08-14 13:58:10 +02:00
40 changed files with 1439 additions and 690 deletions

3
.gitignore vendored
View File

@@ -5,4 +5,5 @@ results/
regression.*
expected/test
sql/test
.idea/*
.idea/*
*.swp

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

@@ -44,7 +44,7 @@ the extension into your test database.
During development the cartodb extension version doesn't change with
every commit, so testing latest change requires cheating with PostgreSQL
so to enforce re-load of the scripts. To help with cheating, "make install"
as to enforce the scripts to reload. To help with cheating, "make install"
also installs migration scripts to go from "V" to "V"next and from "V"next
to "V". Example to upgrade a 0.2.0dev version:

View File

@@ -1,16 +1,16 @@
# cartodb/Makefile
EXTENSION = cartodb
EXTVERSION = 0.10.2
EXTVERSION = 0.12.0
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 = \
@@ -50,6 +50,13 @@ UPGRADABLE = \
0.10.0 \
0.10.1 \
0.10.2 \
0.11.0 \
0.11.1 \
0.11.2 \
0.11.3 \
0.11.4 \
0.11.5 \
0.12.0 \
$(EXTVERSION)dev \
$(EXTVERSION)next \
$(END)
@@ -71,10 +78,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)

38
NEWS.md
View File

@@ -1,5 +1,39 @@
next (2015-mm-dd)
-----------------
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)
-------------------
* Fix schema not being specified on pg_get_serial_sequence [#170](https://github.com/CartoDB/cartodb-postgresql/pull/170)
* Log invalidation function call duration in seconds [#163](https://github.com/CartoDB/cartodb-postgresql/pull/163)
0.11.1 (2015-10-06)
-------------------
* Added CDB_DateToNumber(timestamp with time zone) [#169](https://github.com/CartoDB/cartodb-postgresql/pull/169)
* cartodbfy now discards cartodb_id candidates that contain nulls [#148](https://github.com/CartoDB/cartodb-postgresql/issues/148)
0.11.0 (2015-09-dd)
-------------------
* Groups API
0.10.2 (2015-09-24)
-------------------

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;
```
@@ -98,3 +89,8 @@ ls `pg_config --sharedir`/extension/cartodb*
During development the cartodb extension version doesn't change with
every commit, so testing latest change requires special steps documented
in the CONTRIBUTING document, under "Testing changes live".
Limitations
-----------
- The main schema of an organization user must have one only owner (the user).

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.

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;
@@ -362,7 +363,7 @@ $$ LANGUAGE PLPGSQL;
-- As before, this drops all the metadata and geom sync triggers
--
-- (2) _CDB_Has_Usable_Primary_ID()
-- Returns TRUE if it can find a unique integer primary key named
-- Returns TRUE if it can find a unique and not null integer primary key named
-- 'cartodb_id' or can rename an existing key.
-- Returns FALSE otherwise.
--
@@ -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,11 +504,11 @@ 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;
-- Check and see if the column values are unique,
-- Check and see if the column values are unique and not null,
-- if they are, we can use this column...
ELSE
@@ -559,13 +516,17 @@ BEGIN
useable_key := true;
BEGIN
sql := Format('ALTER TABLE %s ADD CONSTRAINT %s_unique UNIQUE (%s)', reloid::text, const.pkey, const.pkey);
sql := Format('ALTER TABLE %s ADD CONSTRAINT %s_pk PRIMARY KEY (%s)', reloid::text, const.pkey, const.pkey);
RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', sql;
EXECUTE sql;
EXCEPTION
-- Failed unique check...
WHEN unique_violation THEN
RAISE NOTICE 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('column %s is not unique', const.pkey);
RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('column %s is not unique', const.pkey);
useable_key := false;
-- Failed not null check...
WHEN not_null_violation THEN
RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('column %s contains nulls', const.pkey);
useable_key := false;
-- Other fatal error
WHEN others THEN
@@ -574,7 +535,7 @@ BEGIN
-- Clean up test constraint
IF useable_key THEN
PERFORM _CDB_SQL(Format('ALTER TABLE %s DROP CONSTRAINT %s_unique', reloid::text, const.pkey));
PERFORM _CDB_SQL(Format('ALTER TABLE %s DROP CONSTRAINT %s_pk', reloid::text, const.pkey));
-- Move non-unique column out of the way
ELSE
@@ -585,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;
@@ -602,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;
@@ -768,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): %',
@@ -780,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): %',
@@ -850,8 +811,7 @@ DECLARE
destname TEXT;
destseq TEXT;
destseqmax INTEGER;
salt TEXT := md5(random()::text || now());
copyname TEXT;
column_name_sql TEXT;
@@ -957,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);
@@ -1109,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

@@ -0,0 +1,48 @@
----------------------------------
-- CONF MANAGEMENT FUNCTIONS
--
-- Meant to be used by superadmin user.
-- Functions needing reading configuration should use SECURITY DEFINER.
----------------------------------
-- This will trigger NOTICE if cartodb.CDB_CONF already exists
DO LANGUAGE 'plpgsql' $$
BEGIN
CREATE TABLE IF NOT EXISTS cartodb.CDB_CONF ( KEY TEXT PRIMARY KEY, VALUE JSON NOT NULL );
END
$$;
-- This can only be called from an SQL script executed by CREATE EXTENSION
DO LANGUAGE 'plpgsql' $$
BEGIN
PERFORM pg_catalog.pg_extension_config_dump('cartodb.CDB_CONF', '');
END
$$;
CREATE OR REPLACE
FUNCTION cartodb.CDB_Conf_SetConf(key text, value JSON)
RETURNS void AS $$
BEGIN
PERFORM cartodb.CDB_Conf_RemoveConf(key);
EXECUTE 'INSERT INTO cartodb.CDB_CONF (KEY, VALUE) VALUES ($1, $2);' USING key, value;
END
$$ LANGUAGE PLPGSQL VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb.CDB_Conf_RemoveConf(key text)
RETURNS void AS $$
BEGIN
EXECUTE 'DELETE FROM cartodb.CDB_CONF WHERE KEY = $1;' USING key;
END
$$ LANGUAGE PLPGSQL VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb.CDB_Conf_GetConf(key text)
RETURNS JSON AS $$
DECLARE
value JSON;
BEGIN
EXECUTE 'SELECT VALUE FROM cartodb.CDB_CONF WHERE KEY = $1;' INTO value USING key;
RETURN value;
END
$$ LANGUAGE PLPGSQL STABLE;

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

@@ -13,3 +13,19 @@ RETURN output;
END;
$$
LANGUAGE 'plpgsql' STABLE STRICT;
-- Convert timestamp with time zone to double precision
--
CREATE OR REPLACE FUNCTION CDB_DateToNumber(input timestamp with time zone)
RETURNS double precision AS $$
DECLARE output double precision;
BEGIN
BEGIN
SELECT extract (EPOCH FROM input) INTO output;
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
RETURN output;
END;
$$
LANGUAGE 'plpgsql' STABLE STRICT;

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,252 @@
----------------------------------
-- GROUP MANAGEMENT FUNCTIONS
--
-- Meant to be used by org admin. See CDB_Organization_AddAdmin.
----------------------------------
-- Creates a new group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_CreateGroup(group_name text)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
EXECUTE format('CREATE ROLE %I NOLOGIN;', group_role);
PERFORM cartodb._CDB_Group_CreateGroup_API(group_name, group_role);
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Drops group and everything that role owns
-- TODO: LIMITATION: in order to drop a role all its owned objects must be dropped before.
-- Right now this is done with DROP OWNED, which can only be done by a superadmin.
-- Not even the role creator can drop the role and the objects it owns.
-- All group owned objects by the group are permissions.
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_DropGroup(group_name text)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
EXECUTE format('DROP OWNED BY %I', group_role);
EXECUTE format('DROP ROLE IF EXISTS %I', group_role);
PERFORM cartodb._CDB_Group_DropGroup_API(group_name);
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Renames a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_RenameGroup(old_group_name text, new_group_name text)
RETURNS VOID AS $$
DECLARE
old_group_role TEXT;
new_group_role TEXT;
BEGIN
old_group_role = cartodb._CDB_Group_GroupRole(old_group_name);
new_group_role = cartodb._CDB_Group_GroupRole(new_group_name);
EXECUTE format('ALTER ROLE %I RENAME TO %I', old_group_role, new_group_role);
PERFORM cartodb._CDB_Group_RenameGroup_API(old_group_name, new_group_name, new_group_role);
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Adds users to a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_AddUsers(group_name text, usernames text[])
RETURNS VOID AS $$
DECLARE
group_role TEXT;
user_role TEXT;
username TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
foreach username in array usernames
loop
user_role := cartodb._CDB_User_RoleFromUsername(username);
IF(group_role IS NULL OR user_role IS NULL)
THEN
RAISE EXCEPTION 'Group role (%) and user role (%) must be already existing', group_role, user_role;
END IF;
EXECUTE format('GRANT %I TO %I', group_role, user_role);
end loop;
PERFORM cartodb._CDB_Group_AddUsers_API(group_name, usernames);
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Removes users from a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_RemoveUsers(group_name text, usernames text[])
RETURNS VOID AS $$
DECLARE
group_role TEXT;
user_role TEXT;
username TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
foreach username in array usernames
loop
user_role := cartodb._CDB_User_RoleFromUsername(username);
EXECUTE format('REVOKE %I FROM %I', group_role, user_role);
end loop;
PERFORM cartodb._CDB_Group_RemoveUsers_API(group_name, usernames);
END
$$ LANGUAGE PLPGSQL VOLATILE;
----------------------------------
-- TABLE MANAGEMENT FUNCTIONS
--
-- Meant to be used by table owners.
----------------------------------
-- Grants table read permission to a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_Table_GrantRead(group_name text, username text, table_name text)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
PERFORM cartodb._CDB_Group_Table_GrantRead(group_name, username, table_name, true);
END
$$ LANGUAGE PLPGSQL VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_Table_GrantRead(group_name text, username text, table_name text, sync boolean)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', username, group_role);
EXECUTE format('GRANT SELECT ON TABLE %I.%I TO %I', username, table_name, group_role );
IF(sync) THEN
PERFORM cartodb._CDB_Group_Table_GrantPermission_API(group_name, username, table_name, 'r');
END IF;
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Grants table write permission to a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_Table_GrantReadWrite(group_name text, username text, table_name text)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
PERFORM cartodb._CDB_Group_Table_GrantReadWrite(group_name, username, table_name, true);
END
$$ LANGUAGE PLPGSQL VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_Table_GrantReadWrite(group_name text, username text, table_name text, sync boolean)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', username, group_role);
EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE %I.%I TO %I', username, table_name, group_role);
PERFORM cartodb._CDB_Group_TableSequences_Permission(group_name, username, table_name, true);
IF(sync) THEN
PERFORM cartodb._CDB_Group_Table_GrantPermission_API(group_name, username, table_name, 'w');
END IF;
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Granting and revoking permissions on sequences
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_TableSequences_Permission(group_name text, username text, table_name text, do_grant bool)
RETURNS VOID AS $$
DECLARE
column_name TEXT;
sequence_name TEXT;
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
FOR column_name IN EXECUTE 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = current_database() AND TABLE_SCHEMA = $1 AND TABLE_NAME = $2 AND COLUMN_DEFAULT LIKE ''nextval%''' USING username, table_name
LOOP
EXECUTE format('SELECT PG_GET_SERIAL_SEQUENCE(''%I.%I'', ''%I'')', username, table_name, column_name) INTO sequence_name;
IF sequence_name IS NOT NULL THEN
IF do_grant THEN
-- Here %s is needed since sequence_name has quotes
EXECUTE format('GRANT USAGE, SELECT, UPDATE ON SEQUENCE %s TO %I', sequence_name, group_role);
ELSE
EXECUTE format('REVOKE ALL ON SEQUENCE %s FROM %I', sequence_name, group_role);
END IF;
END IF;
END LOOP;
RETURN;
END
$$ LANGUAGE PLPGSQL VOLATILE;
-- Revokes all permissions on a table from a group
CREATE OR REPLACE
FUNCTION cartodb.CDB_Group_Table_RevokeAll(group_name text, username text, table_name text)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
PERFORM cartodb._CDB_Group_Table_RevokeAll(group_name, username, table_name, true);
END
$$ LANGUAGE PLPGSQL VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_Table_RevokeAll(group_name text, username text, table_name text, sync boolean)
RETURNS VOID AS $$
DECLARE
group_role TEXT;
BEGIN
group_role := cartodb._CDB_Group_GroupRole(group_name);
EXECUTE format('REVOKE ALL ON TABLE %I.%I FROM %I', username, table_name, group_role);
PERFORM cartodb._CDB_Group_TableSequences_Permission(group_name, username, table_name, false);
IF(sync) THEN
PERFORM cartodb._CDB_Group_Table_RevokeAllPermission_API(group_name, username, table_name);
END IF;
END
$$ LANGUAGE PLPGSQL VOLATILE;
-----------------------
-- Helper functions
-----------------------
-- Given a group name returns a role. group_name must be a valid PostgreSQL idenfifier. See http://www.postgresql.org/docs/9.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_GroupRole(group_name text)
RETURNS TEXT AS $$
DECLARE
group_role TEXT;
prefix TEXT;
max_length constant INTEGER := 63;
BEGIN
prefix = format('%s_g_', cartodb._CDB_Group_ShortDatabaseName());
group_role := format('%s%s', prefix, group_name);
IF LENGTH(group_role) > max_length
THEN
RAISE EXCEPTION 'Group name must be shorter. It can''t have more than % characters, but it is longer (%): %', max_length - LENGTH(prefix), length(group_name), group_name;
END IF;
RETURN group_role;
END
$$ LANGUAGE PLPGSQL;
-- Returns the first owner of the schema matching username. Organization user schemas must have one only owner.
CREATE OR REPLACE
FUNCTION cartodb._CDB_User_RoleFromUsername(username text)
RETURNS TEXT AS $$
DECLARE
user_role TEXT;
BEGIN
-- This was preferred, but non-superadmins won't get results
-- SELECT SCHEMA_OWNER FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = $1 LIMIT 1'
SELECT pg_get_userbyid(nspowner) FROM pg_namespace WHERE nspname = username INTO user_role;
RETURN user_role;
END
$$ LANGUAGE PLPGSQL;
-- Database names are too long, we need a shorter version for composing role names
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_ShortDatabaseName()
RETURNS TEXT AS $$
DECLARE
short_database_name TEXT;
BEGIN
SELECT md5(current_database()) INTO short_database_name;
RETURN short_database_name;
END
$$ LANGUAGE PLPGSQL;

View File

@@ -0,0 +1,195 @@
----------------------------------
-- GROUP METADATA API FUNCTIONS
--
-- Meant to be used by CDB_Group_* functions to sync data with the editor.
-- Requires configuration parameter. Example: SELECT cartodb.CDB_Conf_SetConf('groups_api', '{ "host": "127.0.0.1", "port": 3000, "timeout": 10, "username": "extension", "password": "elephant" }');
----------------------------------
-- TODO: delete this development cleanup before final merge
DROP FUNCTION IF EXISTS cartodb.CDB_Group_AddMember(group_name text, username text);
DROP FUNCTION IF EXISTS cartodb.CDB_Group_RemoveMember(group_name text, username text);
DROP FUNCTION IF EXISTS cartodb._CDB_Group_AddMember_API(group_name text, username text);
DROP FUNCTION IF EXISTS cartodb._CDB_Group_RemoveMember_API(group_name text, username text);
-- Sends the create group request
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_CreateGroup_API(group_name text, group_role text)
RETURNS VOID AS
$$
import string
url = '/api/v1/databases/{0}/groups'
body = '{ "name": "%s", "database_role": "%s" }' % (group_name, group_role)
query = "select cartodb._CDB_Group_API_Request('POST', '%s', '%s', '{200, 409}') as response_status" % (url, body)
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_DropGroup_API(group_name text)
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s' % (urllib.pathname2url(group_name))
query = "select cartodb._CDB_Group_API_Request('DELETE', '%s', '', '{204, 404}') as response_status" % url
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_RenameGroup_API(old_group_name text, new_group_name text, new_group_role text)
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s' % (urllib.pathname2url(old_group_name))
body = '{ "name": "%s", "database_role": "%s" }' % (new_group_name, new_group_role)
query = "select cartodb._CDB_Group_API_Request('PUT', '%s', '%s', '{200, 409}') as response_status" % (url, body)
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_AddUsers_API(group_name text, usernames text[])
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s/users' % (urllib.pathname2url(group_name))
body = "{ \"users\": [\"%s\"] }" % "\",\"".join(usernames)
query = "select cartodb._CDB_Group_API_Request('POST', '%s', '%s', '{200, 409}') as response_status" % (url, body)
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_RemoveUsers_API(group_name text, usernames text[])
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s/users' % (urllib.pathname2url(group_name))
body = "{ \"users\": [\"%s\"] }" % "\",\"".join(usernames)
query = "select cartodb._CDB_Group_API_Request('DELETE', '%s', '%s', '{200, 404}') as response_status" % (url, body)
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
DO LANGUAGE 'plpgsql' $$
BEGIN
-- Needed for dropping type
DROP FUNCTION IF EXISTS cartodb._CDB_Group_API_Conf();
DROP TYPE IF EXISTS _CDB_Group_API_Params;
END
$$;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_Table_GrantPermission_API(group_name text, username text, table_name text, access text)
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s/permission/%s/tables/%s' % (urllib.pathname2url(group_name), username, table_name)
body = '{ "access": "%s" }' % access
query = "select cartodb._CDB_Group_API_Request('PUT', '%s', '%s', '{200, 409}') as response_status" % (url, body)
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
DO LANGUAGE 'plpgsql' $$
BEGIN
-- Needed for dropping type
DROP FUNCTION IF EXISTS cartodb._CDB_Group_API_Conf();
DROP TYPE IF EXISTS _CDB_Group_API_Params;
END
$$;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_Table_RevokeAllPermission_API(group_name text, username text, table_name text)
RETURNS VOID AS
$$
import string
import urllib
url = '/api/v1/databases/{0}/groups/%s/permission/%s/tables/%s' % (urllib.pathname2url(group_name), username, table_name)
query = "select cartodb._CDB_Group_API_Request('DELETE', '%s', '', '{200, 404}') as response_status" % url
plpy.execute(query)
$$ LANGUAGE 'plpythonu' VOLATILE SECURITY DEFINER;
DO LANGUAGE 'plpgsql' $$
BEGIN
-- Needed for dropping type
DROP FUNCTION IF EXISTS cartodb._CDB_Group_API_Conf();
DROP TYPE IF EXISTS _CDB_Group_API_Params;
END
$$;
CREATE TYPE _CDB_Group_API_Params AS (
host text,
port int,
timeout int,
auth text
);
-- This must be explicitally extracted because "composite types are currently not supported".
-- See http://www.postgresql.org/docs/9.3/static/plpython-database.html.
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_API_Conf()
RETURNS _CDB_Group_API_Params AS
$$
conf = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('groups_api') conf")[0]['conf']
if conf is None:
return None
else:
import json
params = json.loads(conf)
auth = 'Basic %s' % plpy.execute("SELECT cartodb._CDB_Group_API_Auth('%s', '%s') as auth" % (params['username'], params['password']))[0]['auth']
return { "host": params['host'], "port": params['port'], 'timeout': params['timeout'], 'auth': auth }
$$ LANGUAGE 'plpythonu' VOLATILE;
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_API_Auth(username text, password text)
RETURNS TEXT AS
$$
import base64
return base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
$$ LANGUAGE 'plpythonu' VOLATILE;
-- url must contain a '%s' placeholder that will be replaced by current_database, for security reasons.
CREATE OR REPLACE
FUNCTION cartodb._CDB_Group_API_Request(method text, url text, body text, valid_return_codes int[])
RETURNS int AS
$$
import httplib
params = plpy.execute("select c.host, c.port, c.timeout, c.auth from cartodb._CDB_Group_API_Conf() c;")[0]
if params['host'] is None:
return None
headers = { 'Authorization': params['auth'], 'Content-Type': 'application/json', 'X-Forwarded-Proto': 'https' }
retry = 3
last_err = None
while retry > 0:
try:
client = SD['groups_api_client'] = httplib.HTTPConnection(params['host'], params['port'], False, params['timeout'])
database_name = plpy.execute("select current_database();")[0]['current_database']
client.request(method, url.format(database_name), body, headers)
response = client.getresponse()
assert response.status in valid_return_codes
return response.status
except Exception as err:
retry -= 1
last_err = err
plpy.warning('Retrying after: ' + str(err))
client = SD['groups_api_client'] = None
if last_err is not None:
plpy.error('Fatal Group API error: ' + str(last_err))
raise last_err
return None
$$ LANGUAGE 'plpythonu' VOLATILE;
revoke all on function cartodb._CDB_Group_API_Request(text, text, text, int[]) from public;

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

@@ -1,14 +1,16 @@
CREATE OR REPLACE
FUNCTION cartodb.CDB_Organization_Member_Group_Role_Member_Name()
RETURNS TEXT
AS 'SELECT ''cdb_org_member''::text || ''_'' || md5(current_database());'
AS $$
SELECT 'cdb_org_member'::text || '_' || md5(current_database());
$$
LANGUAGE SQL IMMUTABLE;
DO LANGUAGE 'plpgsql' $$
DECLARE
cdb_org_member_role_name TEXT;
BEGIN
cdb_org_member_role_name := cartodb.CDB_Organization_Member_Group_Role_Member_Name();
cdb_org_member_role_name := cartodb.CDB_Organization_Member_Group_Role_Member_Name();
IF NOT EXISTS ( SELECT * FROM pg_roles WHERE rolname= cdb_org_member_role_name )
THEN
EXECUTE 'CREATE ROLE "' || cdb_org_member_role_name || '" NOLOGIN;';
@@ -25,6 +27,60 @@ BEGIN
END
$$ LANGUAGE PLPGSQL VOLATILE;
-------------------------------------------------------------------------------
-- Administrator
-------------------------------------------------------------------------------
CREATE OR REPLACE
FUNCTION cartodb._CDB_Organization_Admin_Role_Name()
RETURNS TEXT
AS $$
SELECT current_database() || '_a'::text;
$$
LANGUAGE SQL IMMUTABLE;
-- Administrator role creation on extension install
DO LANGUAGE 'plpgsql' $$
DECLARE
cdb_org_admin_role_name TEXT;
BEGIN
cdb_org_admin_role_name := cartodb._CDB_Organization_Admin_Role_Name();
IF NOT EXISTS ( SELECT * FROM pg_roles WHERE rolname= cdb_org_admin_role_name )
THEN
EXECUTE format('CREATE ROLE %I CREATEROLE NOLOGIN;', cdb_org_admin_role_name);
END IF;
END
$$;
CREATE OR REPLACE
FUNCTION cartodb.CDB_Organization_AddAdmin(username text)
RETURNS void
AS $$
DECLARE
cdb_user_role TEXT;
cdb_admin_role TEXT;
BEGIN
cdb_admin_role := cartodb._CDB_Organization_Admin_Role_Name();
cdb_user_role := cartodb._CDB_User_RoleFromUsername(username);
EXECUTE format('GRANT %I TO %I WITH ADMIN OPTION', cdb_admin_role, cdb_user_role);
-- CREATEROLE is not inherited, and is needed for user creation
EXECUTE format('ALTER ROLE %I CREATEROLE', cdb_user_role);
END
$$ LANGUAGE PLPGSQL;
CREATE OR REPLACE
FUNCTION cartodb.CDB_Organization_RemoveAdmin(username text)
RETURNS void
AS $$
DECLARE
cdb_user_role TEXT;
cdb_admin_role TEXT;
BEGIN
cdb_admin_role := cartodb._CDB_Organization_Admin_Role_Name();
cdb_user_role := cartodb._CDB_User_RoleFromUsername(username);
EXECUTE format('ALTER ROLE %I NOCREATEROLE', cdb_user_role);
EXECUTE format('REVOKE %I FROM %I', cdb_admin_role, cdb_user_role);
END
$$ LANGUAGE PLPGSQL;
-------------------------------------------------------------------------------
-- Sharing tables

View File

@@ -15,7 +15,7 @@ FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND c.relname NOT IN ('cdb_tablemetadata', 'spatial_ref_sys')
AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'topology')
AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'topology', 'cartodb')
AND CASE WHEN perm = 'public' THEN has_table_privilege('publicuser', c.oid, 'SELECT')
WHEN perm = 'private' THEN has_table_privilege(current_user, c.oid, 'SELECT') AND NOT has_table_privilege('publicuser', c.oid, 'SELECT')
WHEN perm = 'all' THEN has_table_privilege(current_user, c.oid, 'SELECT') OR has_table_privilege('publicuser', c.oid, 'SELECT')

View File

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

View File

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

View File

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

View File

@@ -0,0 +1 @@
../scripts-available/CDB_Groups_API.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
@@ -250,7 +250,7 @@ INSERT INTO existing_cartodb_id (cartodb_id, description) VALUES
(20, 'b'),
(30, 'c');
SELECT CDB_CartodbfyTableCheck('existing_cartodb_id', 'Existing cartodb_id values are respected #138');
SELECT * from existing_cartodb_id;
SELECT cartodb_id,the_geom,the_geom_webmercator,description,name from existing_cartodb_id;
DROP TABLE existing_cartodb_id;
-- Table with both the_geom and wkb_geometry
@@ -281,6 +281,85 @@ INSERT INTO many_colliding_columns VALUES (
SELECT CDB_CartodbfyTableCheck('many_colliding_columns', 'Many colliding columns #141');
DROP TABLE many_colliding_columns;
-- Table with null cartodb_id
CREATE TABLE test (
cartodb_id integer
);
INSERT INTO test VALUES
(1),
(2),
(NULL),
(3);
SELECT CDB_CartodbfyTableCheck('test', 'Table with null cartodb_id #148');
SELECT cartodb_id, cartodb_id_0 from test;
DROP TABLE test;
-- Table with non unique cartodb_id
CREATE TABLE test (
cartodb_id integer
);
INSERT INTO test VALUES
(1),
(2),
(2);
SELECT CDB_CartodbfyTableCheck('test', 'Table with non unique cartodb_id #148');
SELECT cartodb_id, cartodb_id_0 from test;
DROP TABLE test;
-- Table with non unique and null cartodb_id
CREATE TABLE test (
cartodb_id integer
);
INSERT INTO test VALUES
(1),
(2),
(NULL),
(2);
SELECT CDB_CartodbfyTableCheck('test', 'Table with non unique and null cartodb_id #148');
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

@@ -79,5 +79,58 @@ CREATE TABLE
INSERT 0 1
Many colliding columns #141 cartodbfied fine
DROP TABLE
CREATE TABLE
INSERT 0 4
Table with null cartodb_id #148 cartodbfied fine
1|1
2|2
3|
4|3
DROP TABLE
CREATE TABLE
INSERT 0 3
Table with non unique cartodb_id #148 cartodbfied fine
1|1
2|2
3|2
DROP TABLE
CREATE TABLE
INSERT 0 4
Table with non unique and null cartodb_id #148 cartodbfied fine
1|1
2|2
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

View File

@@ -0,0 +1,2 @@
SELECT * FROM CDB_DateToNumber('1999-01-08 00:00:00'::timestamp);
SELECT * FROM CDB_DateToNumber('1999-01-08 00:00:00+05'::timestamp with time zone);

View File

@@ -0,0 +1,2 @@
915753600
915735600

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

@@ -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

View File

@@ -28,6 +28,7 @@ function clear_partial_result() {
function sql() {
local ROLE
local QUERY
ERROR_OUTPUT_FILE='/tmp/test_error.log'
if [[ $# -ge 2 ]]
then
ROLE="$1"
@@ -37,15 +38,40 @@ function sql() {
fi
if [ -n "${ROLE}" ]; then
log_debug "Executing query '${QUERY}' as ${ROLE}"
RESULT=`${CMD} -U "${ROLE}" ${DATABASE} -c "${QUERY}" -A -t`
log_debug "Executing query '${QUERY}' as ${ROLE}"
RESULT=`${CMD} -U "${ROLE}" ${DATABASE} -c "${QUERY}" -A -t 2>"${ERROR_OUTPUT_FILE}"`
else
log_debug "Executing query '${QUERY}'"
RESULT=`${CMD} ${DATABASE} -c "${QUERY}" -A -t`
log_debug "Executing query '${QUERY}'"
RESULT=`${CMD} ${DATABASE} -c "${QUERY}" -A -t 2>"${ERROR_OUTPUT_FILE}"`
fi
CODERESULT=$?
ERROR_OUTPUT=`cat "${ERROR_OUTPUT_FILE}"`
rm ${ERROR_OUTPUT_FILE}
echo ${RESULT}
echo -n "> Code Result: "
echo -n ${CODERESULT}
echo -n "; Result: "
echo -n ${RESULT}
echo -n "; Error output: "
echo -n ${ERROR_OUTPUT}
# Some warnings should actually be failures
if [[ ${CODERESULT} == "0" ]]
then
case "${ERROR_OUTPUT}" in
WARNING:*no*privileges*were*granted*for*)
echo -n "FAILED BECAUSE OF PRIVILEGES GRANTING WARNING"
CODERESULT=1
;;
WARNING:*no*privileges*could*be*revoked*for*)
echo -n "FAILED BECAUSE OF PRIVILEGES REVOKING WARNING"
CODERESULT=1
;;
*) ;;
esac
echo -n "; Code result after warnings: "
echo -n ${CODERESULT}
fi
echo
if [[ ${CODERESULT} -ne 0 ]]
@@ -133,13 +159,18 @@ function create_table() {
function setup() {
${CMD} -c "CREATE DATABASE ${DATABASE}"
sql "CREATE SCHEMA cartodb;"
sql "CREATE EXTENSION plpythonu;"
sql "GRANT USAGE ON SCHEMA cartodb TO public;"
log_info "########################### BOOTSTRAP ###########################"
${CMD} -d ${DATABASE} -f scripts-available/CDB_Organizations.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_Conf.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_Groups.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_Groups_API.sql
log_info "############################# SETUP #############################"
create_role_and_schema cdb_org_admin
sql "SELECT cartodb.CDB_Organization_AddAdmin('cdb_org_admin');"
create_role_and_schema cdb_testmember_1
create_role_and_schema cdb_testmember_2
sql "CREATE ROLE publicuser LOGIN;"
@@ -152,8 +183,16 @@ function setup() {
create_table cdb_testmember_2 bar
sql cdb_testmember_2 'INSERT INTO bar VALUES (1), (2), (3), (4), (5);'
sql cdb_testmember_2 'SELECT * FROM cdb_testmember_2.bar;'
sql "SELECT cartodb.CDB_Group_CreateGroup('group_a_tmp')"
sql "SELECT cartodb.CDB_Group_RenameGroup('group_a_tmp', 'group_a')"
sql "SELECT cartodb.CDB_Group_AddUsers('group_a', ARRAY['cdb_testmember_1'])"
sql "SELECT cartodb.CDB_Group_CreateGroup('group_b')"
}
function tear_down() {
log_info "########################### USER TEAR DOWN ###########################"
sql cdb_testmember_1 "SELECT * FROM cartodb.CDB_Organization_Remove_Access_Permission('cdb_testmember_1', 'foo', 'cdb_testmember_2');"
@@ -162,19 +201,29 @@ function tear_down() {
sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.foo;'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.bar;'
sql "select cartodb.CDB_Group_DropGroup('group_b')"
sql "SELECT cartodb.CDB_Group_RemoveUsers('group_a', ARRAY['cdb_testmember_1'])"
sql "select cartodb.CDB_Group_DropGroup('group_a')"
sql "SELECT cartodb.CDB_Organization_RemoveAdmin('cdb_org_admin');"
sql "DROP SCHEMA cartodb CASCADE"
log_info "########################### TEAR DOWN ###########################"
sql 'DROP SCHEMA cdb_testmember_1;'
sql 'DROP SCHEMA cdb_testmember_2;'
sql 'DROP SCHEMA cdb_org_admin;'
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_1;"
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_2;"
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM publicuser;"
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_org_admin;"
sql 'DROP ROLE cdb_testmember_1;'
sql 'DROP ROLE cdb_testmember_2;'
sql 'DROP ROLE publicuser;'
sql 'DROP ROLE cdb_org_admin;'
${CMD} -c "DROP DATABASE ${DATABASE}"
}
@@ -198,6 +247,7 @@ function run_tests() {
echo "####################################################################"
clear_partial_result
setup
log_info "############################# TESTS #############################"
eval ${t}
if [[ ${PARTIALOK} -ne 0 ]]
then
@@ -330,21 +380,18 @@ function test_user_can_read_when_it_has_permission_after_organization_permission
}
function test_cdb_querytables_returns_schema_and_table_name() {
sql "CREATE EXTENSION plpythonu;"
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql cdb_testmember_1 "select * from CDB_QueryTables('select * from foo');" should "{cdb_testmember_1.foo}"
}
function test_cdb_querytables_returns_schema_and_table_name_for_several_schemas() {
sql "CREATE EXTENSION plpythonu;"
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql postgres "select * from CDB_QueryTables('select * from cdb_testmember_1.foo, cdb_testmember_2.bar');" should "{cdb_testmember_1.foo,cdb_testmember_2.bar}"
}
function test_cdb_querytables_does_not_return_functions_as_part_of_the_resultset() {
sql "CREATE EXTENSION plpythonu;"
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql postgres "select * from CDB_QueryTables('select * from cdb_testmember_1.foo, cdb_testmember_2.bar, plainto_tsquery(''foo'')');" should "{cdb_testmember_1.foo,cdb_testmember_2.bar}"
@@ -393,6 +440,107 @@ function test_cdb_usertables_should_work_with_orgusers() {
sql cdb_testmember_1 "DROP TABLE test_perms_priv"
}
function test_CDB_Group_Table_GrantRead_should_grant_select_and_RevokeAll_should_remove_it() {
create_table cdb_testmember_2 shared_with_group
sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' fails
sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;'
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;'
sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;'
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_RevokeAll('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' fails
sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.shared_with_group;'
}
function test_CDB_Group_Table_GrantReadWrite_should_grant_insert_and_RevokeAll_should_remove_it() {
create_table cdb_testmember_2 shared_with_group
sql cdb_testmember_1 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)' fails
sql cdb_testmember_2 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)'
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_GrantReadWrite('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_testmember_1 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)'
sql cdb_testmember_2 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)'
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_RevokeAll('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_testmember_1 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)' fails
sql cdb_testmember_2 'INSERT INTO cdb_testmember_2.shared_with_group VALUES (1), (2), (3), (4), (5)'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.shared_with_group;'
}
function test_group_management_functions_cant_be_used_by_normal_members() {
sql cdb_testmember_1 "SELECT cartodb.CDB_Group_CreateGroup('group_x_1');" fails
sql cdb_testmember_1 "SELECT cartodb.CDB_Group_RenameGroup('group_a', 'group_x_2');" fails
sql cdb_testmember_1 "SELECT cartodb.CDB_Group_DropGroup('group_a');" fails
sql cdb_testmember_1 "SELECT cartodb.CDB_Group_AddUsers('group_a', ARRAY['cdb_testmember_2']);" fails
sql cdb_testmember_1 "SELECT cartodb.CDB_Group_RemoveUsers('group_a', ARRAY['cdb_testmember_1']);" fails
}
function test_group_permission_functions_cant_be_used_by_normal_members() {
create_table cdb_testmember_2 shared_with_group
sql cdb_testmember_1 "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_testmember_1 "select cartoDB.CDB_Group_Table_GrantReadWrite('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
# Checks that you can't grant even if your group has RW permissions
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_GrantReadWrite('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_testmember_1 "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_testmember_1 "select cartoDB.CDB_Group_Table_GrantReadWrite('group_b', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_testmember_1 "select cartoDB.CDB_Group_Table_RevokeAll('group_b', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.shared_with_group;'
}
function test_group_management_functions_can_be_used_by_org_admin() {
sql cdb_org_admin "SELECT cartodb.CDB_Group_CreateGroup('group_x_tmp');"
sql cdb_org_admin "SELECT cartodb.CDB_Group_RenameGroup('group_x_tmp', 'group_x');"
sql cdb_org_admin "SELECT cartodb.CDB_Group_AddUsers('group_x', ARRAY['cdb_testmember_1', 'cdb_testmember_2']);"
sql cdb_org_admin "SELECT cartodb.CDB_Group_RemoveUsers('group_x', ARRAY['cdb_testmember_1', 'cdb_testmember_2']);"
# TODO: workaround superadmin limitation
sql "SELECT cartodb.CDB_Group_DropGroup('group_x');"
}
function test_org_admin_cant_grant_permissions_on_tables_he_does_not_own() {
create_table cdb_testmember_2 shared_with_group
sql cdb_org_admin "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_org_admin "select cartoDB.CDB_Group_Table_GrantReadWrite('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
# Checks that you can't grant even if your group has RW permissions
sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_GrantReadWrite('group_a', 'cdb_testmember_2', 'shared_with_group')"
sql cdb_org_admin "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_org_admin "select cartoDB.CDB_Group_Table_GrantReadWrite('group_b', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_org_admin "select cartoDB.CDB_Group_Table_RevokeAll('group_b', 'cdb_testmember_2', 'shared_with_group');" fails
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.shared_with_group;'
}
function test_valid_group_names() {
sql postgres "select cartodb._CDB_Group_GroupRole('group_1$_a');"
sql postgres "select cartodb._CDB_Group_GroupRole('GROUP_1$_A');"
sql postgres "select cartodb._CDB_Group_GroupRole('_group_1$_a');"
}
function test_administrator_name_generation() {
sql postgres "select cartodb._CDB_Organization_Admin_Role_Name();"
}
function test_conf() {
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf')" should ''
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf_2')" should ''
sql postgres "SELECT cartodb.CDB_Conf_SetConf('test_conf', '{ \"a_key\": \"test_val\" }')"
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf')" should '{ "a_key": "test_val" }'
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf_2')" should ''
sql postgres "SELECT cartodb.CDB_Conf_RemoveConf('test_conf')"
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf')" should ''
sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf_2')" should ''
}
#################################################### TESTS END HERE ####################################################