Compare commits

...

376 Commits

Author SHA1 Message Date
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
Rafa de la Torre
7d106e68b0 Merge pull request #161 from CartoDB/160-add-drop-function-if-exists
Add DROP FUNCTION back to allow migrations #160
2015-09-24 18:26:30 +02:00
Rafa de la Torre
567e815fd0 Add DROP FUNCTION back to allow migrations #160 2015-09-24 17:56:00 +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
Rafa de la Torre
255618f57d Merge pull request #159 from CartoDB/fix-type-already-exists
Fix creation of type _cdb_has_usable_geom_record
2015-09-21 14:50:44 +02:00
Juan Ignacio Sánchez Lara
bf4f30c99d Removed IMMUTABLE for functions depending on current database 2015-09-21 14:35:28 +02:00
Rafa de la Torre
5ea1b7d4d7 Fix creation of type _cdb_has_usable_geom_record
Fix the ERROR:  type "_cdb_has_usable_geom_record" already exists by
checking for existence before. Duly noted for upgrades.
2015-09-21 14:16:32 +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
0c14df5f89 Fix upgrade from 0.10.0 to 0.10.1 2015-09-16 14:40:18 +02:00
Rafa de la Torre
c2780773d2 Update NEWS.md and version to 0.10.1 2015-09-16 12:40:14 +02:00
Rafa de la Torre
14508ff5f3 Merge pull request #152 from CartoDB/141-fix-table-multiple-geometry-columns
141 fix table multiple geometry columns
2015-09-16 12:22:49 +02:00
Rafa de la Torre
6ba809e798 Remove usage of _CDB_Geometry_SRID #154
This is only used from _CDB_Has_Usable_Geom. It doesn't do what's
promised in the comment. The effect is that a column is taken as valid
when it actually needs setting its SRID restriction so better not use
it as it will need rewrite anyway.
2015-09-16 12:17:40 +02:00
Rafa de la Torre
c8e3cf5500 Add test courtesy of Paul #154 2015-09-16 12:17:35 +02:00
Rafa de la Torre
d268497030 Add expectation for new test #141 2015-09-15 19:14:06 +02:00
Rafa de la Torre
fa514a3b7c Add a couple of NOTICE's to expectations #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
0ebd12a0eb Avoid double-escaping of reloid::text #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
e7c974e957 Fix silly typo #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
789e89a5d2 Create a return type for _cdb_has_usable_geom_record #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
3fdce65368 Move column renaming out of _CDB_Has_Usable_Geom #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
5caddc6cc7 Fix for MultiPoint geometry issue #141 2015-09-15 18:49:59 +02:00
Rafa de la Torre
9d8d79eb40 Slightly improve the test #141 2015-09-14 17:55:30 +02:00
Rafa de la Torre
1596bd56d8 Improve another EXECUTE+FOUND #141 2015-09-14 17:54:35 +02:00
Rafa de la Torre
dfd0454be3 Improve comment #141 2015-09-14 17:53:34 +02:00
Rafa de la Torre
731ee0a9ba Fix the_geom_webmercator already exists #141 2015-09-14 17:06:24 +02:00
Rafa de la Torre
e3bba2ee4b Fix the_geom already exists error #141 2015-09-14 17:05:14 +02:00
Rafa de la Torre
581835d4ff Extract query into _cdb_geom_candidate_columns #141 2015-09-14 11:50:10 +02:00
Rafa de la Torre
9ec24c1aff Fix FOUND in _CDB_Geometry_SRID #141 2015-09-14 11:18:12 +02:00
Rafa de la Torre
e546c15770 Test for failing scenario #141 2015-09-11 16:16:54 +02:00
Rafa de la Torre
c12ae7f4a8 Merge pull request #146 from CartoDB/138-fix-cartodbfy-no-default-seq-value3
138 fix cartodbfy no default seq value3
2015-09-11 11:00:04 +02:00
Rafa de la Torre
7a247c1ab2 Recover usage of cartodb id if has_usable_primary_key #138 2015-09-10 18:20:52 +02:00
Rafa de la Torre
85b206fdba Improve test about existing cartodb_id values #138 2015-09-10 18:18:13 +02:00
Rafa de la Torre
75b37d5a88 Improve tests #138 2015-09-09 18:34:55 +02:00
Rafa de la Torre
ef21128099 Explicitly check if there's a sequence on PK #138 2015-09-09 18:33:06 +02:00
Rafa de la Torre
497034c285 Add test for failing scenario #138 2015-09-09 18:33:06 +02:00
Rafa de la Torre
6e4a5b5635 Add CASCADE to DROP SCHEMA... in tear_down #138 2015-09-09 18:33:06 +02:00
Raul Ochoa
d67f097703 Merge pull request #145 from CartoDB/fix-cdb_stats-test
Do not use random() for the distribution to test CDB_Stats functions
2015-09-09 17:12:07 +02:00
Alejandro Martínez
c460b59c07 Merge pull request #143 from CartoDB/readd-update-updated-at
Readd update_updated_at function (still used by old tables)
2015-09-09 17:09:06 +02:00
Raul Ochoa
1853ee6306 Do not use random() for the distribution to test CDB_Stats functions
Fixes #144
2015-09-09 17:08:32 +02:00
Alejandro Martínez
9ec5d9000a Readd update_updated_at function (still used by old tables) 2015-09-09 14:56:34 +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
Raul Ochoa
0ec579984b Stubs next version 2015-09-07 13:17:22 +02:00
Raul Ochoa
c6f2903221 Release 0.10.0 2015-09-07 13:16:27 +02:00
Raul Ochoa
03f42e36c9 Update news and bump version 2015-09-07 13:02:05 +02:00
Raul Ochoa
af546b35ab Merge pull request #134 from CartoDB/cdb_querytables_quoted
Quote schema and table names returned by CDB_QueryTables
2015-09-07 12:20:17 +02:00
Raul Ochoa
5abe6e0b3d Merge branch 'master' into cdb_querytables_quoted
Conflicts:
	test/extension/test.sh
2015-09-07 12:17:36 +02:00
Raul Ochoa
1eabc5e880 Merge pull request #131 from CartoDB/column-regclass-functions
Column regclass
2015-09-07 12:11:59 +02:00
Raul Ochoa
c6cdaea626 Merge pull request #124 from CartoDB/add-kurtosis
Add kurtosis and skewness
2015-09-07 12:11:34 +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
Andy Eschbacher
b5a9fb9fcf Merge branch 'add-kurtosis' of https://github.com/CartoDB/cartodb-postgresql into add-kurtosis 2015-09-03 22:44:06 -04:00
Andy Eschbacher
83b7f47617 removing raise notices and lower test bounds 2015-09-03 22:43:25 -04:00
Raul Ochoa
25cf48d4a4 Raise min message so we don't have to validate notices 2015-09-04 00:02:30 +02:00
Raul Ochoa
29efdf2ee7 Fix symlink for CDB_Stats.sql 2015-09-04 00:00:30 +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
Raul Ochoa
4be7d4a497 Use quote_ident to quote schema and table names when necessary
Fixes #133
2015-09-03 13:12:29 +02:00
Raul Ochoa
350c76f847 Add option to run tests by prefix
`bash test/extension/test.sh test_cdb_querytables`
will run all tests that start with test_cdb_querytables
2015-09-03 12:59:20 +02:00
Andy Eschbacher
d00e71309d really add tests 2015-09-02 22:35:03 -04:00
Andy Eschbacher
07280321ab adding tests 2015-09-02 22:19:07 -04:00
Raul Ochoa
e28b6344aa Assert it's not possible to get column names from a table without permissions 2015-09-02 12:32:43 +02:00
Raul Ochoa
2867a6fbad Assert user can use its schema to retrieve column names 2015-09-02 12:32:34 +02:00
Raul Ochoa
afecef0e31 Removing redundant ::regclass casting 2015-09-02 12:25:44 +02:00
Raul Ochoa
7582f2cbc5 CDB_ColumnType uses schema and table from regclass
Fixes #130
2015-09-02 12:06:04 +02:00
Raul Ochoa
4b5c5dd275 CDB_ColumnNames uses schema and table name from regclass
Fixes #122
2015-09-02 12:04:52 +02:00
Raul Ochoa
eb6fc4fefb Use CDB_ColumnType and CDB_ColumnNames in bash tests 2015-09-02 12:01:43 +02:00
Rafa de la Torre
4fe85a6a76 Merge pull request #129 from CartoDB/120-fix-extension-upgrade
Do not remove old function #120
2015-08-31 14:05:55 +02:00
Juan Ignacio Sánchez Lara
a003ab7f6a Merge branch 'master' into 103-Extension_Group_API 2015-08-31 13:27:21 +02:00
Rafa de la Torre
2269dc0cb5 Add explanation in NEWS file #120
as suggested in PR.
2015-08-31 12:56:16 +02:00
Rafa de la Torre
0ba57f436a Do not remove old function #120
The `DROP FUNCTION IF EXISTS` was added as transient code and not needed
anymore. See the ticket #120 for more information on this.
2015-08-31 12:01:04 +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
Rafa de la Torre
a5ccbdddcf Update version to 0.9.4 in Makefile #123 2015-08-27 16:47:10 +02:00
Rafa de la Torre
45383d7c8a Merge pull request #127 from CartoDB/123-fix-indices
Fix for index generation when renaming table #123
2015-08-27 16:44:19 +02:00
Rafa de la Torre
0057e2ddec Fix for index generation when renaming table #123 2015-08-27 16:33:46 +02:00
Rafa de la Torre
79cacb8ef4 Modify sampling of table quota trigger #126 2015-08-27 12:52:30 +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
Andy Eschbacher
14e2a65523 adding symlink 2015-08-25 23:11:09 -04:00
Andy Eschbacher
d723487f67 updated definition 2015-08-25 23:10:26 -04:00
Andy Eschbacher
db323f3e13 adding skewness 2015-08-25 22:58:31 -04:00
Andy Eschbacher
49c4cea4e7 adding kurtosis 2015-08-25 22:45:55 -04:00
Rafa de la Torre
7f63688a2f New version 0.9.2 2015-08-24 15:20:50 +02:00
Rafa de la Torre
7ed3c29f82 Merge pull request #121 from CartoDB/text_geom_columns
Handle text 'the_geom' columns as desired in #117
2015-08-24 14:47:27 +02:00
Paul Ramsey
8c2252a9cb Handle text 'the_geom' columns as desired in #117 2015-08-21 13:10:05 -07: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
Rafa de la Torre
95c97a6b1c Update version and news 2015-08-19 19:42:29 +02:00
Rafa de la Torre
5dd497bf20 Fix transformation to webmercator in corner cases #116 2015-08-19 19:37:50 +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
Rafa de la Torre
74e6807c2f Merge pull request #78 from CartoDB/new_cartodbfy
[wip] New cartodbfy function (overwrites CDB_CartodbfyTable)
2015-08-19 15:11:55 +02:00
Rafa de la Torre
f71a2ac52e Version updated to 0.9.0 plus release notes 2015-08-19 15:08:07 +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
Rafa de la Torre
805af3babf Review of format strings and escaping of id's
Just found cartodbfy failed for schema-names-with-dashes. This should
fix it.
2015-08-18 17:05:32 +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
Rafa de la Torre
78bf202b17 Fix for schema-with-dashes 2015-08-18 15:41:11 +02:00
Rafa de la Torre
ed97d87a23 Go back to version 0.8.2
In order to be able to test and rollback, should be needed

See
https://github.com/CartoDB/cartodb-postgresql/blob/master/CONTRIBUTING.md#testing-changes-live
2015-08-18 15:15:56 +02:00
Rafa de la Torre
b798130d23 Update CONTRIBUTING.md 2015-08-18 15:08:35 +02:00
Rafa de la Torre
7800e4e5a8 Update CONTRIBUTING.md 2015-08-18 14:56:37 +02:00
Rafa de la Torre
520024ecb0 Update CONTRIBUTING.md 2015-08-18 14:56:23 +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
Raul Ochoa
5d22464036 Merge pull request #113 from CartoDB/issue-108
Improve cartodb._CDB_total_relation_size performance
2015-08-18 11:17:42 +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
Rafa de la Torre
53754236e3 Fix for quota test after merge with master
Now cartodbfyied tables take less space because of the timestamp
columns.
2015-08-17 15:56:48 +02:00
Rafa de la Torre
3f588df6f6 Drop function in order to change return value 2015-08-17 15:28:37 +02:00
Rafa de la Torre
2b48f90374 Merge remote-tracking branch 'origin/master' into new_cartodbfy
Conflicts:
	test/CDB_QuotaTest.sql
2015-08-17 15:27:33 +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
Raul Ochoa
50169e58d5 Raise better notice on _CDB_total_relation_size errors 2015-08-17 10:25:31 +02:00
Raul Ochoa
6bc91c7125 Using exception with pg_total_relation_size for better performance
IF EXISTS is too slow, one order of magnitude, than using exception
handling. In combination with thousands of tables to check total
relation size that's a problem.

Exception handles specifically undefined_table as it was the original
issue but also any other exception to guarantee a size is always
returned and no error is raised.
2015-08-17 10:17:07 +02:00
Paul Ramsey
a61a92a8f7 Merge pull request #109 from CartoDB/new_cartodbfy_bw_compat_signature
Replace CDB_CartodbfyTable by new CartodbfyTable2
2015-08-14 10:34:54 -07:00
Rafa de la Torre
47d8429277 Use return value from cartodbfy 2015-08-14 17:41:55 +02:00
Rafa de la Torre
565edcb50d Make cartodbfy return destoid 2015-08-14 16:53:43 +02:00
Juan Ignacio Sánchez Lara
a08600a1f8 Exclude cartodb schema from CDB_UserTables 2015-08-14 16:31:19 +02:00
Rafa de la Torre
b7b5be1f3f Add minor piece of doc 2015-08-14 16:10:38 +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
Rafa de la Torre
900531f0c1 Disable a couple of tests
Comment out tests that check cartodb_id text columns. These are no
longer taken into consideration as candidate primary ID (candidate
columns should be numeric).
2015-08-14 13:46:01 +02:00
Rafa de la Torre
010dd13e4d Simple fix for type cheking in test 2015-08-14 13:40:10 +02:00
Rafa de la Torre
72ebc398f8 Recover _CDB_check_prerequisites (sorry, my fault) 2015-08-14 12:30:01 +02:00
Rafa de la Torre
3d89d8231f Fix deletion of cartodb_postgresql_unpriv_user
only used in tests
2015-08-14 09:48:34 +00:00
Rafa de la Torre
f211669e9e Tweak expected output of test_ddl_triggers
Just touch expected output to adapt to NOTICEs and other stuff that
don't affect functionality.
2015-08-14 10:57:11 +02:00
Paul Ramsey
7f55a0263b Fix regclass mismatch on column alter/drop
This logic SHOULD BE MOVED TO Cartodbfy internals.
2015-08-13 16:10:23 -07:00
Paul Ramsey
d268cd07cb Fix many tests and handle ownership issues involved
with Cartodbfy being invoked by schema triggers. Some
issues with regclass interpretation in tests still remain.
Some issues with slightly different behavior to old version
remain. Some issues with error messages / notification messages
changing a little still remain.
2015-08-13 15:59:45 -07:00
Raul Ochoa
219d876973 Merge pull request #110 from CartoDB/issue-108
Fixes CDB_UserDataSize failing due `ERROR: relation "*" does not exist.`
2015-08-13 19:01:05 +02:00
Raul Ochoa
60cc218664 Merge pull request #112 from CartoDB/issue-98
Review test to validate permissions in public tables
2015-08-13 19:00:09 +02:00
Raul Ochoa
e959bba335 Validates it's enought to grant publicuser to user.
Reference to PR where it will be actually fixed for now.
2015-08-13 18:53:41 +02:00
Raul Ochoa
714ba9d0dc Keep all test running :D 2015-08-13 13:27:27 +02:00
Raul Ochoa
4e31d3a37e Fixes CDB_UserDataSize failing due ERROR: relation "*" does not exist.
Adds new _CDB_total_relation_size function that handles nonexistent
tables and does fallback to size=0.

That function could be used to cache total relation size or query another
table view with a cached total relation size.

Fixes #108
2015-08-13 13:23:35 +02:00
Rafa de la Torre
a5321ec7a5 Replace CDB_CartodbfyTable by new CartodbfyTable2
- Delete old CDB_CartodbfyTable code
- Delete auxiliary functions no longer used
- Modify the new CDB_CartodbfyTable signature to be backwards
  compatible.
2015-08-12 18:39:07 +02:00
Rafa de la Torre
c00d607ee2 Merge pull request #107 from CartoDB/new_cartodbfy_rtorre
Do not create timestamp columns/triggers on cartodbfy
2015-08-12 18:34:33 +02:00
Rafa de la Torre
8a031f56f5 Recover test for cartodb_id not-null constraint 2015-08-12 15:58:30 +00:00
Rafa de la Torre
8c41203db6 Fix for the_geom does not exist
When creating triggers, expectation is to have the columns the_geom and
the_geom_webmercator even if the source table does not have any geometry
columns. Populate it in the rewrite with NULL values and right types.
2015-08-12 17:34:47 +02:00
Rafa de la Torre
6b9ab3d956 Fix quota test
Now the cartodbfied table is a bit smaller because it does not have the
timestamp columns.
2015-08-12 10:26:37 +02:00
Raul Ochoa
14213c5d6a Test scenario to show how public tables can be accessed by other roles
This will require changes in cartodb/cartodb rails app because user/role
creation happens over there. So it's not possible to fix all the problems
within the extension right now.
2015-08-12 10:10:21 +02:00
Rafa de la Torre
c11d1bbf50 Fix CDB_CartodbfyTableTest
by removing references to created_at and updated_at columns
2015-08-11 19:52:37 +02:00
Rafa de la Torre
67f8a8cd69 Fix test_ddl_triggers.sql
by removing references to created_at & updated_at columns
2015-08-11 19:18:10 +02:00
Rafa de la Torre
d6afdf751f Do not create timestamp columns/triggers on cartodbfy 2015-08-11 19:07:01 +02:00
Paul Ramsey
1a1f45cdad Add raster table calls, like the old function has 2015-08-11 05:40:31 -07:00
Paul Ramsey
b195aa4b68 Enable trigger addition routine 2015-08-10 08:42:13 -07:00
javi santana
cb57af9074 added requirements for test 2015-08-10 11:01:28 +02:00
javi
513488da0e change random value for quota test again 2015-07-28 09:05:03 +02:00
javi
7921cad4f5 readded removed tests by error 2015-07-27 16:49:59 +02:00
javi santana
10ba742324 Merge pull request #100 from CartoDB/release_0.8.2
Release 0.8.2
2015-07-27 16:19:16 +02:00
javi
788d2a7f10 ready for 0.8.2 2015-07-27 16:12:42 +02:00
javi
189a73ce4d fixed tests 2015-07-27 16:12:15 +02:00
javi santana
d52e05c474 Merge pull request #99 from CartoDB/usertables_fix
added tests for usertables to check private tables are not returned
2015-07-27 16:04:45 +02:00
javi
400248cd5d remove connection permissions to public user 2015-07-27 11:20:55 +02:00
javi
92b5d1f8f4 creating in setup 2015-07-27 11:15:14 +02:00
javi
68fdd9ce33 just add login permissions to public user 2015-07-27 11:07:46 +02:00
javi
53e6b38c32 enabling user again (no sense) 2015-07-27 11:03:21 +02:00
javi
c71faf21e2 do not create publicuser since a previous tests is doing it 2015-07-27 10:57:38 +02:00
javi
12260b9fc3 test cleanup 2015-07-27 10:54:43 +02:00
javi
1b3db28a74 added tests for organization 2015-07-27 10:51:20 +02:00
javi
5d6c2111bf updates tests 2015-07-27 10:37:07 +02:00
javi
df36e83cb5 revoke permissions to list private tables to public user 2015-07-27 10:31:55 +02:00
javi
e05613d5c4 added tests for usertables to check private tables are not returned 2015-07-27 10:25:44 +02:00
Paul Ramsey
565046c3d4 Merge pull request #97 from CartoDB/b0.8
PR for 0.8.1 release
2015-07-08 12:55:02 -07:00
Paul Ramsey
011a007f04 Return test results in deterministic order (closes #96) 2015-07-07 06:13:02 -07:00
Paul Ramsey
08cdb38730 Prepare for 0.8.1 release 2015-07-07 06:07:41 -07:00
Paul Ramsey
734561de4c Use 'publicuser' as public role, not 'public', closes #95.
This is consistent with cartodb behaviour, but not exactly
the same as the contract that the 'public' role guarantees
access to public resources. Possibly a better fix would be
to audit (ug) everything and make sure that it's really
using the public role to mean public, rather than the
'publicuser' connection role. That CDB creates.
2015-07-07 05:49:28 -07:00
Paul Ramsey
8516cbd4c3 Splling fix 2015-07-01 07:03:13 -07:00
Paul Ramsey
509944ea6d Move doc from wiki to repo, closes #85 2015-07-01 07:01:50 -07:00
Rafa de la Torre
ac8203eec4 Merge pull request #93 from CartoDB/fix-upgrade-issue
Fix for upgrade issue from 0.7.4 to 0.8.0
2015-06-30 12:58:23 +02:00
Rafa de la Torre
a6fd829669 Fix for upgrade issue from 0.7.4 to 0.8.0
This fixes the following problem found during testing:
```
ALTER EXTENSION cartodb UPDATE TO '0.8.0';
ERROR:  cannot change return type of existing function
HINT:  Use DROP FUNCTION cdb_usertables(text) first.
```
2015-06-30 12:20:29 +02:00
Rafa de la Torre
0045fb20e8 Update NEWS.md 2015-06-30 11:34:59 +02:00
Raul Ochoa
8190edb461 Merge pull request #83 from CartoDB/64-usertables
Replace CDB_UserTables with something that can handle multi-user accounts
2015-06-30 11:33:32 +02:00
Rafa de la Torre
373e9f5db8 Merge pull request #92 from CartoDB/fix-versioning
Fix versioning by creating a 0.8.0
2015-06-30 11:25:32 +02:00
Rafa de la Torre
6b29c9e67d Fix versioning by creating a 0.8.0
Fix versioning by creating a new major version since it contains new
features. Keep version 0.7.4 that should've never existed and provide an
upgrade path for the new version.
2015-06-30 11:11:24 +02:00
Rafa de la Torre
2b46a2d56f Merge pull request #91 from CartoDB/upgrade-version-0-7-4
Update Makefile and NEWS.md for new version
2015-06-29 12:37:30 +02:00
Rafa de la Torre
371d84ea0c Update Makefile and NEWS.md for new version 2015-06-29 12:09:35 +02:00
Andy Eschbacher
e5897f3dad Merge pull request #87 from CartoDB/categ-distrib
Function deciding criteria for using a category column in a map
2015-06-25 11:50:56 -04:00
Andy Eschbacher
b9fe204007 Merge pull request #81 from CartoDB/equalint
adding equal interval function for consistency
2015-06-25 11:08:24 -04:00
Rafa de la Torre
9b2cff15c5 Merge pull request #88 from CartoDB/86-CDB_QueryTables-fix-long-names
Add a new function CDB_QueryTablesText #86
2015-06-25 16:20:08 +02:00
Andy Eschbacher
13946b4d47 update test output 2015-06-25 08:17:41 -04:00
Andy Eschbacher
97140b17c9 added more flexible output values 2015-06-24 11:03:16 -04:00
Rafa de la Torre
c3eea08f66 Remove ECHO from expectation #86
Remove the `\set ECHO none` from expectation that is automatically
removed by the test harness but still appears in the output when a test
fails.
2015-06-24 16:29:40 +02:00
Rafa de la Torre
22fc962d09 Change expectation #86
Just add CONTEXT lines since they are now added in case of
WARNING/ERROR as a result of having CDB_QueryTables calling
CDB_QueryTablesText.
2015-06-24 16:01:45 +02:00
Rafa de la Torre
ddb6b2c5b5 Return text instead of regclass #86
This way the schema is always returned and backwards compatibility is
kept, should it be needed.
2015-06-24 14:14:00 +02:00
Rafa de la Torre
9a94b3879a Add a new function CDB_QueryTablesRegclass #86
The return values of it can be safely used when len(schema.table_name)
exceeds the 63 char limit of the postgres type `name`.
2015-06-24 11:53:09 +02:00
Andy Eschbacher
d124776c4e simplified assignment 2015-06-23 18:49:59 -04:00
Andy Eschbacher
5941b473ca removed notice 2015-06-23 18:39:15 -04:00
Andy Eschbacher
3ad3038c5e fixed symlink path, other minor items 2015-06-23 18:32:16 -04:00
Andy Eschbacher
c7bb57b405 add symlink 2015-06-23 18:08:32 -04:00
Andy Eschbacher
f8542af57a add tests 2015-06-23 18:07:48 -04:00
Andy Eschbacher
cda6953ea6 initial commit 2015-06-23 16:27:27 -04:00
Andy Eschbacher
189309e1a5 Merge pull request #84 from CartoDB/add-dist-classify
Add distribution classifier
2015-06-12 08:53:42 -04:00
Andy Eschbacher
1d223b77cc changed subfunction name, replaced function with case statement 2015-06-10 10:50:01 -04:00
Andy Eschbacher
6ab1b1d3d0 removed unneeded variables 2015-06-08 18:36:07 -04:00
Andy Eschbacher
c7f4209270 added alias and line 2015-06-08 15:11:58 -04:00
Andy Eschbacher
8e2d86414f updating function 2015-06-08 15:02:39 -04:00
Andy Eschbacher
9cb1fe30d8 adding tests 2015-06-08 15:01:50 -04:00
Andy Eschbacher
424564e324 initial commit 2015-06-08 13:37:27 -04:00
Paul Ramsey
dd3f125339 Fix test expectation 2015-06-01 11:10:06 -07:00
Paul Ramsey
e7ef5e7e8e Clean up after tests
For #64
2015-06-01 10:57:30 -07:00
Paul Ramsey
54973142f6 Handle "unsupported argument" case for CDB_UserTables
in support of #64
2015-06-01 10:37:46 -07:00
Paul Ramsey
ba521461fe Replace CDB_UserTables with new version
fix for #64
2015-06-01 09:47:02 -07:00
Andy Eschbacher
42a617e79c ugh bad filename 2015-05-19 16:03:54 -04:00
Andy Eschbacher
bf4a31842b new result 2015-05-19 15:50:34 -04:00
Andy Eschbacher
a3c8d7bce4 initial commit 2015-05-19 15:28:17 -04:00
Andy Eschbacher
737dc1c1f1 updated formating of test 2015-05-18 12:12:55 -04:00
Andy Eschbacher
d0c85855f5 fixed test expectation value 2015-05-18 12:00:42 -04:00
Andy Eschbacher
ee1df92561 fixed precision in tests 2015-05-14 15:45:57 -04:00
Andy Eschbacher
16d0dc739a added tests improved func 2015-05-14 15:32:58 -04:00
Andy Eschbacher
dcd35fc3d7 Merge branch 'master' into equalint 2015-05-07 17:07:34 -04:00
Andy Eschbacher
2ad3ff547d initial 2015-05-07 15:49:35 -04:00
Andy Eschbacher
b1e1723e75 Merge pull request #80 from CartoDB/sariogonfer-master
updates quantile bins algorithm
2015-05-07 10:55:19 -04:00
Andy Eschbacher
d9e254dbd5 missed updating value 2015-04-28 10:21:34 -04:00
Andy Eschbacher
7d0efa95fb updated test 2015-04-28 09:59:57 -04:00
Andy Eschbacher
1552c03dd4 removed group by; made binning more reliable 2015-04-27 17:59:40 -04:00
sariogonfer
de418ab36d Merge pull request #1 from sariogonfer/sariogonfer-patch-2
Update CDB_QuantileBins.sql
2015-04-27 12:05:23 +02:00
Paul Ramsey
0899c64d0b Break routine into two halves 2015-04-22 13:25:11 -07:00
Paul Ramsey
c1bfef25e0 Fix no-op case error 2015-04-22 13:06:34 -07:00
Paul Ramsey
dd209d02f6 Use standard error message format 2015-04-22 12:51:36 -07:00
Paul Ramsey
614a446cba Document functions a bit more 2015-04-22 09:29:23 -07:00
Paul Ramsey
8dc7f45cca Re-use columns named 'cartodb_id' if the values of the
keys are in fact unique.
2015-04-22 06:33:49 -07:00
Paul Ramsey
74b7740892 Fix bug with missing non-geo columns in case where
geo columns are "perfect" to start w/.
2015-04-21 12:59:44 -07:00
Paul Ramsey
bb685795d5 Handle geometry column with no metadata SRID (grrr) but
a valid SRID on the geometry objects themselves
2015-04-21 06:58:33 -07:00
Paul Ramsey
14414c4bf3 Fix Rambo's test case, of a single geometry-only table
with no SRID in the metadata (thanks mate).
2015-04-21 06:25:35 -07:00
Paul Ramsey
f3c20ac2fb First draft of new cartodbfy function (named CDB_CartodbfyTable2)
Still needs to be fully tested (partially tested now) using
the existing regression tests. Does not manage the timestamp
columns at this time.
2015-04-17 17:53:07 +02:00
sariogonfer
cbd3c447b6 Update CDB_QuantileBins.sql 2015-04-14 20:45:37 +02:00
Raul Ochoa
fc95566ddd Remove test for unexistent table as there was already one 2015-03-31 16:01:49 +02:00
Raul Ochoa
7f58e1f690 Adds tests for cdb_tablemetadatatouch
- fixes tableoid by using the proper table oid
 - tests quoted and unqouted call with OID
 - tests non existent table to fail
2015-03-31 14:48:45 +02:00
Rafa de la Torre
ca643b2e03 Merge pull request #75 from CartoDB/73-fix-upgrade-of-cdb-stringtodate
73 fix upgrade of cdb stringtodate
2015-03-03 17:27:45 +01:00
Rafa de la Torre
a7a52a23ea fix indentation of Makefile #73 2015-03-03 16:10:56 +00:00
Rafa de la Torre
1c9e5f241f Fix upgrade of CDB_StringToDate function #73 2015-03-03 16:09:57 +00:00
Raul Ochoa
38d32371c8 Adds test to validate CDB_TableMetadataTouch usage with OID 2015-03-03 12:09:25 +01:00
Rafa de la Torre
e80ea92c57 Merge pull request #74 from CartoDB/73-fix-timestamps
Fix conversion of strings to datetimes #73
2015-03-03 11:03:27 +01:00
Rafa de la Torre
61804187c8 Fix conversion of strings to datetimes #73 2015-03-03 09:49:33 +00:00
Kartones
9114d4e463 #revert-size_calc Stop this madness 2015-02-27 11:08:19 +01:00
Kartones
5db9dc6a9f #revert-size_calc 3KB diff at expected result 2015-02-27 10:58:13 +01:00
Kartones
0a3d08edc3 #revert-size_calc 2015-02-27 10:53:14 +01:00
Raul Ochoa
b913defebb Stubs next version 2015-02-19 14:34:32 +01:00
Raul Ochoa
978742f868 Release 0.7.0 2015-02-19 14:33:21 +01:00
Raul Ochoa
5080e3d985 Merge pull request #71 from CartoDB/CDB_ZoomFromScale
Adds CDB_ZoomFromScale function
2015-02-19 14:28:30 +01:00
Raul Ochoa
cb61fd8747 Enable DB_ZoomFromScale 2015-02-19 14:24:10 +01:00
Raul Ochoa
ebcca141bd Adds CDB_ZoomFromScale function. Closes #62 2015-02-19 14:20:35 +01:00
Raul Ochoa
9d679614c8 Stubs next version 2015-02-19 14:11:54 +01:00
Raul Ochoa
bebebc255a Release 0.6.0 2015-02-19 14:10:15 +01:00
Raul Ochoa
11bf7f6fdf Fix release notes for 0.5.3 2015-02-19 14:09:49 +01:00
Raul Ochoa
05617382a9 Merge pull request #70 from CartoDB/remove-grant-select-from-cdb_tablemetadata-to-public
Remove grant select from cdb tablemetadata to public
2015-02-19 14:04:56 +01:00
Raul Ochoa
f16f53ceab Adds test for non-authorized writes to cdb_tablemetadata through CDB_TableMetadataTouch 2015-02-19 14:02:27 +01:00
Raul Ochoa
27aec0d4b4 Adds tests for qualified table names 2015-02-18 18:01:29 +01:00
Raul Ochoa
f18232037d Release notes and version bump 2015-02-18 17:31:04 +01:00
Raul Ochoa
da7b3b7080 Adds CDB_TableMetadataTouch function to be able to upsert updated_at
value in cdb_tablemetadata
2015-02-18 17:08:46 +01:00
Raul Ochoa
38fe98d983 Merge branch 'master' into remove-grant-select-from-cdb_tablemetadata-to-public 2015-02-18 15:43:16 +01:00
Kartones
39e16ebc59 Update NEWS.md 2015-02-17 16:25:16 +01:00
Kartones
dbc0e069c5 #69 Updated version at makefile 2015-02-17 15:47:18 +01:00
Kartones
6c7706672f #69 now using pg_relation_size 2015-02-17 15:40:26 +01:00
javi
d43e141291 updated news 2015-02-17 11:34:49 +01:00
javi santana
0d5a1c3e49 Merge pull request #68 from CartoDB/fix_querytables
try to fix security problem
2015-02-17 11:27:46 +01:00
javi
519ea075d6 fixed reg exp 2015-02-13 17:32:14 +01:00
javi
0223d00a54 fixed security problem 2015-02-12 10:57:12 +01:00
Raul Ochoa
3cf62ecd2e Do not grant select permission to public user
- Fake the behaviour in tests by switching between users
2015-02-10 15:27:42 +01:00
Rafa de la Torre
ee8a031ea0 Merge pull request #67 from CartoDB/faster-quota-check
Optimize CDB_UserDataSize (on behalf of @javisantana) #65
2015-01-29 18:06:46 +01:00
Rafa de la Torre
f0bf8a85a5 Fix Makefile versioning stuff #65 2015-01-29 16:37:59 +00:00
Rafa de la Torre
693b147ef1 Fix corner case (no tables) in CDB_UserDataSize #65 2015-01-29 15:46:08 +00:00
Rafa de la Torre
73232b8802 Increase version number to 0.5.2 #65 2015-01-29 14:02:38 +00:00
Rafa de la Torre
a4e42571cd Add a comment to CDB_UserDataSize (from PR) #65 2015-01-28 17:10:04 +00:00
Rafa de la Torre
bf622ae5a6 Optimize CDB_UserDataSize (on behalf of @javisantana) #65 2015-01-28 16:54:50 +00:00
Kartones
dbb6f42b99 #1368 fixed escapings 2014-12-05 17:30:47 +01:00
Kartones
626b883cfc Reactivating sh specs after stabilization 2014-11-19 10:53:52 +01:00
Kartones
cd9e44b266 #1138 Fixed DDL triggers to properly use new cartodbfy signature, fixed cartodbfy to properly send params to check raster table 2014-11-19 10:00:04 +01:00
Kartones
fd9d79372f #1138 Found issue with DDL triggers 2014-11-18 19:00:33 +01:00
Kartones
61b47617b8 #1138 fixes for specs 2014-11-18 17:35:11 +01:00
Kartones
3b5c1f65cb #1138 Quota changes, raster import cartodbfication and quota spec 2014-11-18 15:24:54 +01:00
Kartones
b7c2336ae0 #1138 not counting raster overviews for quota 2014-11-14 10:34:18 +01:00
Kartones
6f80b52c92 Merge branch 'master' of github.com:CartoDB/cartodb-postgresql 2014-10-21 16:48:51 +02:00
Kartones
dc6ac7f56b Merge tag '0.4.1'
v0.4.1
2014-10-21 16:48:23 +02:00
Kartones
68e132ade5 Merge pull request #56 from CartoDB/CDB-4418
CDB-4418 CDB_CartodbfyTable does not create Primary Key on cartodb_id
2014-10-21 16:44:41 +02:00
Kartones
c9ff282b17 CDB-4418 2014-10-21 16:37:59 +02:00
Kartones
f251e12d35 CDB-4418 2014-10-21 16:19:44 +02:00
Raul Ochoa
5a3b93fd6b Release 0.4.0 2014-08-27 14:34:37 +02:00
Raul Ochoa
eaee6d3d70 Merge pull request #53 from CartoDB/CDB-3504
New versioning mechanism
2014-08-25 17:12:57 +02:00
Raul Ochoa
7840e7c50b Prepares version 0.4.0 with new versioning mechanism 2014-08-25 12:00:45 +02:00
Raul Ochoa
5b0a7bf9ad Adds highlighting 2014-08-21 19:05:15 +02:00
Raul Ochoa
2ef6d5901e Fixes typos 2014-08-21 19:05:04 +02:00
Raul Ochoa
3d37b3646e Renames files to take advantage of markdown 2014-08-21 19:01:19 +02:00
Raul Ochoa
51d48c7629 CDB-3656 Removes revision from the extension version 2014-08-21 18:52:21 +02:00
Raul Ochoa
25a0e5ec68 Stubs next version 2014-08-21 18:41:09 +02:00
Raul Ochoa
daa61a6aa8 Merge pull request #52 from CartoDB/CDB-3483
Adds CDB_Math_Model
2014-08-21 17:48:36 +02:00
javi
723a08e814 added CDB_Math_mode 2014-08-19 18:09:27 +02:00
Raul Ochoa
41a2c7363e Merge tag '0.3.6' into cdb
Release 0.3.6
2014-08-11 16:39:20 +02:00
Raul Ochoa
45d07bc5a8 Release 0.3.6 2014-08-11 16:38:41 +02:00
Raul Ochoa
55615e1a32 Stubs next version 2014-08-11 16:18:02 +02:00
Raul Ochoa
4b397d6bc0 Merge tag '0.3.5'
Release 0.3.5
2014-08-11 16:16:50 +02:00
Raul Ochoa
8349e3c94c Merge tag '0.3.5' into cdb
Release 0.3.5 fixed
2014-08-11 16:14:00 +02:00
Raul Ochoa
a747f16ecc Fixes release dates 2014-08-11 16:13:04 +02:00
Raul Ochoa
93de996acc Fixes 0.3.5 version:
- Version in Makefile
- Upgrade path from 0.3.4
2014-08-11 15:41:53 +02:00
Raul Ochoa
a98b100182 Ignore idea ide based settings 2014-08-11 15:41:33 +02:00
Kartones
72d8cf6210 Merge pull request #46 from CartoDB/CDB-3870
CDB-3870
2014-08-11 15:30:11 +02:00
Kartones
6c57640901 CDB-3870 replaced priority of qmax inside checkquota 2014-08-11 15:26:13 +02:00
Raul Ochoa
a67f324001 Release 0.3.4 version 2014-08-01 18:21:48 +02:00
Raul Ochoa
5bb638b995 Merge pull request #45 from CartoDB/CDB-3743
CDB_QueryTables returns only results for schemas associated to Relation-Names
2014-08-01 18:14:53 +02:00
Raul Ochoa
2637742c2e CDB-3743 Makes CDB_QueryTables to return only results for schemas associated to Relation-Names 2014-08-01 18:06:06 +02:00
Kartones
b75b492490 Merge pull request #44 from CartoDB/CDB-3497
Cdb 3497
2014-07-30 16:01:09 +02:00
Kartones
f9ec3c46ee Merge branch 'master' into CDB-3497
Conflicts:
	Makefile
	NEWS
2014-07-29 14:16:52 +02:00
Kartones
679af1d4a3 CDB-3497 Finished stabilizing specs 2014-07-28 17:53:19 +02:00
Kartones
6d665ab163 CDB-3497 ongoing spec stabilization 2014-07-28 15:16:19 +02:00
Kartones
e5c8015e17 CDB-3497 Splitted 2014-07-28 13:11:51 +02:00
Kartones
f61d07518d CDB-3497 ongoing splitting 2014-07-28 12:25:42 +02:00
Kartones
b5589fdf09 CDB-3497 2014-07-25 12:19:40 +02:00
Kartones
de2d3f818e CDB-3497 Updating travis.yml to make it work with newer PG version 2014-07-25 10:56:54 +02:00
Kartones
9500010a67 CDB-3497 Partial splitting 2014-07-25 10:52:46 +02:00
79 changed files with 4003 additions and 763 deletions

2
.gitignore vendored
View File

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

View File

@@ -4,6 +4,7 @@ addons:
postgresql: 9.3
before_install:
- sudo apt-get update
#- sudo apt-get install -q postgresql-9.3-postgis-2.1
- sudo apt-get update
- sudo apt-get install -q postgresql-server-dev-9.3

View File

@@ -19,7 +19,7 @@ in which those scripts are loaded.
Scripts would be best coded in a way to be usable both for creation
and upgrade of the objects. This means using CREATE OR REPLACE for
the functions, and whatever it takes to check existance of any previous
the functions, and whatever it takes to check existence of any previous
version of objects in other cases.
When used as an extension (probably always from version 0.2.0 onwards)
@@ -27,8 +27,8 @@ all the objects will be installed in a "cartodb" schema. Take this into
account to fully-qualify internal calls to avoid (possibly dangerous)
name clashes.
Every new feature (as well as bugfixes) should come with a testcase,
see next session.
Every new feature (as well as bugfixes) should come with a test case,
see next section.
Writing testcases
-----------------
@@ -49,13 +49,16 @@ also installs migration scripts to go from "V" to "V"next and from "V"next
to "V". Example to upgrade a 0.2.0dev version:
```sql
ALTER EXTENSION cartodb UPDATE TO '0.2.0devnext';
ALTER EXTENSION cartodb UPDATE TO '0.2.0next';
ALTER EXTENSION cartodb UPDATE TO '0.2.0dev';
```
Starting with 0.2.0, the in-place reload can be done with an ad-hoc function:
```sql
SELECT cartodb.cdb_extension_reload();
```
A useful query:
```sql
SELECT * FROM pg_extension_update_paths('cartodb') WHERE path IS NOT NULL AND source = cdb_version();
```

View File

@@ -1,7 +1,7 @@
# cartodb/Makefile
EXTENSION = cartodb
EXTVERSION = 0.3.2
EXTVERSION = 0.11.0
SED = sed
@@ -22,6 +22,35 @@ UPGRADABLE = \
0.3.0 \
0.3.0dev \
0.3.1 \
0.3.2 \
0.3.3 \
0.3.4 \
0.3.5 \
0.3.6 \
0.4.0 \
0.4.1 \
0.5.0 \
0.5.1 \
0.5.2 \
0.5.3 \
0.6.0 \
0.7.0 \
0.7.1 \
0.7.2 \
0.7.3 \
0.7.4 \
0.8.0 \
0.8.1 \
0.8.2 \
0.9.0 \
0.9.1 \
0.9.2 \
0.9.3 \
0.9.4 \
0.10.0 \
0.10.1 \
0.10.2 \
0.11.0 \
$(EXTVERSION)dev \
$(EXTVERSION)next \
$(END)
@@ -32,7 +61,6 @@ UPGRADES = \
$(SED) 's/$$/--$(EXTVERSION).sql/' | \
$(SED) 's/ /--$(EXTVERSION).sql $(EXTENSION)--/g')
REV=$(shell git describe)
GITDIR=$(shell test -d .git && echo '.git' || cat .git | $(SED) 's/^gitdir: //')
DATA_built = \
@@ -74,7 +102,7 @@ $(EXTENSION).control: $(EXTENSION).control.in Makefile
$(SED) -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
cartodb_version.sql: cartodb_version.sql.in Makefile $(GITDIR)/index
$(SED) -e 's/@@VERSION@@/$(EXTVERSION) $(REV)/' $< > $@
$(SED) -e 's/@@VERSION@@/$(EXTVERSION)/' $< > $@
legacy_regress: $(REGRESS_OLD) Makefile
mkdir -p sql/test/
@@ -83,21 +111,24 @@ legacy_regress: $(REGRESS_OLD) Makefile
for f in $(REGRESS_OLD); do \
tn=`basename $${f} .sql`; \
of=sql/test/$${tn}.sql; \
echo '\\set ECHO off' > $${of}; \
echo '\\set ECHO none' > $${of}; \
echo '\\a' >> $${of}; \
echo '\\t' >> $${of}; \
echo '\\set QUIET off' >> $${of}; \
cat $${f} | \
$(SED) -e 's/public\./cartodb./g' >> $${of}; \
exp=expected/test/$${tn}.out; \
echo '\\set ECHO off' > $${exp}; \
echo '\\set ECHO none' > $${exp}; \
cat test/$${tn}_expect >> $${exp}; \
done
test_organization:
bash test/organization/test.sh
test_extension_new:
bash test/extension/test.sh
legacy_tests: legacy_regress
installcheck: legacy_tests test_organization
installcheck: legacy_tests test_extension_new test_organization

61
NEWS
View File

@@ -1,61 +0,0 @@
0.3.2 (2014-07-28)
------------------
* Make 0.3.0dev version upgradeable
0.3.1 (2014-07-22)
------------------
* Dummy version. We start using semantic versioning
0.3.0 (2014-07-15)
------------------
* Permission management functions
* Adapt functions to use schemas
0.2.1 - 2014-06-11
------------------
Enhancements:
- Do not force re-cartodbfication on CREATE FROM unpackaged
- Drop useless DEFAULT specification in plpgsql variable declarations
- List plpythonu requirement first, to get pg_catalog scanned before public
Bug fixes:
- Do not add unique index on cartodb_id if already a primary key (#38)
0.2.0 - 2014-06-09
------------------
Important changes:
- This release adds dependency on "plpythonu" extension
- Roles are not created anymore, previously private functions
for table information extraction (CDB_UserTables, CDB_TableIndexes,
CDB_ColumnNames, CDB_ColumnType) will now be callable by anyone while
only returning information about tables over which the calling user
has SELECT privilege (#36)
Bug fixes:
- Fix recursive trigger on create table (#32)
- Ensure cartodb_id uses an associated sequence (#33)
- Fully qualify call to cdb_disable_ddl_hooks from cdb_enable_ddl_hooks
- Fully qualify call to CDB_UserDataSize from quota trigger
- Fully qualify call to CDB_TransformToWebmercator from CDB_CartodbfyTable
- Fix potential infinite loop in CDB_CartodbfyTable
- Fix potential infinite loop in CDB_QueryStatements
Enhancements:
- Include revision info in cdb_version() output (#34)
New features:
- Add a cdb_extension_reload() function
0.1.0 - 2014-05-23
------------------
Initial release

210
NEWS.md Normal file
View File

@@ -0,0 +1,210 @@
next (2015-mm-dd)
-----------------
0.11.0 (2015-09-dd)
-------------------
* Groups API
0.10.2 (2015-09-24)
-------------------
* Add back the `DROP FUNCTION IF EXISTS CDB_UserTables(text);` to be able to upgrade from `0.7.3` upward [#160](https://github.com/CartoDB/cartodb-postgresql/issues/160)
0.10.1 (2015-09-16)
-------------------
* Get back the `update_updated_at` function (still used by old tables) [#143](https://github.com/CartoDB/cartodb-postgresql/pull/143)
* Fix for CDB_StatsTest.sql test failing randomly [#144](https://github.com/CartoDB/cartodb-postgresql/issues/144)
* Fix for table cartodbfy'ed without default seq value [#138](https://github.com/CartoDB/cartodb-postgresql/issues/138)
* Fix for cartodbfy error column `the_geom` already exists [#141](https://github.com/CartoDB/cartodb-postgresql/issues/141)
* Fix for columns with geometry cartodbfy'ed without SRID [#154](https://github.com/CartoDB/cartodb-postgresql/issues/154)
0.10.0 (2015-09-07)
-----------------
* Quote schema and table names returned by CDB_QueryTables [#134](https://github.com/CartoDB/cartodb-postgresql/pull/134). Use quote_ident to quote schema and table names when necessary.
* Fixed CDB_ColumnNames [#122](https://github.com/CartoDB/cartodb-postgresql/issues/122) and CDB_ColumnType [#130](https://github.com/CartoDB/cartodb-postgresql/issues/130) should honor regclass, returning columns for just the table in the schema and not in any other one [#131](https://github.com/CartoDB/cartodb-postgresql/pull/131).
* Add kurtosis and skewness [#124](https://github.com/CartoDB/cartodb-postgresql/pull/124).
* Removed `DROP FUNCTION IF EXISTS cdb_usertables(text);` [#129](https://github.com/CartoDB/cartodb-postgresql/pull/129). This was needed for upgrading between 0.7.4 to 0.8.0 but is no longer needed.
0.9.4 (2015-08-28)
------------------
* Fixed issue with indices when renaming tables [#123](https://github.com/CartoDB/cartodb-postgresql/issues/123)
0.9.3 (2015-08-27)
------------------
* Modify sampling of quota trigger [#126](https://github.com/CartoDB/cartodb-postgresql/issues/126)
0.9.2 (2015-08-24)
------------------
* Fix for `the_geom` column present but not SRID (EWKT) and other corner cases [#121](https://github.com/CartoDB/cartodb-postgresql/pull/121)
0.9.1 (2015-08-19)
------------------
* Fix for transformation to webmercator in corner cases [#116](https://github.com/CartoDB/cartodb-postgresql/issues/116)
0.9.0 (2015-08-19)
------------------
* Re-implementation of `CDB_CartodbfyTable` functions
- The signature of the main function changes to
```
FUNCTION CDB_CartodbfyTable(destschema TEXT, reloid REGCLASS)
RETURNS REGCLASS
```
- The `destschema` does not need to match the origin schema of `reloid`
- It returns the `regclass` of the cartodbfy'ed table, if it needs to be rewritten.
- There are many optimizations
- The columns `created_at` and `updated_at` will no longer be added
* Fix for CDB_UserDataSize failing due `ERROR: relation "*" does not exist.` #110
* Review test to validate permissions in public tables [#112](https://github.com/CartoDB/cartodb-postgresql/pull/112)
0.8.3 (2015-08-14)
------------------
* Fixes CDB_UserDataSize failing due `ERROR: relation "*" does not exist.` [#108](https://github.com/CartoDB/cartodb-postgresql/issues/108)
0.8.2 (2015-07-27)
------------------
* Fix for CDB_UserTables returning wrong listings when publicuser is used
0.8.1 (2015-06-30)
------------------
* Fix for [#95](https://github.com/CartoDB/cartodb-postgresql/issues/95) *cdb_usertables should return public tables when the user is publicuser*
0.8.0 (2015-06-30)
------------------
* Adds new function CDB_QueryTablesText that can deal with "schema.table_name"
longer than 63 chars.
* Adds a set of statistical functions:
- CDB_DistType
- CDB_DistinctMeasure
- CDB_EqualIntervalBins
* Fix for CDB_UserTables returns 0 entries for multiuser accounts [#64](https://github.com/CartoDB/cartodb-postgresql/issues/64)
0.7.4 (2015-06-29)
------------------
Dummy transitional version.
0.7.3 (2015-03-03)
------------------
* Fix upgrade of CDB_StringToDate function
* Add a test for to validate CDB_TableMetadataTouch usage with OID
0.7.2 (2015-03-03)
------------------
* Fix conversion of strings to datetime
0.7.1 (2015-02-27)
------------------
* Revert quota checks to `pg_total_relation_size`
0.7.0 (2015-02-19)
------------------
* Adds CDB_ZoomFromScale function
0.6.0 (2015-02-19)
------------------
* Select permission in CDB_TableMetadata no longer granted to public
* New function to upsert the updated_at in CDB_TableMetadata for a regclass
0.5.3 (2015-02-17)
------------------
* Fixed security problem related with system tables
* Changed quota checks to use `pg_relation_size` instead of `pg_total_relation_size`
0.5.2 (2015-01-29)
------------------
* Improvement: make CDB_UserDataSize functions much faster.
0.5.1 (2014-11-21)
------------------
* Bugfix: Quota check and some organization permissions functions were not properly escaping table name.
0.5.0 (2014-11-03)
------------------
* Support of raster tables for cartodbfication
* Modified quota functions: vector tables stay the same, raster tables count as full size (as have no
the_geom + the_geom_webmercator combo) and raster overviews are not counted
0.4.1 (2014-09-21)
------------------
* Bugfix for Cartodbfication: Set primary key of the table if not already present (e.g. tables created from SQL API)
0.4.0 (2014-08-27)
------------------
Added CDB_Math_Mode function
Changes in versioning: no revision is attached so it no longer uses `git describe` for the version.
0.3.6 (2014-08-11)
------------------
Dummy release to solve some issues with cdb branch/tag
0.3.5 (2014-08-11)
------------------
Inverting priority of CDB_CheckQuota qmax so gies more priority to existing user quota function over parameter value.
0.3.4 (2014-08-01)
------------------
Fixes issue with schemas in CDB_QueryTables
0.3.3 (2014-07-30)
------------------
* Splitting of CartodbfyTable method in subfunctions to be able to call in fragments and evade timeouts on hot zones
0.3.2 (2014-07-28)
------------------
* Make 0.3.0dev version upgradeable
0.3.1 (2014-07-22)
------------------
* Dummy version. We start using semantic versioning
0.3.0 (2014-07-15)
------------------
* Permission management functions
* Adapt functions to use schemas
0.2.1 - 2014-06-11
------------------
Enhancements:
- Do not force re-cartodbfication on CREATE FROM unpackaged
- Drop useless DEFAULT specification in plpgsql variable declarations
- List plpythonu requirement first, to get pg_catalog scanned before public
Bug fixes:
- Do not add unique index on cartodb_id if already a primary key (#38)
0.2.0 - 2014-06-09
------------------
Important changes:
- This release adds dependency on "plpythonu" extension
- Roles are not created anymore, previously private functions
for table information extraction (CDB_UserTables, CDB_TableIndexes,
CDB_ColumnNames, CDB_ColumnType) will now be callable by anyone while
only returning information about tables over which the calling user
has SELECT privilege (#36)
Bug fixes:
- Fix recursive trigger on create table (#32)
- Ensure cartodb_id uses an associated sequence (#33)
- Fully qualify call to cdb_disable_ddl_hooks from cdb_enable_ddl_hooks
- Fully qualify call to CDB_UserDataSize from quota trigger
- Fully qualify call to CDB_TransformToWebmercator from CDB_CartodbfyTable
- Fix potential infinite loop in CDB_CartodbfyTable
- Fix potential infinite loop in CDB_QueryStatements
Enhancements:
- Include revision info in cdb_version() output (#34)
New features:
- Add a cdb_extension_reload() function
0.1.0 - 2014-05-23
------------------
Initial release

View File

@@ -11,7 +11,7 @@ See https://github.com/CartoDB/cartodb/wiki/CartoDB-PostgreSQL-extension
Dependencies
------------
* PostgreSQL 9.3+ (with plpythonu extension)
* PostgreSQL 9.3+ (with plpythonu extension and xml support)
* [PostGIS extension](http://postgis.net)
* [Schema triggers extension]
(https://bitbucket.org/malloclabs/pg_schema_triggers)
@@ -20,12 +20,16 @@ Dependencies
Install
-------
make all install
```sh
make all install
```
Test installation
-----------------
make installcheck
```sh
make installcheck
```
NOTE: if ``test_ddl_triggers`` fails it's likely due to an incomplete
installation of schema_triggers: you need to add ``schema_triggers.so``
@@ -33,6 +37,8 @@ NOTE: if ``test_ddl_triggers`` fails it's likely due to an incomplete
NOTE: you need to run the installcheck as a superuser, use PGUSER
env variable if needed, like: PGUSER=postgres make installcheck
NOTE: the tests need to run against a **clean postgres instance**, if you have some roles already created test will likely fail due `publicuser` not being dropped.
Enable database
---------------
@@ -92,3 +98,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).

14
doc/CDB_ColumnNames.md Normal file
View File

@@ -0,0 +1,14 @@
Retrieve all column names in a particular table
#### Using the function
```sql
SELECT CDB_ColumnNames('table_name')
--- Returns a set of rows with column names
```
#### Arguments
CDB_ColumnNames(table_name)
* **table_name** text

15
doc/CDB_ColumnType.md Normal file
View File

@@ -0,0 +1,15 @@
Returns a column type for any column in a table
#### Using the function
```sql
SELECT CDB_ColumnType('column_name','table_name')
--- Returns a set of rows with column types
```
#### Arguments
CDB_ColumnType(column_name, table_name)
* **column_name** text
* **table_name** text

21
doc/CDB_HeadsTailsBins.md Normal file
View File

@@ -0,0 +1,21 @@
Find the breaks for N categories in a numerical column based on the [Heads/Tails optimization](http://arxiv.org/pdf/1209.2801v1.pdf). Below, Heads/Tails used to color based on the area of the polygons.
![headtails](https://f.cloud.github.com/assets/370259/140655/6eebb918-7228-11e2-89fa-149745f25d34.png)
#### Using the function
We can determine the 7 most optimal breaks in a column of numerical data as follows,
```sql
SELECT CDB_HeadsTailsBins(array_agg(numeric_column), 7) FROM table_name
-- Results in an ordered array like, {7824,23492,52696,233857,666089,1001709,1638094}
-- Each break happens up to, and equal, to a number:
-- (bin1 is less than or equal to 7824, bin2 is less than or equal to 23492, etc.)
```
#### Arguments
CDB_HeadsTailsBins(in_array, breaks)
* **in_array** numeric[]. A NUMERIC array of values.
* **breaks** int. The number of categories you want to create

43
doc/CDB_HexagonGrid.md Normal file
View File

@@ -0,0 +1,43 @@
Fill given extent with an hexagonal coverage
#### Using the function
Create a hexagonal grid from a polygon geometry. For example, take the geometry
```sql
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(10000000,-10000000),
ST_MakePoint(-10000000,10000000)
)
),
3857)
```
We can create a grid as follows,
```sql
SELECT CDB_HexagonGrid(
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(10000000,-10000000),
ST_MakePoint(-10000000,10000000)
)
),
3857),
1000000) the_geom_webmercator
```
Which will look something like this,
![grid tile](http://i.imgur.com/4rZXGMb.png)
#### Arguments
CDB_HexagonGrid(ext, side, origin)
* **ext** geometry. Extent to fill. Only hexagons with center point falling inside the extent (or at the lower or leftmost edge) will be emitted. The returned hexagons will have the same SRID as this extent.
* **side** float. Side measure for the hexagon. Maximum diameter will be 2 * side. Measure is in the same projection as **ext**
* **origin** OPTIONAL geometry. Optional origin to allow for exact tiling. If omitted the origin will be 0,0. The parameter is checked for having the same SRID as the extent.

23
doc/CDB_JenksBins.md Normal file
View File

@@ -0,0 +1,23 @@
Find the breaks for N categories in a numerical column based on the [Jenks optimization](http://en.wikipedia.org/wiki/Jenks_natural_breaks_optimization). Below, Jenks used to color based on the area of the polygons.
![Jenks](https://f.cloud.github.com/assets/370259/140093/b64a9382-7210-11e2-81a4-c65cce3c885e.png)
#### Using the function
We can determine the 7 most optimal breaks in a column of numerical data as follows,
```sql
SELECT CDB_JenksBins(array_agg(numeric_column), 7) FROM table_name
-- Results in an ordered array like, {0,73,2568,9408,29411,768230,1638094}
-- Each break happens up to, and equal, to a number:
-- (bin1 is less than or equal to 0, bin2 is less than or equal to 73, etc.)
```
#### Arguments
CDB_JenksBins(in_array, breaks, invert)
* **in_array** numeric[]. A NUMERIC array of values.
* **breaks** int. The number of categories you want to create
* **iterations** OPTIONAL int. The number of iterations used for calculating breaks.
* **invert** OPTIONAL boolean. Flips whether you receive top down breaks or bottom up breaks. Default is top down (so, <=). Bottom up would give you values that define the lower-end start of a bin (so >=).

21
doc/CDB_MakeHexagon.md Normal file
View File

@@ -0,0 +1,21 @@
Return an Hexagon with given center and side (or maximal radius)
#### Using the function
Running the following SQL
```sql
SELECT CDB_MakeHexagon(ST_MakePoint(0,0),10000000)
```
Would give you back a single hexagon geometry,
![hexagon](http://i.imgur.com/6jeGStb.png)
#### Arguments
CDB_MakeHexagon(center, radius)
* **center** geometry
* **radius** float. Radius of hexagon measured in same projection as **center**

21
doc/CDB_QuantileBins.md Normal file
View File

@@ -0,0 +1,21 @@
Find the breaks for N categories in a numerical column based on the [Quantile bins]. Below, the quantile method is used to determine color based on the area of the polygons.
![qunatile](https://f.cloud.github.com/assets/370259/140714/932ed0e6-722b-11e2-9807-ffbd0fddb9ac.png)
#### Using the function
We can determine the 7 most optimal breaks in a column of numerical data as follows,
```sql
SELECT CDB_QuantileBins(array_agg(numeric_column), 7) FROM table_name
-- Results in an ordered array like, {80,2281,7162,17652,39730,91077,1638094}
-- Each break happens up to, and equal, to a number:
-- (bin1 is less than or equal to 80, bin2 is less than or equal to 2281, etc.)
```
#### Arguments
CDB_QuantileBins(in_array, breaks)
* **in_array** numeric[]. A NUMERIC array of values.
* **breaks** int. The number of categories you want to create

46
doc/CDB_RectangleGrid.md Normal file
View File

@@ -0,0 +1,46 @@
Fill given extent with a rectangular coverage
#### Using the function
Create a rectangular grid from a polygon geometry. For example, take the geometry
```sql
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(10000000,-10000000),
ST_MakePoint(-10000000,10000000)
)
),
3857)
```
We can create a grid as follows,
```sql
SELECT CDB_RectangleGrid(
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(10000000,-10000000),
ST_MakePoint(-10000000,10000000)
)
),
3857),
1000000,
1000000
) the_geom_webmercator
```
Which will look something like this,
![rect grid](http://i.imgur.com/HuhOJRs.png)
#### Arguments
CDB_RectangleGrid(ext, width, height, origin)
* **ext** geometry. Extent to fill. Only rectangles with center point falling inside the extent (or at the lower or leftmost edge) will be emitted. The returned hexagons will have the same SRID as this extent.
* **width** float. Width of each rectangle. Measure is in the same projection as **ext**
* **height** float. Height of each rectangle. Measure is in the same projection as **ext**
* **origin** OPTIONAL geometry. Optional origin to allow for exact tiling. If omitted the origin will be 0,0. The parameter is checked for having the same SRID as the extent.

View File

@@ -0,0 +1,11 @@
Sets user quota in bytes (superuser only)
#### Using the function
```sql
SELECT CDB_SetUserQuotaInBytes(10485760);
--- Returns the previously set quota.
--- Use 0 to disable quota.
```
REF: https://github.com/CartoDB/cartodb-postgresql/blob/master/scripts-available/CDB_Quota.sql

View File

@@ -0,0 +1,44 @@
Function to "safely" transform to webmercator. This function is most useful for rendering custom geometries using the CartoDB tiler. Often, transforming a projection like WGS84 can cause issues with extents beyond what are actually valid in webmercator, this attempts to fix those issues.
#### Using the function
Using a box that is nearly the full globe,
```sql
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(-180,60),
ST_MakePoint(180,-60)
)
),
4326
)
```
We can then convert it to a renderable webmercator geometry.
```sql
SELECT CDB_TransformToWebmercator(
ST_SetSRID(
ST_Envelope(
ST_Collect(
ST_MakePoint(-10,60),
ST_MakePoint(300,-60)
)
),
4326
)
)
```
Would give you back a single valid rectangle in webmercator. Since a longitude of 300 would convert to an unallowed webmercator coordinate, it gets clipped first. Valid extent is WGS84 (-180, -89, 180, 89)
![valid geom](http://i.imgur.com/EFdXiqt.png)
#### Arguments
CDB_TransformToWebmercator(geom)
* **geom** geometry

11
doc/CDB_UserTables.md Normal file
View File

@@ -0,0 +1,11 @@
List the name of available tables (only the usable ones)
#### Using the function
```sql
--- Returns a row for each table having given permission with the table name
--- Currently accepted permissions are: 'public', 'private' or 'all'
SELECT CDB_UserTables(perms)
```
REF: https://github.com/CartoDB/cartodb-postgresql/blob/master/scripts-available/CDB_UserTables.sql

22
doc/CDB_XYZ_Extent.md Normal file
View File

@@ -0,0 +1,22 @@
Determine the spatial extent of a tile based on the tile's XYZ coordinate.
#### Using the function
Take a common tile with coordinates x=3, y=2, z=2,
![2/3/2](https://viz2.cartodb.com/tiles/quantile_breaks/2/3/2.png)
To determine its extent you would run,
```sql
SELECT CDB_XYZ_Extent(3,2,2)
--- Returns a WKB polygon in Webmercator (SRID 3857)
```
#### Arguments
CDB_XYZ_Extent(x,y,z)
* **x** integer
* **y** integer
* **z** integer

20
doc/CDB_XYZ_Resolution.md Normal file
View File

@@ -0,0 +1,20 @@
Return pixel resolution of tiles at a given zoom level
#### Using the function
Take a common tile with zoom, z=2,
![2/3/2](https://viz2.cartodb.com/tiles/quantile_breaks/2/3/2.png)
To determine the resolution of these pixels,
```sql
SELECT CDB_XYZ_Resolution(2)
--- Returns a float, 39135.7587890625
```
#### Arguments
CDB_XYZ_Resolution(z)
* **z** integer

38
doc/CartoDB-PLpgSQL.md Normal file
View File

@@ -0,0 +1,38 @@
INTRODUCTION
============
CartoDB uses a number of custom [PLpgSQL](http://www.postgresql.org/docs/8.3/static/plpgsql.html) functions to perform a few magical things. Those functions are accessible to users on CartoDB as well, so we would like to document what they are and what they do here.
## Spatial functions
[CDB_HexagonGrid](CDB_HexagonGrid) - create hexagonal grid from extent and size
[CDB_MakeHexagon](CDB_MakeHexagon) - make a hexagon with given center and side
[CDB_RectangleGrid](CDB_RectangleGrid) - fill given extent with a rectangular coverage
##### Tile based
[CDB_XYZ_Extent](CDB_XYZ_Extent) - Find the extent of a tile by XYZ
[CDB_XYZ_Resolution](CDB_XYZ_Resolution) - Find the pixel resolution of tiles
[CDB_TransformToWebmercator](CDB_TransformToWebmercator) - Convert a geometry to valid webmercator
## Statistical functions
[CDB_JenksBins](CDB_JenksBins) - Find breaks in an array of numbers using Jenks method
[CDB_HeadsTailsBins](CDB_HeadsTailsBins) - Find breaks in an array of numbers using Heads/Tails method
[CDB_QuantileBins](CDB_QuantileBins) - Find quantile breaks in an array of numbers
## System functions
[CDB_UserTables](CDB_UserTables) - Get a list of all tables in your account
[[CDB_SetUserQuotaInBytes]] - Set maximum user quota in bytes
column names - now returned in JSON response
column types - now returned in JSON response

29
doc/CartoDB-user-table.md Normal file
View File

@@ -0,0 +1,29 @@
A "cartodb" user table is a table with a well-known set of fields and a well-known set of triggers attached on.
The fields are:
- `cartodb_id`, a numerical primary key of serial type
- `created_at`, timestamp with timezone not null default now()
- `updated_at`, timestamp with timezone not null default now()
- `the_geom`, geometry, GiST indexed, constrained (see below)
- `the_geom_webmercator`, geometry, GiST indexed, constrained (see below)
The values of "the_geom" and "the_geom_webmercator" must match these constraints:
- Only POINT, MULTILINE, MULTIPOLYGON types ? Maybe UNCONSTRAINED
- Only 2 dimensions ? Maybe UNCONSTRAINED
- SRID=4326 for the_geom and SRID=3857 for the_geom_webmercator
The triggers are:
- `track_updates` after modifying statement updates cdb_tablemetadata
- `test_quota` before changing statement to forbid if overquota
- `test_quota_per_row` before changing row to forbod if overquota (checked on a probabilistic basis)
- `update_the_geom_webmercator` before insert or update row to maintain the_geom_webmercator
- `update_updated_at_trigger` before update row to maintain updated_at
Some conversions will be attempted to perform upon cartodbfication when certain fields appear:
- `cartodb_id`: If found type TEXT will be attempted to cast
- `created_at`: If found type TEXT will be attempted to cast
- `updated_at`: If found type TEXT will be attempted to cast

48
doc/README.md Normal file
View File

@@ -0,0 +1,48 @@
# Contents
* [CartoDB-user-table](CartoDB-user-table.md)
* [CartoDB-PLpgSQL](CartoDB-PLpgSQL.md)
* [CDB_ColumnNames](CDB_ColumnNames.md)
* [CDB_ColumnType](CDB_ColumnType.md)
* [CDB_HeadsTailsBins](CDB_HeadsTailsBins.md)
* [CDB_HexagonGrid](CDB_HexagonGrid.md)
* [CDB_JenksBins](CDB_JenksBins.md)
* [CDB_MakeHexagon](CDB_MakeHexagon.md)
* [CDB_QuantileBins](CDB_QuantileBins.md)
* [CDB_RectangleGrid](CDB_RectangleGrid.md)
* [CDB_SetUserQuotaInBytes](CDB_SetUserQuotaInBytes.md)
* [CDB_TransformToWebmercator](CDB_TransformToWebmercator.md)
* [CDB_UserTables](CDB_UserTables.md)
* [CDB_XYZ_Extent](CDB_XYZ_Extent.md)
* [CDB_XYZ_Resolution](CDB_XYZ_Resolution.md)
The CartoDB PostgreSQL extension is a module to load into each CartoDB user database to perform cartodb-specific security and functionality checks.
# 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

@@ -19,6 +19,14 @@ NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
(1 row)
create schema c;
SELECT CDB_SetUserQuotaInBytes('c', 0);
cdb_setuserquotainbytes
-------------------------
0
(1 row)
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';
@@ -26,10 +34,10 @@ SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
----------------------
-- CREATE TABLE
----------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select 1 as i INTO c.t3;
NOTICE: trigger "track_updates" for table "c.t3" does not exist, skipping
NOTICE: trigger "update_the_geom_webmercator_trigger" for table "c.t3" does not exist, skipping
NOTICE: trigger "update_updated_at_trigger" for table "c.t3" does not exist, skipping
NOTICE: trigger "test_quota" for table "c.t3" does not exist, skipping
NOTICE: trigger "test_quota_per_row" for table "c.t3" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_create" does not exist, skipping
@@ -38,17 +46,7 @@ NOTICE: event trigger "cdb_on_alter_column" does not exist, skipping
NOTICE: event trigger "cdb_on_drop_column" does not exist, skipping
NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
NOTICE: cdb_invalidate_varnish(c.t3) called
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i
from c.t3;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator | i
------------+-----+------+----------+----------------------+---
1 | t | t | | | 1
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
@@ -58,33 +56,21 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
c.t3 | 0
(1 row)
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
-- Table with cartodb_id field, see
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
select 1 as cartodb_id INTO c.t4;
NOTICE: trigger "track_updates" for table "c.t4" does not exist, skipping
NOTICE: trigger "update_the_geom_webmercator_trigger" for table "c.t4" does not exist, skipping
NOTICE: trigger "update_updated_at_trigger" for table "c.t4" does not exist, skipping
NOTICE: trigger "test_quota" for table "c.t4" does not exist, skipping
NOTICE: trigger "test_quota_per_row" for table "c.t4" does not exist, skipping
NOTICE: Column cartodb_id already exists
NOTICE: Existing cartodb_id field does not have an associated sequence, renaming
NOTICE: Trying to recover data from _cartodb_id0 column
NOTICE: event trigger "cdb_on_relation_create" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_drop" does not exist, skipping
NOTICE: event trigger "cdb_on_alter_column" does not exist, skipping
NOTICE: event trigger "cdb_on_drop_column" does not exist, skipping
NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
NOTICE: cdb_invalidate_varnish(c.t4) called
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator
from c.t4;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator
------------+-----+------+----------+----------------------
1 | t | t | |
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
@@ -97,6 +83,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t4'::regclass;
----------------------------
-- ALTER TABLE RENAME COLUMN
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
@@ -104,27 +91,14 @@ select pg_sleep(.1);
(1 row)
alter table c.t3 rename column the_geom_webmercator to webmerc;
NOTICE: Column cartodb_id already exists
NOTICE: Column created_at already exists
NOTICE: Column updated_at already exists
NOTICE: Column the_geom already exists
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
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc
from c.t3;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator | i | webmerc
------------+-----+------+----------+----------------------+---+---------
1 | t | t | | | 1 |
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -134,6 +108,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
c.t3 | 0
(1 row)
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
@@ -141,27 +116,14 @@ select pg_sleep(.1);
(1 row)
alter table c.t3 rename column the_geom_webmercator to webmerc2;
NOTICE: Column cartodb_id already exists
NOTICE: Column created_at already exists
NOTICE: Column updated_at already exists
NOTICE: Column the_geom already exists
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
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2
from c.t3;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator | i | webmerc | webmerc2
------------+-----+------+----------+----------------------+---+---------+----------
1 | t | t | | | 1 | |
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -174,6 +136,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- ALTER TABLE DROP COLUMN
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
@@ -181,27 +144,13 @@ select pg_sleep(.1);
(1 row)
alter table c.t3 drop column the_geom_webmercator;
NOTICE: Column cartodb_id already exists
NOTICE: Column created_at already exists
NOTICE: Column updated_at already exists
NOTICE: Column the_geom already exists
NOTICE: event trigger "cdb_on_relation_create" does not exist, skipping
NOTICE: event trigger "cdb_on_relation_drop" does not exist, skipping
NOTICE: event trigger "cdb_on_alter_column" does not exist, skipping
NOTICE: event trigger "cdb_on_drop_column" does not exist, skipping
NOTICE: event trigger "cdb_on_add_column" does not exist, skipping
NOTICE: cdb_invalidate_varnish(c.t3) called
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2
from c.t3;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator | i | webmerc | webmerc2
------------+-----+------+----------+----------------------+---+---------+----------
1 | t | t | | | 1 | |
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -214,6 +163,7 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
-- ALTER TABLE ADD COLUMN
----------------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
pg_sleep
----------
@@ -222,17 +172,7 @@ select pg_sleep(.1);
alter table c.t3 add column id2 int;
NOTICE: cdb_invalidate_varnish(c.t3) called
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2, id2
from c.t3;
cartodb_id | c=u | u<1s | the_geom | the_geom_webmercator | i | webmerc | webmerc2 | id2
------------+-----+------+----------+----------------------+---+---------+----------+-----
1 | t | t | | | 1 | | |
(1 row)
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -247,12 +187,13 @@ FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
----------------------------
RESET SESSION AUTHORIZATION;
drop schema c cascade;
NOTICE: drop cascades to 2 other objects
NOTICE: drop cascades to 3 other objects
select count(*) from CDB_TableMetadata;
count
-------
0
(1 row)
DROP USER cartodb_postgresql_unpriv_user;
DROP OWNED BY cartodb_postgresql_unpriv_user;
DROP ROLE cartodb_postgresql_unpriv_user;
DROP FUNCTION _CDB_UserQuotaInBytes();

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,12 @@ CREATE OR REPLACE FUNCTION CDB_ColumnNames(REGCLASS)
RETURNS SETOF information_schema.sql_identifier
AS $$
SELECT column_name
FROM information_schema.columns
WHERE
table_name IN (SELECT CDB_UserTables())
AND table_name = '' || $1 || '';
SELECT c.column_name
FROM information_schema.columns c, pg_class _tn, pg_namespace _sn
WHERE table_name = _tn.relname
AND table_schema = _sn.nspname
AND _tn.oid = $1::oid
AND _sn.oid = _tn.relnamespace;
$$ LANGUAGE SQL;

View File

@@ -3,12 +3,13 @@ CREATE OR REPLACE FUNCTION CDB_ColumnType(REGCLASS, TEXT)
RETURNS information_schema.character_data
AS $$
SELECT data_type
FROM information_schema.columns
WHERE
table_name IN (SELECT CDB_UserTables())
AND table_name = '' || $1 || ''
AND column_name = '' || quote_ident($2) || '';
SELECT c.data_type
FROM information_schema.columns c, pg_class _tn, pg_namespace _sn
WHERE table_name = _tn.relname
AND table_schema = _sn.nspname
AND column_name = $2
AND _tn.oid = $1::oid
AND _sn.oid = _tn.relnamespace;
$$ LANGUAGE SQL;

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

@@ -4,14 +4,23 @@ 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;
RAISE DEBUG 'Relation % of kind % created in namespace oid %',
event_info.relation, (event_info.new).relkind, (event_info.new).relnamespace;
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
@@ -22,15 +31,15 @@ BEGIN
PERFORM cartodb.cdb_disable_ddl_hooks();
-- CDB_CartodbfyTable must not create tables, or infinite loop will happen
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
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 (event_info.relation, now());
INSERT INTO cartodb.CDB_TableMetadata(tabname, updated_at)
VALUES (newtable, now());
END; $$;
-- }
@@ -63,13 +72,19 @@ 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 oid,* FROM pg_class WHERE oid = event_info.relation INTO rel;
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'), event_info.relation::regclass, rel.relkind;
(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;
@@ -82,12 +97,12 @@ BEGIN
PERFORM cartodb.cdb_disable_ddl_hooks();
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
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()
UPDATE cartodb.CDB_TableMetadata SET updated_at = NOW(), tabname = newtable
WHERE tabname = event_info.relation;
END; $$;
@@ -100,13 +115,19 @@ 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 oid,* FROM pg_class WHERE oid = event_info.relation INTO rel;
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'), event_info.relation::regclass, rel.relkind;
(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;
@@ -117,15 +138,16 @@ BEGIN
RETURN;
END IF;
PERFORM cartodb.cdb_disable_ddl_hooks();
PERFORM cartodb.CDB_CartodbfyTable(event_info.relation);
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()
WHERE tabname = event_info.relation;
UPDATE cartodb.CDB_TableMetadata SET updated_at = NOW(), tabname = newtable
WHERE tabname = event_info.relation;
END; $$;
-- }
@@ -140,10 +162,15 @@ DECLARE
BEGIN
event_info := schema_triggers.get_column_add_eventinfo();
SELECT oid,* FROM pg_class WHERE oid = event_info.relation INTO rel;
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'), event_info.relation::regclass, rel.relkind;
(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;

View File

@@ -0,0 +1,122 @@
--
-- CDB_DistType classifies the histograms of a column into
-- one of the basic types listed by Galtung: http://druedin.com/2012/12/08/galtungs-ajus-system/
--
-- Future improvements:
-- variable number of bins (7 is baked in right now)
-- catch the number of items to ensure that the sample is large enough
--
-- Refs:
-- 1. width_bucket/histograms: http://tapoueh.org/blog/2014/02/21-PostgreSQL-histogram
-- 2. R implementation: https://github.com/cran/agrmt
CREATE OR REPLACE FUNCTION CDB_DistType ( in_array NUMERIC[] ) RETURNS text as $$
DECLARE
element_count INT4;
minv numeric;
maxv numeric;
bins numeric[];
freqs numeric[];
ajus INT[];
freq INT4;
signature text;
i INT := 1;
BEGIN
SELECT min(e), max(e), count(e) INTO minv, maxv, element_count FROM ( SELECT unnest(in_array) e ) x;
IF abs(maxv - minv) < 1e-7 THEN -- if max and min are nearly equal, call if 'F' (make relative to maxv?)
signature = 'F';
ELSE
-- Calculate bins and count in bins
EXECUTE 'WITH stats as (
SELECT min(e) as minv,
max(e) as maxv,
count(e) as total
FROM (SELECT unnest($1) e) x
WHERE e is not null
),
hist as (
SELECT width_bucket(e, s.minv, s.maxv, 7) bucket,
count(*) freq
FROM (SELECT unnest($1) e) x, stats s
WHERE e is not null
GROUP BY 1
ORDER BY 1
)
SELECT array_agg(round(100.0 * hist.freq::numeric / stats.total::numeric,1)) freqs,
array_agg(hist.bucket) buckets
FROM hist, stats'
INTO freqs, bins
USING in_array;
LOOP
IF i < 7 THEN
ajus[i] = CASE WHEN freqs[i] > freqs[i+1] THEN -1
WHEN abs(freqs[i] - freqs[i+1]) <= 0.05 THEN 0
ELSE 1 END;
ELSE
EXIT;
END IF;
i := i + 1;
END LOOP;
signature = _CDB_DistTypeClassify(ajus);
END IF;
RETURN signature;
END;
$$ language plpgsql IMMUTABLE;
-- Classify data into AJUSFL
CREATE OR REPLACE FUNCTION _CDB_DistTypeClassify ( in_array INT[] ) RETURNS text as $$
DECLARE
element_count INT4;
maxv numeric;
minv numeric;
uniques INT[];
type text;
BEGIN
SELECT max(e), min(e) INTO maxv, minv FROM ( SELECT unnest(in_array) e ) x;
IF (maxv = 0 AND minv = 0) THEN
type = 'F';
ELSIF maxv < 1 THEN
type = 'L';
ELSIF minv > -1 THEN
type = 'J';
ELSE
-- Get distinct elements ordered by original position
EXECUTE 'WITH b AS (
SELECT a
FROM (SELECT unnest($1) a) x
),
c AS (
SELECT a, row_number() OVER () r
FROM b
),
d AS (
SELECT DISTINCT a
FROM c
),
e AS (
SELECT a FROM d ORDER BY (
SELECT r FROM c WHERE d.a = c.a ORDER BY r ASC LIMIT 1
) ASC)
SELECT array_agg(a) FROM e'
INTO uniques
USING in_array;
-- Decide if it's an A, U, or other
IF (uniques = ARRAY[1,-1] OR uniques = ARRAY[1,0,-1] OR uniques = ARRAY[1,-1,0] OR uniques = ARRAY[0,1,-1]) THEN
type = 'A';
ELSIF (uniques = ARRAY[-1,1] OR uniques = ARRAY[-1,0,1] OR uniques = ARRAY[-1,1,0] OR uniques = ARRAY[0,-1,1]) THEN
type = 'U';
ELSE
type = 'S';
END IF;
END IF;
RETURN type;
END;
$$ language plpgsql IMMUTABLE;

View File

@@ -0,0 +1,46 @@
--
-- CDB_DistinctMeasure
-- calculates the fraction of rows in the 10 most common distinct categories
-- returns true if the number of rows in these 10 categories is >= 0.9 * total number of rows
--
--
CREATE OR REPLACE FUNCTION CDB_DistinctMeasure ( in_array text[], threshold numeric DEFAULT null ) RETURNS numeric as $$
DECLARE
element_count INT4;
maxval numeric;
passes numeric;
BEGIN
SELECT count(e) INTO element_count FROM ( SELECT unnest(in_array) e ) x;
-- count number of occurrences per bin
-- calculate the normalized cumulative sum
-- return the max value: which corresponds nth entry
-- for n <= 10 depending on # of distinct values
EXECUTE 'WITH a As (
SELECT
count(*) cnt
FROM
(SELECT * FROM unnest($2) e ) x
WHERE e is not null
GROUP BY e
ORDER BY cnt DESC
),
b As (
SELECT
sum(cnt) OVER (ORDER BY cnt DESC) / $1 As cumsum
FROM a
LIMIT 10
)
SELECT max(cumsum) maxval FROM b'
INTO maxval
USING element_count, in_array;
IF threshold is null THEN
passes = maxval;
ELSE
passes = CASE WHEN (maxval >= threshold) THEN 1 ELSE 0 END;
END IF;
RETURN passes;
END;
$$ language plpgsql IMMUTABLE;

View File

@@ -0,0 +1,37 @@
--
-- Calculate the equal interval bins for a given column
--
-- @param in_array A numeric array of numbers to determine the best
-- to determine the bin boundary
--
-- @param breaks The number of bins you want to find.
--
--
-- Returns: upper edges of bins
--
--
CREATE OR REPLACE FUNCTION CDB_EqualIntervalBins ( in_array NUMERIC[], breaks INT ) RETURNS NUMERIC[] as $$
DECLARE
diff numeric;
min_val numeric;
max_val numeric;
tmp_val numeric;
i INT := 1;
reply numeric[];
BEGIN
SELECT min(e), max(e) INTO min_val, max_val FROM ( SELECT unnest(in_array) e ) x WHERE e IS NOT NULL;
diff = (max_val - min_val) / breaks::numeric;
LOOP
IF i < breaks THEN
tmp_val = min_val + i::numeric * diff;
reply = array_append(reply, tmp_val);
i := i+1;
ELSE
reply = array_append(reply, max_val);
EXIT;
END IF;
END LOOP;
RETURN reply;
END;
$$ language plpgsql IMMUTABLE;

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 'SELECT PG_GET_SERIAL_SEQUENCE($1, $2)' USING 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,26 @@
-- CartoDB Math SQL functions
-- Mode
-- https://wiki.postgresql.org/wiki/Aggregate_Mode
CREATE OR REPLACE FUNCTION cartodb._CDB_Math_final_mode(anyarray)
RETURNS anyelement AS
$BODY$
SELECT a
FROM unnest($1) a
GROUP BY 1
ORDER BY COUNT(1) DESC, 1
LIMIT 1;
$BODY$
LANGUAGE 'sql' IMMUTABLE;
DROP AGGREGATE IF EXISTS cartodb.CDB_Math_Mode(anyelement);
CREATE AGGREGATE cartodb.CDB_Math_Mode(anyelement) (
SFUNC=array_append,
STYPE=anyarray,
FINALFUNC=_CDB_Math_final_mode,
INITCOND='{}'
);

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
@@ -35,7 +91,7 @@ FUNCTION cartodb.CDB_Organization_Add_Table_Read_Permission(from_schema text, ta
AS $$
BEGIN
EXECUTE 'GRANT USAGE ON SCHEMA "' || from_schema || '" TO "' || to_role_name || '"';
EXECUTE 'GRANT SELECT ON "' || from_schema || '".' || table_name || ' TO "' || to_role_name || '"';
EXECUTE 'GRANT SELECT ON "' || from_schema || '"."' || table_name || '" TO "' || to_role_name || '"';
END
$$ LANGUAGE PLPGSQL VOLATILE;
@@ -54,7 +110,7 @@ FUNCTION cartodb.CDB_Organization_Add_Table_Read_Write_Permission(from_schema te
AS $$
BEGIN
EXECUTE 'GRANT USAGE ON SCHEMA "' || from_schema || '" TO "' || to_role_name || '"';
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON "' || from_schema || '".' || table_name || ' TO "' || to_role_name || '"';
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON "' || from_schema || '"."' || table_name || '" TO "' || to_role_name || '"';
END
$$ LANGUAGE PLPGSQL VOLATILE;
@@ -73,7 +129,7 @@ FUNCTION cartodb.CDB_Organization_Remove_Access_Permission(from_schema text, tab
RETURNS void
AS $$
BEGIN
EXECUTE 'REVOKE ALL PRIVILEGES ON TABLE "' || from_schema || '".' || table_name || ' FROM "' || to_role_name || '"';
EXECUTE 'REVOKE ALL PRIVILEGES ON TABLE "' || from_schema || '"."' || table_name || '" FROM "' || to_role_name || '"';
-- EXECUTE 'REVOKE USAGE ON SCHEMA ' || from_schema || ' FROM "' || to_role_name || '"';
-- We need to revoke usage on schema only if we are revoking privileges from the last table where to_role_name has
-- any permission granted within the schema from_schema

View File

@@ -15,18 +15,29 @@ DECLARE
i INT := 1;
reply numeric[];
BEGIN
-- get our unique values
SELECT array_agg(e) INTO in_array FROM (SELECT unnest(in_array) e GROUP BY e ORDER BY e ASC) x;
-- get the total size of our row
element_count := array_upper(in_array, 1) - array_lower(in_array, 1);
-- sort our values
SELECT array_agg(e) INTO in_array FROM (SELECT unnest(in_array) e ORDER BY e ASC) x;
-- get the total size of our data
element_count := array_length(in_array, 1);
break_size := element_count::numeric / breaks;
-- slice our bread
LOOP
IF i > breaks THEN EXIT; END IF;
SELECT e INTO tmp_val FROM ( SELECT unnest(in_array) e LIMIT 1 OFFSET round(break_size * i)) x;
IF i < breaks THEN
IF break_size * i % 1 > 0 THEN
SELECT e INTO tmp_val FROM ( SELECT unnest(in_array) e LIMIT 1 OFFSET ceil(break_size * i) - 1) x;
ELSE
SELECT avg(e) INTO tmp_val FROM ( SELECT unnest(in_array) e LIMIT 2 OFFSET ceil(break_size * i) - 1 ) x;
END IF;
ELSIF i = breaks THEN
-- select the last value
SELECT max(e) INTO tmp_val FROM ( SELECT unnest(in_array) e ) x;
ELSE
EXIT;
END IF;
reply = array_append(reply, tmp_val);
i := i+1;
END LOOP;
RETURN reply;
i := i+1;
END LOOP;
RETURN reply;
END;
$$ language plpgsql IMMUTABLE;
$$ language plpgsql IMMUTABLE;

View File

@@ -2,12 +2,12 @@
--
-- Requires PostgreSQL 9.x+
--
CREATE OR REPLACE FUNCTION CDB_QueryTables(query text)
RETURNS name[]
CREATE OR REPLACE FUNCTION CDB_QueryTablesText(query text)
RETURNS text[]
AS $$
DECLARE
exp XML;
tables NAME[];
tables text[];
rec RECORD;
rec2 RECORD;
BEGIN
@@ -16,9 +16,9 @@ BEGIN
FOR rec IN SELECT CDB_QueryStatements(query) q LOOP
IF NOT ( rec.q ilike 'select %' or rec.q ilike 'with %' ) THEN
--RAISE WARNING 'Skipping %', rec.q;
CONTINUE;
IF NOT ( rec.q ilike 'select%' or rec.q ilike 'with%' ) THEN
--RAISE WARNING 'Skipping %', rec.q;
CONTINUE;
END IF;
BEGIN
@@ -39,13 +39,13 @@ BEGIN
inp AS (
SELECT
xpath('//x:Relation-Name/text()', exp, ARRAY[ARRAY['x', 'http://www.postgresql.org/2009/explain']]) as x,
xpath('//x:Schema/text()', exp, ARRAY[ARRAY['x', 'http://www.postgresql.org/2009/explain']]) as s
xpath('//x:Relation-Name/../x:Schema/text()', exp, ARRAY[ARRAY['x', 'http://www.postgresql.org/2009/explain']]) as s
)
SELECT unnest(x)::name as p, unnest(s)::name as sc from inp
SELECT unnest(x)::text as p, unnest(s)::text as sc from inp
LOOP
-- RAISE DEBUG 'tab: %', rec2.p;
-- RAISE DEBUG 'sc: %', rec2.sc;
tables := array_append(tables, (rec2.sc || '.' || rec2.p)::name);
tables := array_append(tables, format('%s.%s', quote_ident(rec2.sc), quote_ident(rec2.p)));
END LOOP;
-- RAISE DEBUG 'Tables: %', tables;
@@ -65,3 +65,14 @@ BEGIN
return tables;
END
$$ LANGUAGE 'plpgsql' VOLATILE STRICT;
-- Keep CDB_QueryTables with same signature for backwards compatibility.
-- It should probably be removed in the future.
CREATE OR REPLACE FUNCTION CDB_QueryTables(query text)
RETURNS name[]
AS $$
BEGIN
RETURN CDB_QueryTablesText(query)::name[];
END
$$ LANGUAGE 'plpgsql' VOLATILE STRICT;

View File

@@ -1,21 +1,62 @@
CREATE OR REPLACE FUNCTION cartodb._CDB_total_relation_size(_schema_name TEXT, _table_name TEXT)
RETURNS bigint AS
$$
DECLARE relation_size bigint := 0;
BEGIN
BEGIN
SELECT pg_total_relation_size(format('"%s"."%s"', _schema_name, _table_name)) INTO relation_size;
EXCEPTION
WHEN undefined_table OR OTHERS THEN
RAISE NOTICE 'cartodb._CDB_total_relation_size(''%'', ''%'') caught error: % (%)', _schema_name, _table_name, SQLERRM, SQLSTATE;
END;
RETURN relation_size;
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
-- Return the estimated size of user data. Used for quota checking.
CREATE OR REPLACE FUNCTION CDB_UserDataSize(schema_name TEXT)
RETURNS bigint AS
$$
-- TODO: double check this query. Maybe use CDB_TableMetadata for lookup ?
-- also, it's "table_name" sounds sensible to search_path
--
-- NOTE: division by 2 is an hack for the_geom_webmercator
--
SELECT coalesce(int8(sum(pg_total_relation_size(schema_name || '.' || table_name)) / 2), 0)
AS quota
FROM information_schema.tables
WHERE table_catalog = current_database() AND table_schema = schema_name
DECLARE
total_size INT8;
BEGIN
WITH raster_tables AS (
SELECT o_table_name, r_table_name FROM raster_overviews
WHERE o_table_schema = schema_name AND o_table_catalog = current_database()
),
user_tables AS (
SELECT table_name FROM information_schema.tables
WHERE table_catalog = current_database() AND table_schema = schema_name
AND table_name != 'spatial_ref_sys'
AND table_name != 'cdb_tablemetadata'
AND table_type = 'BASE TABLE';
AND table_type = 'BASE TABLE'
),
table_cat AS (
SELECT
table_name,
EXISTS(select * from raster_tables where o_table_name = table_name) AS is_overview,
EXISTS(SELECT * FROM raster_tables WHERE r_table_name = table_name) AS is_raster
FROM user_tables
),
sizes AS (
SELECT COALESCE(INT8(SUM(cartodb._CDB_total_relation_size(schema_name, table_name)))) table_size,
CASE
WHEN is_overview THEN 0
WHEN is_raster THEN 1
ELSE 0.5 -- Division by 2 is for not counting the_geom_webmercator
END AS multiplier FROM table_cat GROUP BY is_overview, is_raster
)
SELECT sum(table_size*multiplier)::int8 INTO total_size FROM sizes;
IF total_size IS NOT NULL THEN
RETURN total_size;
ELSE
RETURN 0;
END IF;
END;
$$
LANGUAGE 'sql' VOLATILE;
LANGUAGE 'plpgsql' VOLATILE;
-- Return the estimated size of user data. Used for quota checking.
@@ -46,16 +87,20 @@ BEGIN
ELSE
schema_name := 'public';
END IF;
-- Hack to support old versions of CDB_CheckQuota with 2 params but without schema_name
IF TG_NARGS >= 2 AND TG_ARGV[1] <> '-1' THEN
qmax := TG_ARGV[1];
ELSE
-- By default try to use quota function, and if not present then rely on the one specified by params
BEGIN
EXECUTE FORMAT('SELECT %I._CDB_UserQuotaInBytes();', schema_name) INTO qmax;
EXCEPTION WHEN undefined_function THEN
BEGIN
EXECUTE FORMAT('SELECT %I._CDB_UserQuotaInBytes();', schema_name) INTO qmax;
EXCEPTION WHEN undefined_function THEN
RAISE EXCEPTION 'Missing "%"._CDB_UserQuotaInBytes()', schema_name;
IF TG_NARGS >= 2 AND TG_ARGV[1] <> '-1' THEN
qmax := TG_ARGV[1];
ELSE
RAISE EXCEPTION 'Missing "%"._CDB_UserQuotaInBytes()', schema_name;
END IF;
END;
END IF;
END;
pbfact := TG_ARGV[0];
dice := random();

View File

@@ -0,0 +1,47 @@
--
-- Calculate basic statistics of a given dataset
--
-- @param in_array A numeric array of numbers
--
-- Returns: statistical quantity chosen
--
-- References: http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
--
-- Calculate kurtosis
CREATE OR REPLACE FUNCTION CDB_Kurtosis ( in_array NUMERIC[] ) RETURNS NUMERIC as $$
DECLARE
a numeric;
c numeric;
s numeric;
k numeric;
BEGIN
SELECT AVG(e), COUNT(e)::numeric, stddev(e) INTO a, c, s FROM ( SELECT unnest(in_array) e ) x;
EXECUTE 'SELECT sum(power($1 - e, 4)) / ( $2 * power($3, 4)) - 3
FROM (SELECT unnest($4) e ) x'
INTO k
USING a, c, s, in_array;
RETURN k;
END;
$$ language plpgsql IMMUTABLE;
-- Calculate skewness
CREATE OR REPLACE FUNCTION CDB_Skewness ( in_array NUMERIC[] ) RETURNS NUMERIC as $$
DECLARE
a numeric;
c numeric;
s numeric;
sk numeric;
BEGIN
SELECT AVG(e), COUNT(e)::numeric, stddev(e) INTO a, c, s FROM ( SELECT unnest(in_array) e ) x;
EXECUTE 'SELECT sum(power($1 - e, 3)) / ( $2 * power($3, 3))
FROM (SELECT unnest($4) e ) x'
INTO sk
USING a, c, s, in_array;
RETURN sk;
END;
$$ language plpgsql IMMUTABLE;

View File

@@ -1,8 +1,9 @@
-- Convert string to date
--
DROP FUNCTION IF EXISTS CDB_StringToDate(character varying);
CREATE OR REPLACE FUNCTION CDB_StringToDate(input character varying)
RETURNS date AS $$
DECLARE output DATE;
RETURNS TIMESTAMP AS $$
DECLARE output TIMESTAMP;
BEGIN
BEGIN
output := input::date;

View File

@@ -5,9 +5,9 @@ CREATE TABLE IF NOT EXISTS
updated_at timestamp with time zone not null default now()
);
-- Anyone can see this, but updates are only possible trough
-- the security definer trigger
GRANT SELECT ON public.CDB_TableMetadata TO public;
-- No one can see this
-- Updates are only possible trough the security definer trigger
-- GRANT SELECT ON public.CDB_TableMetadata TO public;
--
-- Trigger logging updated_at in the CDB_TableMetadata
@@ -118,3 +118,21 @@ CREATE TRIGGER table_modified AFTER INSERT OR UPDATE
ON CDB_TableMetadata FOR EACH ROW EXECUTE PROCEDURE
_CDB_TableMetadata_Updated();
-- similar to TOUCH(1) in unix filesystems but for table in cdb_tablemetadata
CREATE OR REPLACE FUNCTION public.CDB_TableMetadataTouch(tablename regclass)
RETURNS void AS
$$
BEGIN
WITH upsert AS (
UPDATE public.cdb_tablemetadata
SET updated_at = NOW()
WHERE tabname = tablename
RETURNING *
)
INSERT INTO public.cdb_tablemetadata (tabname, updated_at)
SELECT tablename, NOW()
WHERE NOT EXISTS (SELECT * FROM upsert);
END;
$$
LANGUAGE 'plpgsql' VOLATILE STRICT;

View File

@@ -5,35 +5,22 @@
--
-- Currently accepted permissions are: 'public', 'private' or 'all'
--
DROP FUNCTION IF EXISTS CDB_UserTables(text);
CREATE OR REPLACE FUNCTION CDB_UserTables(perm text DEFAULT 'all')
RETURNS SETOF information_schema.sql_identifier
RETURNS SETOF name
AS $$
WITH usertables AS (
-- TODO: query CDB_TableMetadata for this ?
-- See http://github.com/CartoDB/cartodb/issues/254#issuecomment-26044777
SELECT table_name as t
FROM information_schema.tables
WHERE
table_type='BASE TABLE'
AND table_schema='public'
AND table_name NOT IN (
'cdb_tablemetadata',
'spatial_ref_sys'
)
), perms AS (
SELECT t, has_table_privilege('public', 'public'||'.'||t, 'SELECT') as p
FROM usertables
)
SELECT t FROM perms
WHERE (
p = CASE WHEN $1 = 'private' THEN false
WHEN $1 = 'public' THEN true
ELSE not p -- none
END
OR $1 = 'all'
)
AND has_table_privilege('public'||'.'||t, 'SELECT')
;
SELECT c.relname
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND c.relname NOT IN ('cdb_tablemetadata', 'spatial_ref_sys')
AND 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')
ELSE false END;
$$ LANGUAGE 'sql';
-- This is to migrate from pre-0.2.0 version

View File

@@ -0,0 +1,31 @@
CREATE OR REPLACE FUNCTION cartodb.CDB_ZoomFromScale(scaleDenominator numeric) RETURNS int AS $$
BEGIN
CASE
WHEN scaleDenominator > 1000000000 THEN RETURN 0;
WHEN scaleDenominator <= 1000000000 AND scaleDenominator > 500000000 THEN RETURN 1;
WHEN scaleDenominator <= 500000000 AND scaleDenominator > 200000000 THEN RETURN 2;
WHEN scaleDenominator <= 200000000 AND scaleDenominator > 100000000 THEN RETURN 3;
WHEN scaleDenominator <= 100000000 AND scaleDenominator > 50000000 THEN RETURN 3;
WHEN scaleDenominator <= 50000000 AND scaleDenominator > 25000000 THEN RETURN 4;
WHEN scaleDenominator <= 25000000 AND scaleDenominator > 12500000 THEN RETURN 5;
WHEN scaleDenominator <= 12500000 AND scaleDenominator > 6500000 THEN RETURN 6;
WHEN scaleDenominator <= 6500000 AND scaleDenominator > 3000000 THEN RETURN 7;
WHEN scaleDenominator <= 3000000 AND scaleDenominator > 1500000 THEN RETURN 8;
WHEN scaleDenominator <= 1500000 AND scaleDenominator > 750000 THEN RETURN 9;
WHEN scaleDenominator <= 750000 AND scaleDenominator > 400000 THEN RETURN 10;
WHEN scaleDenominator <= 400000 AND scaleDenominator > 200000 THEN RETURN 11;
WHEN scaleDenominator <= 200000 AND scaleDenominator > 100000 THEN RETURN 12;
WHEN scaleDenominator <= 100000 AND scaleDenominator > 50000 THEN RETURN 13;
WHEN scaleDenominator <= 50000 AND scaleDenominator > 25000 THEN RETURN 14;
WHEN scaleDenominator <= 25000 AND scaleDenominator > 12500 THEN RETURN 15;
WHEN scaleDenominator <= 12500 AND scaleDenominator > 5000 THEN RETURN 16;
WHEN scaleDenominator <= 5000 AND scaleDenominator > 2500 THEN RETURN 17;
WHEN scaleDenominator <= 2500 AND scaleDenominator > 1500 THEN RETURN 18;
WHEN scaleDenominator <= 1500 AND scaleDenominator > 750 THEN RETURN 19;
WHEN scaleDenominator <= 750 AND scaleDenominator > 500 THEN RETURN 20;
WHEN scaleDenominator <= 500 AND scaleDenominator > 250 THEN RETURN 21;
WHEN scaleDenominator <= 250 AND scaleDenominator > 100 THEN RETURN 22;
WHEN scaleDenominator <= 100 THEN RETURN 23;
END CASE;
END
$$ LANGUAGE plpgsql IMMUTABLE;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,9 @@ 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';
@@ -16,29 +19,21 @@ SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
----------------------
-- CREATE TABLE
----------------------
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select 1 as i INTO c.t3;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i
from c.t3;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
-- Table with cartodb_id field, see
-- http://github.com/CartoDB/cartodb-postgresql/issues/32
select 1 as cartodb_id INTO c.t4;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator
from c.t4;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)) as age
@@ -47,32 +42,22 @@ 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;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc
from c.t3;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
FROM CDB_TableMetadata WHERE tabname = 'c.t3'::regclass;
SET SESSION AUTHORIZATION 'cartodb_postgresql_unpriv_user';
select pg_sleep(.1);
alter table c.t3 rename column the_geom_webmercator to webmerc2;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2
from c.t3;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -81,17 +66,11 @@ 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;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2
from c.t3;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -100,17 +79,11 @@ 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;
select
cartodb_id, created_at=updated_at as "c=u",
NOW() - updated_at < '1 secs' as "u<1s",
the_geom, the_geom_webmercator,
i, webmerc, webmerc2, id2
from c.t3;
RESET SESSION AUTHORIZATION;
select
tabname::text,
round(extract('secs' from now() - updated_at)*10) as agecs
@@ -124,5 +97,6 @@ RESET SESSION AUTHORIZATION;
drop schema c cascade;
select count(*) from CDB_TableMetadata;
DROP USER cartodb_postgresql_unpriv_user;
DROP OWNED BY cartodb_postgresql_unpriv_user;
DROP ROLE cartodb_postgresql_unpriv_user;
DROP FUNCTION _CDB_UserQuotaInBytes();

View File

@@ -7,4 +7,4 @@ RETURNS void AS $$
BEGIN
RAISE NOTICE 'cdb_invalidate_varnish(%) called', table_name;
END;
$$ LANGUAGE 'plpgsql';
$$ LANGUAGE 'plpgsql';

View File

@@ -1,5 +1,5 @@
SET client_min_messages TO error;
\set VERBOSITY terse;
\set VERBOSITY default
CREATE OR REPLACE FUNCTION CDB_CartodbfyTableCheck(tabname regclass, label text)
RETURNS text AS
@@ -12,6 +12,7 @@ DECLARE
tmp INTEGER;
ogc_geom geometry_columns; -- old the_geom record in geometry_columns
ogc_merc geometry_columns; -- old the_geom_webmercator record in geometry_columns
tabtext TEXT;
BEGIN
-- Save current constraints on geometry columns, if any
@@ -30,24 +31,17 @@ BEGIN
END IF;
END LOOP;
tabtext := Format('%s.%s','public',tabname);
RAISE NOTICE 'CARTODBFYING % !!!!', tabtext;
PERFORM CDB_CartodbfyTable('public', tabname);
tabname := tabtext::regclass;
sql := 'INSERT INTO ' || tabname::text || '(the_geom) values ( CDB_LatLng(2,1) ) RETURNING cartodb_id';
EXECUTE sql INTO STRICT id;
sql := 'SELECT created_at,updated_at,the_geom_webmercator FROM '
sql := 'SELECT the_geom_webmercator FROM '
|| tabname::text || ' WHERE cartodb_id = ' || id;
EXECUTE sql INTO STRICT rec;
-- Check created_at and updated_at at creation time
lag = rec.created_at - now();
IF lag > '1 second' THEN
RAISE EXCEPTION 'created_at not defaulting to now() after insert [ valued % ago ]', lag;
END IF;
lag = rec.updated_at - now();
IF lag > '1 second' THEN
RAISE EXCEPTION 'updated_at not defaulting to now() after insert [ valued % ago ]', lag;
END IF;
-- Check the_geom_webmercator trigger
IF round(st_x(rec.the_geom_webmercator)) != 111319 THEN
RAISE EXCEPTION 'the_geom_webmercator X is % (expecting 111319)', round(st_x(rec.the_geom_webmercator));
@@ -84,7 +78,7 @@ BEGIN
rec.f_geometry_column, rec.srid, rec.expsrid;
END IF;
-- Check TYPE constraint didn't change
IF rec.type != rec.exptype THEN
IF (rec.type != 'GEOMETRY') AND (rec.type != 'POINT') THEN
RAISE EXCEPTION 'type of % in geometry_columns is %, expected %',
rec.f_geometry_column, rec.type, rec.exptype;
END IF;
@@ -115,10 +109,10 @@ BEGIN
-- Check null constraint on cartodb_id, created_at, updated_at
SELECT count(*) FROM pg_attribute a, pg_class c WHERE c.oid = tabname::oid
AND a.attrelid = c.oid AND NOT a.attisdropped AND a.attname in
( 'cartodb_id', 'created_at', 'updated_at' )
( 'cartodb_id' )
AND NOT a.attnotnull INTO strict tmp;
IF tmp > 0 THEN
RAISE EXCEPTION 'cartodb_id or created_at or updated_at are missing not-null constraint';
RAISE EXCEPTION 'cartodb_id is missing not-null constraint';
END IF;
-- Cleanup
@@ -170,34 +164,48 @@ SELECT CDB_CartodbfyTableCheck('t', 'trigger-protected the_geom');
SELECT 'extent',ST_Extent(ST_SnapToGrid(the_geom,0.2)) FROM t;
DROP TABLE t;
-- table with existing updated_at and created_at fields ot type text
CREATE TABLE t AS SELECT NOW()::text as created_at,
NOW()::text as updated_at,
NOW() as reftime;
SELECT CDB_CartodbfyTableCheck('t', 'text timestamps');
SELECT extract(secs from reftime-created_at),
extract(secs from reftime-updated_at) FROM t;
CREATE VIEW v AS SELECT * FROM t;
SELECT CDB_CartodbfyTableCheck('t', 'cartodbfied with view');
DROP VIEW v;
DROP TABLE t;
-- INFO: disabled because cartodbfy does not longer consider text columns for primary ID
-- -- table with existing cartodb_id field of type text
-- CREATE TABLE t AS SELECT 10::text as cartodb_id;
-- SELECT CDB_CartodbfyTableCheck('t', 'text cartodb_id');
-- select cartodb_id/2 FROM t;
-- DROP TABLE t;
-- table with existing cartodb_id field of type text
CREATE TABLE t AS SELECT 10::text as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'text cartodb_id');
select cartodb_id/2 FROM t;
DROP TABLE t;
-- table with existing cartodb_id field of type text not casting
CREATE TABLE t AS SELECT 'nan' as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'uncasting text cartodb_id');
select cartodb_id,_cartodb_id0 FROM t;
DROP TABLE t;
-- INFO: disabled because cartodbfy does not longer consider text columns for primary ID
-- -- table with existing cartodb_id field of type text not casting
-- CREATE TABLE t AS SELECT 'nan' as cartodb_id;
-- SELECT CDB_CartodbfyTableCheck('t', 'uncasting text cartodb_id');
-- select cartodb_id,_cartodb_id0 FROM t;
-- DROP TABLE t;
-- table with existing cartodb_id field of type int4 not sequenced
CREATE TABLE t AS SELECT 1::int4 as cartodb_id;
SELECT CDB_CartodbfyTableCheck('t', 'unsequenced cartodb_id');
select cartodb_id FROM t;
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;
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;
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;
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;
DROP TABLE t;
-- table with existing cartodb_id serial primary key
@@ -208,21 +216,71 @@ WHERE c.conrelid = 't'::regclass and a.attrelid = c.conrelid
AND c.conkey[1] = a.attnum AND NOT a.attisdropped;
DROP TABLE t;
-- table with existing the_geom and created_at and containing null values
-- Really, a test for surviving an longstanding PostgreSQL bug:
-- http://www.postgresql.org/message-id/20140530143150.GA11051@localhost
CREATE TABLE t (
the_geom geometry(Geometry,4326),
created_at timestamptz,
updated_at timestamptz
-- tables can be renamed and there's no index name clashing #123
CREATE TABLE original();
SELECT CDB_CartodbfyTable('original');
ALTER TABLE original RENAME TO original_renamed;
CREATE TABLE original();
SELECT CDB_CartodbfyTable('original');
DROP TABLE original_renamed;
DROP TABLE original;
-- Table always have a default seq value after cartodbfy #138
CREATE TABLE bug_empty_table_no_seq (
cartodb_id integer,
the_geom geometry(Geometry,4326),
the_geom_webmercator geometry(Geometry,3857),
name text,
description text
);
COPY t (the_geom, created_at, updated_at) FROM stdin;
0106000020E610000001000000010300000001000000050000009EB8244146435BC017B65E062AD343409EB8244146435BC0F51AF6E2708044400B99891683765AC0F51AF6E2708044400B99891683765AC017B65E062AD343409EB8244146435BC017B65E062AD34340 2012-06-06 21:59:08 2013-06-10 20:17:20
0106000020E61000000100000001030000000100000005000000DA7763431A1A5CC0FBCEE869313C3A40DA7763431A1A5CC09C1B8F55BC494440F9F4A9C7993356C09C1B8F55BC494440F9F4A9C7993356C0FBCEE869313C3A40DA7763431A1A5CC0FBCEE869313C3A40 2012-06-06 21:59:08 2013-06-10 20:17:20
\N \N \N
\.
SELECT CDB_CartodbfyTableCheck('t', 'null geom and timestamp values');
DROP TABLE t;
SELECT CDB_CartodbfyTableCheck('bug_empty_table_no_seq', 'Table always have a default seq value after cartodbfy #138');
INSERT INTO bug_empty_table_no_seq DEFAULT VALUES;
DROP TABLE bug_empty_table_no_seq;
-- Existing cartodb_id values are respected
CREATE table existing_cartodb_id (
cartodb_id integer,
the_geom geometry(Geometry,4326),
the_geom_webmercator geometry(Geometry,3857),
name text,
description text
);
INSERT INTO existing_cartodb_id (cartodb_id, description) VALUES
(10, 'a'),
(20, 'b'),
(30, 'c');
SELECT CDB_CartodbfyTableCheck('existing_cartodb_id', 'Existing cartodb_id values are respected #138');
SELECT * from existing_cartodb_id;
DROP TABLE existing_cartodb_id;
-- Table with both the_geom and wkb_geometry
CREATE TABLE many_geometry_columns (
the_geom geometry,
wkb_geometry geometry(MultiPoint,4326),
description varchar
);
INSERT INTO many_geometry_columns (the_geom, wkb_geometry) VALUES
('0104000020E61000000100000001010000007108B023698052C03CEEA53A2E5D4440', '0104000020E61000000100000001010000007108B023698052C03CEEA53A2E5D4440'),
('0104000020E6100000010000000101000000864C9E57618052C0994F0C7F3C5B4440', '0104000020E6100000010000000101000000864C9E57618052C0994F0C7F3C5B4440');
SELECT CDB_CartodbfyTableCheck('many_geometry_columns', 'Table with both the_geom and wkb_geometry #141');
SELECT * FROM many_geometry_columns;
DROP TABLE many_geometry_columns;
-- Many colliding geom columns
CREATE TABLE many_colliding_columns (
the_geom varchar,
the_geom_webmercator varchar,
my_geom geometry,
my_mercgeom geometry(Point, 3857),
cartodb_id varchar,
my_pk integer primary key
);
INSERT INTO many_colliding_columns VALUES (
'foo', 'bar', 'SRID=4326;POINT(0 0)', 'SRID=3857;POINT(0 0)', 'nerf', 1
);
SELECT CDB_CartodbfyTableCheck('many_colliding_columns', 'Many colliding columns #141');
DROP TABLE many_colliding_columns;
-- TODO: table with existing custom-triggered the_geom

View File

@@ -2,6 +2,8 @@ SET
CREATE FUNCTION
SELECT 1
ERROR: Please set user quota before cartodbfying tables.
CONTEXT: SQL statement "SELECT cartodb._CDB_check_prerequisites(destschema, reloid)"
PL/pgSQL function cdb_cartodbfytable(text,regclass) line 21 at PERFORM
0
single non-geometrical column cartodbfied fine
DROP TABLE
@@ -26,30 +28,56 @@ trigger-protected the_geom cartodbfied fine
extent|BOX(1 1,2 2)
DROP TABLE
SELECT 1
text timestamps cartodbfied fine
0|0
CREATE VIEW
cartodbfied with view cartodbfied fine
DROP VIEW
DROP TABLE
SELECT 1
text cartodb_id cartodbfied fine
5
DROP TABLE
SELECT 1
uncasting text cartodb_id cartodbfied fine
1|nan
DROP TABLE
SELECT 1
unsequenced cartodb_id cartodbfied fine
1
DROP TABLE
SELECT 1
text the_geom column cartodbfied fine
1
DROP TABLE
SELECT 1
text the_geom column, no srs cartodbfied fine
1
DROP TABLE
SELECT 1
text the_geom column, srs = 26819 cartodbfied fine
1
DROP TABLE
SELECT 1
text the_geom column, unparseable content cartodbfied fine
1
DROP TABLE
CREATE TABLE
cartodb_id serial primary key cartodbfied fine
t_pkey|cartodb_id
DROP TABLE
CREATE TABLE
null geom and timestamp values cartodbfied fine
original
ALTER TABLE
CREATE TABLE
original
DROP TABLE
DROP TABLE
CREATE TABLE
Table always have a default seq value after cartodbfy #138 cartodbfied fine
INSERT 0 1
DROP TABLE
CREATE TABLE
INSERT 0 3
Existing cartodb_id values are respected #138 cartodbfied fine
10|||a|
20|||b|
30|||c|
DROP TABLE
CREATE TABLE
INSERT 0 2
Table with both the_geom and wkb_geometry #141 cartodbfied fine
1|0104000020E61000000100000001010000007108B023698052C03CEEA53A2E5D4440|0104000020110F00000100000001010000004A9F662B456D5FC11392690DC3F75241|
2|0104000020E6100000010000000101000000864C9E57618052C0994F0C7F3C5B4440|0104000020110F00000100000001010000002858E0EC376D5FC1CAE8DB4B95F55241|
DROP TABLE
CREATE TABLE
INSERT 0 1
Many colliding columns #141 cartodbfied fine
DROP TABLE
DROP FUNCTION
DROP FUNCTION

View File

@@ -0,0 +1,4 @@
WITH data AS (
SELECT pow(x,3)::numeric x FROM generate_series(-100,100) x
)
SELECT CDB_DistType(array_agg(x)) FROM data

View File

@@ -0,0 +1 @@
A

View File

@@ -0,0 +1,20 @@
-- a - j add up to 89%, k-m add up to 11%
WITH a As (
SELECT (
repeat('a',12) ||
repeat('b',11) ||
repeat('c',11) ||
repeat('d',10) ||
repeat('e',10) ||
repeat('f',9) ||
repeat('g',8) ||
repeat('h',7) ||
repeat('i',6) ||
repeat('j',5) ||
repeat('k',4) ||
repeat('l',4) ||
repeat('m',3)
)::text AS x
)
SELECT CDB_DistinctMeasure(string_to_array(x,null),0.90) from a

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,5 @@
WITH data AS (
SELECT array_agg(x::numeric) s FROM generate_series(1,300) x
WHERE x % 5 != 0 AND x % 7 != 0
)
SELECT round(unnest(CDB_EqualIntervalBins(s, 7)),7) FROM data

View File

@@ -0,0 +1,7 @@
43.5714286
86.1428571
128.7142857
171.2857143
213.8571429
256.4285714
299.0000000

4
test/CDB_MathTest.sql Normal file
View File

@@ -0,0 +1,4 @@
SELECT cdb_math_mode(a) from unnest(ARRAY[1,2,2,3]) a;
SELECT cdb_math_mode(a) from unnest(ARRAY[1,2,3]) a;
SELECT cdb_math_mode(a) from unnest(ARRAY[1]) a;

3
test/CDB_MathTest_expect Normal file
View File

@@ -0,0 +1,3 @@
2
1
1

View File

@@ -1,7 +1,7 @@
16
13
29
43
57
71
83
86
99

View File

@@ -31,3 +31,9 @@ create table sc.test (a int);
insert into sc.test values (1);
WITH inp AS ( select 'select * from sc.test'::text as q )
SELECT q, CDB_QueryTables(q) from inp;
DROP TABLE sc.test;
DROP SCHEMA sc;
WITH inp AS ( select 'SELECT
* FROM geometry_columns'::text as q )
SELECT q, CDB_QueryTables(q) from inp;

View File

@@ -4,12 +4,20 @@ CREATE table "my'tab;le" as select 1|{}
SELECT a.oid, b.oid FROM pg_class a, pg_class b|{pg_catalog.pg_class}
SELECT 1 as col1; select 2 as col2|{}
WARNING: CDB_QueryTables cannot explain query: select 1 from nonexistant (42P01: relation "nonexistant" does not exist)
CONTEXT: PL/pgSQL function cdb_querytables(text) line 3 at RETURN
ERROR: relation "nonexistant" does not exist
CONTEXT: PL/pgSQL function cdb_querytables(text) line 3 at RETURN
begin; select * from pg_class; commit;|{pg_catalog.pg_class}
WARNING: CDB_QueryTables cannot explain query: select * from test (42P01: relation "test" does not exist)
CONTEXT: PL/pgSQL function cdb_querytables(text) line 3 at RETURN
ERROR: relation "test" does not exist
CONTEXT: PL/pgSQL function cdb_querytables(text) line 3 at RETURN
WITH a AS (select * from pg_class) select * from a|{pg_catalog.pg_class}
CREATE SCHEMA
CREATE TABLE
INSERT 0 1
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}

View File

@@ -1,19 +1,31 @@
set client_min_messages to ERROR;
\set VERBOSITY terse
set client_min_messages to error;
\set VERBOSITY default
-- See the dice
SELECT setseed(0.5);
CREATE TABLE big(a int);
-- Try the legacy interface
-- See https://github.com/CartoDB/cartodb-postgresql/issues/13
CREATE TRIGGER test_quota BEFORE UPDATE OR INSERT ON big
EXECUTE PROCEDURE CDB_CheckQuota(1, 1, 'public');
INSERT INTO big VALUES (1); -- allowed, check runs before
INSERT INTO big VALUES (1); -- disallowed, quota exceeds before
INSERT INTO big VALUES (2); -- disallowed, quota exceeds before
SELECT CDB_SetUserQuotaInBytes(0);
SELECT CDB_CartodbfyTable('big');
INSERT INTO big SELECT generate_series(1,1024);
SELECT CDB_SetUserQuotaInBytes(8);
INSERT INTO big VALUES (1);
INSERT INTO big SELECT generate_series(2049,4096);
INSERT INTO big SELECT generate_series(4097,6144);
INSERT INTO big SELECT generate_series(6145,8192);
-- Test for #108: https://github.com/CartoDB/cartodb-postgresql/issues/108
SELECT CDB_UserDataSize();
SELECT cartodb._CDB_total_relation_size('public', 'big');
SELECT cartodb._CDB_total_relation_size('public', 'nonexistent_table_name');
-- END Test for #108
SELECT setseed(0.9);
SELECT CDB_SetUserQuotaInBytes(2);
INSERT INTO big VALUES (8193);
SELECT CDB_SetUserQuotaInBytes(0);
INSERT INTO big VALUES (1);
INSERT INTO big VALUES (8194);
DROP TABLE big;
set client_min_messages to NOTICE;
DROP FUNCTION _CDB_UserQuotaInBytes();

View File

@@ -1,13 +1,20 @@
SET
CREATE TABLE
CREATE TRIGGER
INSERT 0 1
ERROR: Quota exceeded by 3.9990234375KB
0
big
INSERT 0 2048
INSERT 0 2048
INSERT 0 2048
454656
909312
0
INSERT 0 1024
8
ERROR: Quota exceeded by 103.9921875KB
2
ERROR: Quota exceeded by 443.998046875KB
0
INSERT 0 1
DROP TABLE

13
test/CDB_StatsTest.sql Normal file
View File

@@ -0,0 +1,13 @@
-- continuous uniform distribution has kurtosis = -6/5, skewness = 0.0
-- http://mathworld.wolfram.com/UniformDistribution.html
set client_min_messages to ERROR;
WITH dist AS (
SELECT generate_series(0,10000)::numeric / 10000.0 i
)
SELECT
abs(CDB_Kurtosis(array_agg(i)) + 1.2) < 1e-3 AS kurtosis,
abs(CDB_Skewness(array_agg(i))) < 1e-3 AS skewness
FROM dist;
set client_min_messages to NOTICE;

View File

@@ -0,0 +1,3 @@
SET
t|t
SET

View File

@@ -1,11 +1,19 @@
create table pub(a int);
create table prv(a int);
GRANT SELECT ON TABLE pub TO public;
REVOKE SELECT ON TABLE prv FROM public;
CREATE ROLE publicuser LOGIN;
CREATE TABLE pub(a int);
CREATE TABLE prv(a int);
GRANT SELECT ON TABLE pub TO publicuser;
REVOKE SELECT ON TABLE prv FROM publicuser;
SELECT CDB_UserTables() ORDER BY 1;
SELECT 'all',CDB_UserTables('all') ORDER BY 2;
SELECT 'public',CDB_UserTables('public') ORDER BY 2;
SELECT 'private',CDB_UserTables('private') ORDER BY 2;
SELECT '--unsupported--',CDB_UserTables('--unsupported--') ORDER BY 2;
drop table pub;
drop table prv;
-- now tests with public user
\c contrib_regression publicuser
SELECT 'all_publicuser',CDB_UserTables('all') ORDER BY 2;
SELECT 'public_publicuser',CDB_UserTables('public') ORDER BY 2;
SELECT 'private_publicuser',CDB_UserTables('private') ORDER BY 2;
\c contrib_regression postgres
DROP TABLE pub;
DROP TABLE prv;
DROP ROLE publicuser;

View File

@@ -1,3 +1,4 @@
CREATE ROLE
CREATE TABLE
CREATE TABLE
GRANT
@@ -8,5 +9,10 @@ all|prv
all|pub
public|pub
private|prv
You are now connected to database "contrib_regression" as user "publicuser".
all_publicuser|pub
public_publicuser|pub
You are now connected to database "contrib_regression" as user "postgres".
DROP TABLE
DROP TABLE
DROP ROLE

View File

@@ -5,5 +5,5 @@ inp AS ( select z0.z, r1.r as x, r2.r as y FROM zoom z0, range r1, range r2 WHER
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)
from ext;
from ext order by xyz;

View File

@@ -1,13 +1,13 @@
0,0,0|-20037508.5|20037508.5|-20037508.5|20037508.5
0,0,1|-20037508.5|0|0|20037508.5
0,1,1|-20037508.5|0|-20037508.5|0
1,0,1|0|20037508.5|0|20037508.5
1,1,1|0|20037508.5|-20037508.5|0
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

View File

@@ -0,0 +1,6 @@
SET SCHEMA 'cartodb';
\i scripts-available/CDB_Quota.sql
\i scripts-available/CDB_TableMetadata.sql
\i scripts-available/CDB_ColumnNames.sql
\i scripts-available/CDB_ColumnType.sql
SET SCHEMA 'public';

436
test/extension/test.sh Executable file
View File

@@ -0,0 +1,436 @@
#!/bin/sh
#
# Tests for the extension since version 0.5.0. They don't replace SQL based ones, for now need to run both
#
# It is expected that you run this script as a PostgreSQL superuser, for example:
#
# PGUSER=postgres bash ./test.sh
#
DATABASE=test_extension
CMD='echo psql'
CMD=psql
OK=0
PARTIALOK=0
function set_failed() {
OK=1
PARTIALOK=1
}
function clear_partial_result() {
PARTIALOK=0
}
function sql() {
local ROLE
local QUERY
if [[ $# -ge 2 ]]
then
ROLE="$1"
QUERY="$2"
else
QUERY="$1"
fi
if [ -n "${ROLE}" ]; then
log_debug "Executing query '${QUERY}' as ${ROLE}"
RESULT=`${CMD} -U "${ROLE}" ${DATABASE} -c "${QUERY}" -A -t`
else
log_debug "Executing query '${QUERY}'"
RESULT=`${CMD} ${DATABASE} -c "${QUERY}" -A -t`
fi
CODERESULT=$?
echo ${RESULT}
echo
if [[ ${CODERESULT} -ne 0 ]]
then
echo -n "FAILED TO EXECUTE QUERY: "
log_warning "${QUERY}"
if [[ "$3" != "fails" ]]
then
log_error "${QUERY}"
set_failed
fi
else
if [[ "$3" == "fails" ]]
then
log_error "QUERY: '${QUERY}' was expected to fail and it did not fail"
set_failed
fi
fi
if [[ "$3" == "should" ]]
then
if [[ "${RESULT}" != "$4" ]]
then
log_error "QUERY '${QUERY}' expected result '${4}' but got '${RESULT}'"
set_failed
fi
fi
if [[ "$3" == "should-not" ]]
then
if [[ "${RESULT}" == "$4" ]]
then
log_error "QUERY '${QUERY}' did not expect '${RESULT}'"
set_failed
fi
fi
}
function log_info()
{
echo
echo
echo
_log "1;34m" "$1"
}
function log_error() {
_log "1;31m" "$1"
}
function log_debug() {
_log "1;32m" "> $1"
}
function log_warning() {
_log "0;33m" "$1"
}
function _log() {
echo -e "\033[$1$2\033[0m"
}
# '############################ HELPERS #############################'
function create_role_and_schema() {
local ROLE=$1
sql "CREATE ROLE ${ROLE} LOGIN;"
sql "GRANT CONNECT ON DATABASE \"${DATABASE}\" TO ${ROLE};"
sql "CREATE SCHEMA ${ROLE} AUTHORIZATION ${ROLE};"
sql "SELECT cartodb.CDB_Organization_Create_Member('${ROLE}');"
}
function drop_role_and_schema() {
local ROLE=$1
sql "DROP SCHEMA \"${ROLE}\" CASCADE;"
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM \"${ROLE}\";"
sql "DROP ROLE \"${ROLE}\";"
}
function create_table() {
if [[ $# -ne 2 ]]
then
log_error "create_table requires two arguments: role and table_name"
exit 1
fi
local ROLE="$1"
local TABLENAME="$2"
sql ${ROLE} "CREATE TABLE ${ROLE}.${TABLENAME} ( a int );"
}
function create_raster_table() {
if [[ $# -ne 2 ]]
then
log_error "create_raster_table requires two arguments: role and table_name"
exit 1
fi
local RASTER_COL="the_raster_webmercator"
local ROLE="$1"
local TABLENAME="$2"
local OVERVIEW_TABLENAME="o_2_${TABLENAME}"
sql ${ROLE} "CREATE TABLE ${ROLE}.${TABLENAME} (rid serial PRIMARY KEY, ${RASTER_COL} raster);"
sql ${ROLE} "CREATE TABLE ${ROLE}.${OVERVIEW_TABLENAME} (rid serial PRIMARY KEY, ${RASTER_COL} raster);"
sql ${ROLE} "SELECT AddOverviewConstraints('${ROLE}','${OVERVIEW_TABLENAME}','${RASTER_COL}','${ROLE}','${TABLENAME}','${RASTER_COL}',2);"
}
function drop_raster_table() {
if [[ $# -ne 2 ]]
then
log_error "drop_raster_table requires two arguments: role and table_name"
exit 1
fi
local ROLE="$1"
local TABLENAME="$2"
local OVERVIEW_TABLENAME="o_2_${TABLENAME}"
sql ${ROLE} "DROP TABLE ${ROLE}.${OVERVIEW_TABLENAME};"
sql ${ROLE} "DROP TABLE ${ROLE}.${TABLENAME};"
}
function setup() {
${CMD} -c "CREATE DATABASE ${DATABASE}"
sql "CREATE SCHEMA cartodb;"
sql "GRANT USAGE ON SCHEMA cartodb TO public;"
sql "CREATE EXTENSION postgis;"
sql "CREATE EXTENSION plpythonu;"
log_info "########################### BOOTSTRAP ###########################"
${CMD} -d ${DATABASE} -f scripts-available/CDB_Organizations.sql
# trick to allow forcing a schema when loading SQL files (see: http://bit.ly/1HeLnhL)
${CMD} -d ${DATABASE} -f test/extension/run_at_cartodb_schema.sql
log_info "############################# SETUP #############################"
create_role_and_schema cdb_testmember_1
create_role_and_schema cdb_testmember_2
create_table cdb_testmember_1 foo
sql cdb_testmember_1 'INSERT INTO cdb_testmember_1.foo VALUES (1), (2), (3), (4), (5), (6);'
sql cdb_testmember_1 'SELECT * FROM cdb_testmember_1.foo;'
create_table cdb_testmember_2 bar
sql cdb_testmember_2 'INSERT INTO bar VALUES (1), (2), (3);'
sql cdb_testmember_2 'SELECT * FROM cdb_testmember_2.bar;'
}
function tear_down() {
log_info "########################### USER TEAR DOWN ###########################"
sql cdb_testmember_1 "SELECT * FROM cartodb.CDB_Organization_Remove_Access_Permission('cdb_testmember_1', 'foo', 'cdb_testmember_2');"
sql cdb_testmember_2 "SELECT * FROM cartodb.CDB_Organization_Remove_Access_Permission('cdb_testmember_2', 'bar', 'cdb_testmember_1');"
sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.foo;'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.bar;'
sql "DROP SCHEMA cartodb CASCADE"
log_info "########################### TEAR DOWN ###########################"
sql 'DROP SCHEMA cdb_testmember_1 CASCADE;'
sql 'DROP SCHEMA cdb_testmember_2 CASCADE;'
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_1;"
sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_2;"
sql 'DROP ROLE cdb_testmember_1;'
sql 'DROP ROLE cdb_testmember_2;'
${CMD} -c "DROP DATABASE ${DATABASE}"
}
function run_tests() {
local FAILED_TESTS=()
local TESTS
if [[ $# -ge 1 ]]
then
if [[ $# -eq 1 ]]
then
TESTS=`cat $0 | grep -o "$1[^\(]*"`
else
TESTS="$@"
fi
else
TESTS=`cat $0 | perl -n -e'/function (test.*)\(\)/ && print "$1\n"'`
fi
for t in ${TESTS}
do
echo "####################################################################"
echo "#"
echo "# Running: ${t}"
echo "#"
echo "####################################################################"
clear_partial_result
setup
eval ${t}
if [[ ${PARTIALOK} -ne 0 ]]
then
FAILED_TESTS+=(${t})
fi
tear_down
done
if [[ ${OK} -ne 0 ]]
then
echo
log_error "The following tests are failing:"
printf -- '\t%s\n' "${FAILED_TESTS[@]}"
fi
}
#################################################### TESTS GO HERE ####################################################
# Tests quota checking taking into account both geom and raster tables
function test_quota_for_each_user() {
# Normal tables add 4096 bytes
# Raster tables no longer add anything so also count as 4096
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 4096
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 4096
create_raster_table cdb_testmember_1 raster_1
create_raster_table cdb_testmember_2 raster_2
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 20480
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 20480
create_raster_table cdb_testmember_1 raster_3
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 36864
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 20480
drop_raster_table cdb_testmember_1 raster_1
drop_raster_table cdb_testmember_2 raster_2
drop_raster_table cdb_testmember_1 raster_3
sql cdb_testmember_1 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_1'::TEXT);" should 4096
sql cdb_testmember_2 "SELECT cartodb.CDB_UserDataSize('cdb_testmember_2'::TEXT);" should 4096
}
function test_cdb_tablemetadatatouch() {
sql "CREATE TABLE touch_example (a int)"
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should ''
sql "SELECT CDB_TableMetadataTouch('touch_example');"
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should-not ''
# Another call doesn't fail
sql "SELECT CDB_TableMetadataTouch('touch_example');"
sql postgres "SELECT updated_at FROM CDB_TableMetadata WHERE tabname = 'touch_example'::regclass;" should-not ''
# Works with qualified tables
sql "SELECT CDB_TableMetadataTouch('public.touch_example');"
sql "SELECT CDB_TableMetadataTouch('public.\"touch_example\"');"
sql "SELECT CDB_TableMetadataTouch('\"public\".touch_example');"
sql "SELECT CDB_TableMetadataTouch('\"public\".\"touch_example\"');"
# Works with OID
sql postgres "SELECT tabname from CDB_TableMetadata;" should 'touch_example'
sql postgres "SELECT count(*) from CDB_TableMetadata;" should 1
TABLE_OID=`${CMD} -U postgres ${DATABASE} -c "SELECT attrelid FROM pg_attribute WHERE attrelid = 'touch_example'::regclass limit 1;" -A -t`
# quoted OID works
sql "SELECT CDB_TableMetadataTouch('${TABLE_OID}');"
sql postgres "SELECT tabname from CDB_TableMetadata;" should 'touch_example'
sql postgres "SELECT count(*) from CDB_TableMetadata;" should 1
# non quoted OID works
sql "SELECT CDB_TableMetadataTouch(${TABLE_OID});"
sql postgres "SELECT tabname from CDB_TableMetadata;" should 'touch_example'
sql postgres "SELECT count(*) from CDB_TableMetadata;" should 1
#### test tear down
sql 'DROP TABLE touch_example;'
}
function test_cdb_tablemetadatatouch_fails_for_unexistent_table() {
sql postgres "SELECT CDB_TableMetadataTouch('unexistent_example');" fails
}
function test_cdb_tablemetadatatouch_fails_from_user_without_permission() {
sql "CREATE TABLE touch_example (a int);"
sql postgres "SELECT CDB_TableMetadataTouch('touch_example');"
sql cdb_testmember_1 "SELECT CDB_TableMetadataTouch('touch_example');" fails
sql postgres "GRANT ALL ON CDB_TableMetadata TO cdb_testmember_1;"
sql cdb_testmember_1 "SELECT CDB_TableMetadataTouch('touch_example');"
sql postgres "REVOKE ALL ON CDB_TableMetadata FROM cdb_testmember_1;"
}
function test_cdb_column_names() {
sql cdb_testmember_1 'CREATE TABLE cdb_testmember_1.table_cnames(c int, a int, r int, t int, o int);'
sql cdb_testmember_2 'CREATE TABLE cdb_testmember_2.table_cnames(d int, b int);'
sql cdb_testmember_1 "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('table_cnames') c) as s" should "carto"
sql cdb_testmember_2 "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('table_cnames') c) as s" should "db"
sql postgres "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('cdb_testmember_1.table_cnames'::regclass) c) as s" should "carto"
sql postgres "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('cdb_testmember_2.table_cnames') c) as s" should "db"
# Using schema from owner
sql cdb_testmember_1 "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('cdb_testmember_1.table_cnames') c) as s" should "carto"
## it's not possible to get column names from a table where you don't have permissions
sql cdb_testmember_2 "SELECT string_agg(c,'') from (SELECT cartodb.CDB_ColumnNames('cdb_testmember_1.table_cnames') c) as s" fails
sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.table_cnames'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.table_cnames'
}
function test_cdb_column_type() {
sql cdb_testmember_1 'CREATE TABLE cdb_testmember_1.table_ctype(c int, a int, r int, t int, o int);'
sql cdb_testmember_2 'CREATE TABLE cdb_testmember_2.table_ctype(c text, a text, r text, t text, o text);'
sql cdb_testmember_1 "SELECT cartodb.CDB_ColumnType('table_ctype', 'c')" should "integer"
sql cdb_testmember_2 "SELECT cartodb.CDB_ColumnType('table_ctype', 'c')" should "text"
sql postgres "SELECT cartodb.CDB_ColumnType('cdb_testmember_1.table_ctype', 'c')" should "integer"
sql postgres "SELECT cartodb.CDB_ColumnType('cdb_testmember_2.table_ctype', 'c')" should "text"
sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.table_ctype'
sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.table_ctype'
}
function test_cdb_querytables_schema_and_table_names_with_dots() {
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql postgres 'CREATE SCHEMA "foo.bar";'
sql postgres 'CREATE TABLE "foo.bar"."c.a.r.t.o.d.b" (a int);'
sql postgres 'INSERT INTO "foo.bar"."c.a.r.t.o.d.b" values (1);'
sql postgres 'SELECT a FROM "foo.bar"."c.a.r.t.o.d.b";' should 1
sql postgres 'SELECT CDB_QueryTablesText($q$select * from "foo.bar"."c.a.r.t.o.d.b"$q$);' should '{"\"foo.bar\".\"c.a.r.t.o.d.b\""}'
sql postgres 'SELECT CDB_QueryTables($q$select * from "foo.bar"."c.a.r.t.o.d.b"$q$);' should '{"\"foo.bar\".\"c.a.r.t.o.d.b\""}'
sql postgres 'DROP TABLE "foo.bar"."c.a.r.t.o.d.b";'
sql postgres 'DROP SCHEMA "foo.bar";'
}
function test_cdb_querytables_table_name_with_dots() {
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql postgres 'CREATE TABLE "w.a.d.u.s" (a int);';
sql postgres 'SELECT CDB_QueryTablesText($q$select * from "w.a.d.u.s"$q$);' should '{"public.\"w.a.d.u.s\""}'
sql postgres 'SELECT CDB_QueryTables($q$select * from "w.a.d.u.s"$q$);' should '{"public.\"w.a.d.u.s\""}'
sql postgres 'DROP TABLE "w.a.d.u.s";';
}
function test_cdb_querytables_happy_cases() {
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql
${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql
sql postgres 'CREATE TABLE wadus (a int);';
sql postgres 'CREATE TABLE "FOOBAR" (a int);';
sql postgres 'CREATE SCHEMA foo;'
sql postgres 'CREATE TABLE foo.wadus (a int);';
## See how it does NOT quote anything here
sql postgres 'SELECT CDB_QueryTablesText($q$select * from wadus$q$);' should '{public.wadus}'
sql postgres 'SELECT CDB_QueryTablesText($q$select * from foo.wadus$q$);' should '{foo.wadus}'
sql postgres 'SELECT CDB_QueryTables($q$select * from wadus$q$);' should '{public.wadus}'
sql postgres 'SELECT CDB_QueryTables($q$select * from foo.wadus$q$);' should '{foo.wadus}'
## But it quotes when it's needed even if table name has no dots but was created with quotes
sql postgres 'SELECT CDB_QueryTablesText($q$select * from "FOOBAR"$q$);' should '{"public.\"FOOBAR\""}'
sql postgres 'DROP TABLE wadus;'
sql postgres 'DROP TABLE "FOOBAR";'
sql postgres 'DROP TABLE foo.wadus;'
sql postgres 'DROP SCHEMA foo;'
}
#################################################### TESTS END HERE ####################################################
run_tests $@
exit ${OK}

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,15 +159,22 @@ 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;"
sql "GRANT CONNECT ON DATABASE \"${DATABASE}\" TO publicuser;"
create_table cdb_testmember_1 foo
sql cdb_testmember_1 'INSERT INTO cdb_testmember_1.foo VALUES (1), (2), (3), (4), (5);'
@@ -150,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');"
@@ -160,17 +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}"
}
@@ -194,6 +247,7 @@ function run_tests() {
echo "####################################################################"
clear_partial_result
setup
log_info "############################# TESTS #############################"
eval ${t}
if [[ ${PARTIALOK} -ne 0 ]]
then
@@ -325,6 +379,169 @@ function test_user_can_read_when_it_has_permission_after_organization_permission
drop_role_and_schema cdb_testmember_3
}
function test_cdb_querytables_returns_schema_and_table_name() {
${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() {
${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() {
${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}"
}
function test_cdb_usertables_should_work_with_orgusers() {
# This test validates the changes proposed in https://github.com/CartoDB/cartodb/pull/5021
# create tables
sql cdb_testmember_1 "CREATE TABLE test_perms_pub (a int)"
sql cdb_testmember_1 "INSERT INTO test_perms_pub (a) values (1);"
sql cdb_testmember_1 "GRANT SELECT ON TABLE test_perms_pub TO publicuser"
sql cdb_testmember_1 "CREATE TABLE test_perms_priv (a int)"
# this is what we need to make public tables available in CDB_UserTables
sql postgres "grant publicuser to cdb_testmember_1;"
sql postgres "grant publicuser to cdb_testmember_2;"
# this is required to enable select from other schema
sql postgres "GRANT USAGE ON SCHEMA cdb_testmember_1 TO publicuser";
# test CDB_UserTables with publicuser
${CMD} -d ${DATABASE} -f scripts-available/CDB_UserTables.sql
sql publicuser "SELECT count(*) FROM CDB_UserTables('all')" should 1
sql publicuser "SELECT count(*) FROM CDB_UserTables('public')" should 1
sql publicuser "SELECT count(*) FROM CDB_UserTables('private')" should 0
sql publicuser "SELECT * FROM CDB_UserTables('all')" should "test_perms_pub"
sql publicuser "SELECT * FROM CDB_UserTables('public')" should "test_perms_pub"
sql publicuser "SELECT * FROM CDB_UserTables('private')" should ""
# the following tests are for https://github.com/CartoDB/cartodb-postgresql/issues/98
# cdb_testmember_2 is already owner of `bar` table
sql cdb_testmember_2 "select string_agg(t,',') from (select cdb_usertables('all') t order by t) as s" should "bar,test_perms_pub"
sql cdb_testmember_2 "SELECT * FROM CDB_UserTables('public')" should "test_perms_pub"
sql cdb_testmember_2 "SELECT * FROM CDB_UserTables('private')" should "bar"
# test cdb_testmember_2 can select from cdb_testmember_1's public table
sql cdb_testmember_2 "SELECT * FROM cdb_testmember_1.test_perms_pub" should 1
sql cdb_testmember_1 "DROP TABLE test_perms_pub"
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 ####################################################