Compare commits

...

194 Commits

Author SHA1 Message Date
Mario de Frutos
eb5c7ec5c3 Merge pull request #341 from CartoDB/development
Release client 0.15.0 and server 0.21.0
2017-02-08 15:27:42 +01:00
Mario de Frutos
435a84f294 OBS_GetData functions shall increase the DO quota usage 2017-02-06 17:47:15 +01:00
Mario de Frutos
061956f250 Remove quota usage for obs_meta functions 2017-02-02 10:59:21 +01:00
Mario de Frutos
2621573d71 Extracted parameters from getmeta and getdata functions tests to fix
problems
2017-02-01 12:12:17 +01:00
Mario de Frutos
d7bb31be9a Client 0.15.0 version release artifacts 2017-02-01 10:52:56 +01:00
Mario de Frutos
3d94d1dfaf Server 0.21.0 version release artifacts 2017-02-01 10:19:32 +01:00
Mario de Frutos
c364c7f5ed Merge pull request #339 from CartoDB/obs-getdata-getmeta-wrappers
Obs_GetData OBS_GetMeta wrappers
2017-02-01 10:05:52 +01:00
Mario de Frutos
b2f9a10035 Change timespan for getboundaryid to 2015 2017-02-01 09:53:35 +01:00
Mario de Frutos
c550a5d4e9 Merge pull request #321 from CartoDB/fix-default-isolines-provider
Change default isolines provider
2017-02-01 09:41:21 +01:00
Mario de Frutos
b4fa0dd4fc Added integration tests for the new DO functions 2017-01-26 17:46:36 +01:00
Mario de Frutos
f0d96541b6 Fixed client tests 2017-01-26 17:00:56 +01:00
John Krauss
8094e79d0b fix some bugs in client test 2017-01-26 12:27:30 +01:00
John Krauss
bfd7df8c8a tmp commit 2017-01-26 12:27:29 +01:00
John Krauss
1f225e0978 fix extraneous newline in expectation 2017-01-26 12:27:29 +01:00
John Krauss
e81f005ce9 adding server tests, interface to generate client sql code 2017-01-26 12:27:29 +01:00
John Krauss
8204bb3451 fix error-causing raise (which obscures real error) 2017-01-26 12:27:29 +01:00
John Krauss
56de523498 add wrappers for getmeta, getdata(geoms) and getdata(ids) 2017-01-26 12:27:29 +01:00
Mario de Frutos
7fe8b6cccc Added CONTRIBUTING.md 2017-01-25 10:47:20 +01:00
piensaenpixel
ec3b99f258 Update quota_information.md 2017-01-11 12:45:59 +01:00
piensaenpixel
1a7e99b2fd Update quota_information.md 2017-01-11 12:43:51 +01:00
Rafa de la Torre
2ad9e508f5 Merge pull request #337 from CartoDB/335-fix-test-date-no-padding-bug
Fix tests: zero-pad months in redis key #335
2017-01-04 11:41:00 +01:00
Rafa de la Torre
a0dd7c7497 Fix tests: zero-pad months in redis key #335 2017-01-04 11:11:27 +01:00
Rafa de la Torre
9cbde7d319 Merge pull request #336 from CartoDB/master
Master
2017-01-03 15:10:00 +01:00
Rafa de la Torre
f7ecb30384 Merge pull request #333 from CartoDB/331-quota-info-doc
Add documentation about the quota information functions
2017-01-03 15:07:07 +01:00
Rafa de la Torre
6ca9e87035 Fix typo in doc: s/exceptio/exception #331 2017-01-03 14:55:48 +01:00
Rafa de la Torre
caa00c63fa Merge remote-tracking branch 'origin/development' into 331-quota-info-doc 2017-01-03 14:54:00 +01:00
csobier
dae8021efe applied copyedits to quote info docs 2017-01-03 08:35:57 -05:00
Javier Goizueta
ebbfae95cf Merge pull request #327 from CartoDB/mapzen_services_use_quotas
Mapzen services use quotas
2016-12-30 08:43:13 +01:00
Javier Goizueta
227c05bf70 Merge branch 'development' into mapzen_services_use_quotas
Bring in client 0.14.1 release
2016-12-30 08:29:54 +01:00
Rafa de la Torre
a800706249 Merge remote-tracking branch 'origin/master' into development 2016-12-29 17:27:56 +01:00
Rafa de la Torre
439f604a04 Merge pull request #334 from CartoDB/fix-cannot-find-geometry
Add cartodb to the search path
2016-12-29 12:43:34 +01:00
Rafa de la Torre
9791a5bada Add cartodb to the search path
See
https://github.com/CartoDB/dataservices-api/issues/324#issuecomment-269614566
2016-12-29 12:11:00 +01:00
Javier Goizueta
07616c468a Documantation fixes 2016-12-29 09:19:52 +01:00
Rafa de la Torre
9700ae966c Remove uneeded math for simplicity's sake 2016-12-28 14:44:48 +01:00
Javier Goizueta
bdf9627586 Fix typo
I needed to fix this; I felt some kitten was being killed somewhere
because of this. And it made baby Jesus cry.
2016-12-27 17:11:39 +01:00
Javier Goizueta
9abb81d0e7 Add documentation about the quota information functions
See #331
2016-12-27 16:51:52 +01:00
Mario de Frutos
80b23c62c3 QPS timeout was badly calculated
timedelta microseconds is just the microseconds part of the timedelta
object not the elapsed time in microseconds.

I've change to use the total_seconds method to get all the elapsed time
in seconds and transform to miliseconds.
2016-12-23 11:40:30 +01:00
Mario de Frutos
23a2de0321 Add mapzen isolines to the quota checker 2016-12-22 17:38:10 +01:00
Javier Goizueta
629555e193 Generate release 0.14.1
This release cantains no actual code changes, only the
use of search_path at the top of the install/migrate scripts
2016-12-21 11:40:55 +01:00
Javier Goizueta
af993fde55 Merge branch 'development'
Bring in the setting of the search_path in the client SQL scripts
2016-12-21 11:16:29 +01:00
Javier Goizueta
4be6c9f31d Merge pull request #330 from CartoDB/324-search-path
Set search path before installing/update the extension
2016-12-21 10:47:08 +01:00
Javier Goizueta
9ee1d045c8 Fix tests 2016-12-21 09:54:08 +01:00
Rafa de la Torre
360b5bd57f Merge remote-tracking branch 'origin/development' into mapzen_services_use_quotas
Solve merge conflict in setup.py (version of python lib).
2016-12-20 18:14:01 +01:00
Javier Goizueta
ed1386d571 Merge branch 'development' 2016-12-20 16:43:42 +01:00
Javier Goizueta
32010669e8 New version of the python lib
To fix bug with period end date; see #322
2016-12-20 16:39:19 +01:00
Javier Goizueta
b0f10d1680 Merge pull request #329 from CartoDB/322-period_end_date
Fix problem with period end dates
2016-12-20 16:33:39 +01:00
Mario de Frutos
38754fec26 Cover refactor mapzen geocoder config with tests 2016-12-20 16:17:42 +01:00
Mario de Frutos
356135672b Sanitize quota get in the refactor part 2016-12-20 16:17:42 +01:00
Mario de Frutos
4d0abf9026 Bump python library version 2016-12-20 16:17:42 +01:00
Mario de Frutos
0672f2752b Improve tests and add more unit tests for the quota functionality 2016-12-20 16:17:41 +01:00
Javier Goizueta
18df3368ef Set search path before installing/update the extension
See #324
2016-12-20 12:57:40 +01:00
Javier Goizueta
b5514aea60 Avoid invalid end of period dates
Fixes #322
2016-12-20 12:48:36 +01:00
Javier Goizueta
53acd4d30e Add tests that reveal end-of-period date problem
See #322
2016-12-20 12:41:54 +01:00
Mario de Frutos
6c71d73498 Use the current quota for mapzen services 2016-12-20 11:52:06 +01:00
Rafa de la Torre
a00fca6d13 Update README.md
Add a bit about versioning stuff
2016-12-16 18:00:22 +01:00
Rafa de la Torre
29caaf9297 Update README.md
Remove misleading paragraph about `requirements.txt` and `setup.py` dependencies. Refer to https://packaging.python.org/requirements/ for an authoritative discussion.
2016-12-16 18:00:22 +01:00
Rafa de la Torre
6e134d1ea6 Update exception_safe.md 2016-12-15 19:10:18 +01:00
Rafa de la Torre
59ae4a5492 Merge pull request #325 from CartoDB/exception-safe-doc
Add Exception-safe documentaion
2016-12-15 19:06:37 +01:00
Javier Goizueta
b3e67afd92 Add internal documentaion about exception-safe functions 2016-12-15 19:03:12 +01:00
Rafa de la Torre
5b8fd70bdd Merge remote-tracking branch 'origin/development' 2016-12-14 17:23:09 +01:00
Rafa de la Torre
15438db59b Client 0.14.0 control and upgrade/downgrade files 2016-12-14 16:52:40 +01:00
Rafa de la Torre
0918f91bfa Merge pull request #323 from CartoDB/314-exception-safe-public-funcs
314 exception safe public funcs
2016-12-14 16:34:09 +01:00
Rafa de la Torre
3c60f3e93b Minor improvement for test #314
Make sure we return an empty record and that the mentioned code is never
reached.
2016-12-14 13:30:30 +01:00
Rafa de la Torre
8692fb12ca Add test case for multi_field #314 2016-12-14 12:57:51 +01:00
Rafa de la Torre
4523b2e04d Add test for multi_row case #314 2016-12-14 12:53:51 +01:00
Rafa de la Torre
5c8dbe91eb Add test for simple interface case #314 2016-12-14 12:39:56 +01:00
Rafa de la Torre
99b76afc33 Some versioning facilities for make release #314 2016-12-14 12:08:26 +01:00
Rafa de la Torre
c97f03b2e3 Add generated file to .gitignore #314 2016-12-14 12:06:51 +01:00
Rafa de la Torre
cd653bc496 Add diagnostics info to rest of cases #314 2016-12-14 10:35:44 +01:00
Rafa de la Torre
610cfaab57 Move exception info vars to the top #314 2016-12-14 10:33:50 +01:00
Rafa de la Torre
58b1713a0d Make the functions private #314 2016-12-14 10:27:43 +01:00
Rafa de la Torre
842be0ba85 Add diagnostics info to warning #314 2016-12-13 19:19:03 +01:00
Javier Goizueta
55a467f2df Merge branch 'development'
merge python 0.12.3 release
2016-12-13 18:13:14 +01:00
Javier Goizueta
4fc90626ab New version of the python lib
New release to change number of http connection retries to 1
2016-12-13 18:03:37 +01:00
Javier Goizueta
16cce3bddc Merge pull request #320 from CartoDB/317-revert-retries
Revert number of isochrone retries to 3
2016-12-13 18:00:48 +01:00
Rafa de la Torre
dbd5911a2a Implement the multi_field case #314 2016-12-13 17:00:55 +01:00
Rafa de la Torre
e53a39875e Implement the multi_row case #314 2016-12-13 16:51:11 +01:00
Rafa de la Torre
4cd72616ca Fix the no multi_row, no multi_field case #314
Fix for the `ERROR:  control reached end of function without RETURN` but
now need to implement for the two other cases.
2016-12-13 16:46:58 +01:00
Rafa de la Torre
fae7889fe3 First take at producing exception-safe functions #314 2016-12-13 16:27:38 +01:00
Javier Goizueta
1f53af65b9 Set number of http connection retries to 1
Change the maximum number of retries for connection to external services to 1.
2016-12-13 11:32:22 +01:00
Javier Goizueta
96a147a242 The default isolines provider should be Mapzen 2016-12-13 10:19:27 +01:00
Javier Goizueta
79fb796180 Fix bug in retries usage; mantain behaviour
The number of retries was being passed as the pool size parameter.
This is corrected but number of retries changed to 1 to maintain previous behaviour.
2016-12-13 10:07:10 +01:00
Rafa de la Torre
0adb5164d7 Update README.md
Add a bit about versioning stuff
2016-12-12 17:54:02 +01:00
Rafa de la Torre
147e0ab567 Update README.md
Remove misleading paragraph about `requirements.txt` and `setup.py` dependencies. Refer to https://packaging.python.org/requirements/ for an authoritative discussion.
2016-12-12 17:42:46 +01:00
Javier Goizueta
2953fda75c Revert num of isochrone retries to 3
See #317
2016-12-12 12:14:10 +01:00
Rafa de la Torre
f716fbb502 Merge pull request #318 from CartoDB/317-timeouts-patch
317 timeouts patch
2016-12-07 16:50:44 +01:00
Rafa de la Torre
98fa248fff New version of the python lib #317 2016-12-07 16:39:28 +01:00
Rafa de la Torre
7c348dee0f Mapzen isochrones: tweak retry params #317 2016-12-07 16:38:47 +01:00
Rafa de la Torre
bdeaadf33f Fix QPS: Compare everything in microseconds #317 2016-12-07 16:37:25 +01:00
Rafa de la Torre
a977bc97ab Merge pull request #315 from CartoDB/add_retries_to_requests
Make the HTTP requests retry on timeout
2016-12-07 12:51:02 +01:00
Mario de Frutos
51face5593 Make the HTTP requests retry on timeout 2016-12-02 17:01:05 +01:00
Mario de Frutos
a60a6f04b1 Update NEWS.md 2016-12-01 16:49:01 +01:00
Mario de Frutos
190c9888d0 Merge pull request #313 from CartoDB/development
Release 0.20.0 and python 0.12.0
2016-11-29 16:41:44 +01:00
Mario de Frutos
77b2ac9155 Bump python version 2016-11-29 16:34:59 +01:00
Mario de Frutos
8edbf33ff1 Added denoise and generalize options to make the ischrones less heavy 2016-11-29 16:10:59 +01:00
Mario de Frutos
bd439d8985 Car is auto in mapzen isochrones 2016-11-29 13:18:52 +01:00
Mario de Frutos
16259862dd Version 0.20.0 artifact 2016-11-29 13:08:43 +01:00
Mario de Frutos
7c816be5e5 Merge pull request #312 from CartoDB/mapzen_isochrones_integration
Mapzen isochrones integration
2016-11-29 13:07:36 +01:00
Mario de Frutos
77f4f3e7ff Mapzen isochtrones integration 2016-11-29 12:57:23 +01:00
Mario de Frutos
4b714b3845 New version 0.20.0 2016-11-29 12:25:35 +01:00
Rafa de la Torre
59ed8b88a3 New client version 0.13.0 #302 2016-11-25 11:28:10 +01:00
Rafa de la Torre
ab4584bed3 New server version 0.19.0 #302 2016-11-25 10:56:41 +01:00
Rafa de la Torre
2b2691d0b9 New minor version of the python library #302 2016-11-25 10:43:06 +01:00
Rafa de la Torre
3524aabd9e Merge pull request #311 from CartoDB/302-expose-quotas
302 expose quotas
2016-11-25 10:37:48 +01:00
Rafa de la Torre
9c6eabc59e Do not enforce types for params #302
As types are tied to a schema, they don't get along very well with
pl/proxy. Do not use them for the service_type.
2016-11-24 18:38:33 +01:00
Rafa de la Torre
0d92eb4ba8 Fix issue with multi-field values #302
The difference between

```
=> select * from cdb_service_quota_info();
    service     | monthly_quota | used_quota | soft_limit |     provider
----------------+---------------+------------+------------+------------------
 isolines       |          1000 |          0 | f          | heremaps
 hires_geocoder |             5 |          2 | f          | mapzen
 routing        |       1500000 |          0 | f          | mapzen
 observatory    |          1000 |          0 | f          | data observatory
(4 rows)
```

and

```
=> select cdb_service_quota_info();
          cdb_service_quota_info
-------------------------------------------
 (isolines,1000,0,f,heremaps)
 (hires_geocoder,5,2,f,mapzen)
 (routing,1500000,0,f,mapzen)
 (observatory,1000,0,f,"data observatory")
(4 rows)
```

is important to pl/proxy. In the later case, rows only have one field
(a tuple) and it complains with "Got too few fields from remote end".
2016-11-24 18:24:17 +01:00
Rafa de la Torre
769b740ba4 Rename service_params to service_quota_info #302 2016-11-24 17:46:07 +01:00
Rafa de la Torre
c2ede37d75 Revert internal geocoder related stuff #302 2016-11-24 17:45:19 +01:00
Rafa de la Torre
4c75c5f261 Revert internal geocoder related stuff #302
This reverts commits 579d11e, 4af5975 and a2da597
2016-11-24 17:33:06 +01:00
Rafa de la Torre
f07d2f9302 Remove the no_params from client generator #302 2016-11-24 13:27:32 +01:00
Rafa de la Torre
37a3214f67 Add quota functions to client #302 2016-11-24 13:05:31 +01:00
Rafa de la Torre
efb10e43e4 Merge remote-tracking branch 'origin/development' into 302-expose-quotas 2016-11-24 12:36:23 +01:00
Rafa de la Torre
1dc6060570 Fix: deal with string values for soft limits #302 2016-11-23 18:51:13 +01:00
Rafa de la Torre
a2da597e00 Support null quota (internal_geocoder) #302 2016-11-23 18:10:44 +01:00
Rafa de la Torre
4af5975ac1 Add the internal geocoder to cdb_service_params #302 2016-11-23 17:07:23 +01:00
Rafa de la Torre
579d11ebd5 Add params to InternalGeocoderConfig #302
Add a bunch of params to InternalGeocoderConfig for consistency with
other services:
- monthly_quota
- period_end_date
- soft_limit
2016-11-23 17:04:50 +01:00
Rafa de la Torre
a1eae3934c Add OBS to UserMetricsService #302 2016-11-23 16:47:35 +01:00
Rafa de la Torre
d70d149eed Fix bug: the service_type to used_quota #302 2016-11-23 16:40:00 +01:00
Rafa de la Torre
decc7626a8 Create types only if they don't exist #302 2016-11-23 16:38:47 +01:00
Rafa de la Torre
abbb227ad5 Fix typo: use obs config for obs service #302 2016-11-23 11:40:02 +01:00
Rafa de la Torre
970927375e Merge pull request #310 from CartoDB/fix-typo-doc
Fix typo: replace "isolines" with "routes" in routing api docs
2016-11-21 14:39:59 +01:00
Mario de Frutos
6f2883be5d Merge pull request #309 from CartoDB/development
Release client 0.12.1 and server 0.18.1
2016-11-21 13:44:38 +01:00
Rafa de la Torre
06df5a84c4 Fix typo: s/isolines/routes/ 2016-11-21 11:51:51 +01:00
csobier
5d94a852e4 Merge pull request #300 from CartoDB/docs-1129-edits
Docs 1129 edits
2016-11-14 07:41:35 -05:00
Mario de Frutos
f0474852f2 Client 0.12.1 and server 0.18.1 artifacts 2016-11-11 18:27:37 +01:00
Mario de Frutos
975efb0f92 Merge pull request #308 from CartoDB/update_do_getavailablegeometries
Update do getavailablegeometries
2016-11-11 18:27:00 +01:00
Mario de Frutos
7f963d2f7a Client update to type obs_meta_geometry with new types 2016-11-11 18:13:35 +01:00
Mario de Frutos
8396eae733 Server update to type obs_meta_geometry with new types 2016-11-11 18:13:01 +01:00
Mario de Frutos
25cd40164a Client init new version 0.12.1 2016-11-11 17:55:35 +01:00
Mario de Frutos
dfaa037475 Server init new version 0.18.1 2016-11-11 17:53:20 +01:00
Mario de Frutos
c92ab9c207 Typo in integration test 2016-11-11 14:55:20 +01:00
Mario de Frutos
27806ead54 Merge pull request #307 from CartoDB/development
Release client 0.12.0 and server 0.18.0
2016-11-11 14:14:10 +01:00
Mario de Frutos
d1b17da70b Don't make mandatory to have a metrics file 2016-11-11 11:48:08 +01:00
Rafa de la Torre
2e6f37af56 Add observatory #302 2016-11-11 11:27:57 +01:00
Mario de Frutos
b5f4c507b3 Fixed some typos in SQL artifact v0.18 and v0.17 2016-11-11 11:13:08 +01:00
Rafa de la Torre
95dda082e7 Add routing #302 2016-11-11 10:24:03 +01:00
Mario de Frutos
d65a0d9ac5 Integration tests for the meta functions 2016-11-11 10:20:20 +01:00
Rafa de la Torre
9f9034f4f1 Make cdb_enough_quota check the table got from cdb_service_params #302 2016-11-10 19:23:39 +01:00
Rafa de la Torre
603fbbbc3f Make cdb_service_params return a table for all services #302 2016-11-10 19:23:01 +01:00
Rafa de la Torre
3fa686ec65 Remove the class Service in favor of service_type ENUM #302 2016-11-10 19:21:29 +01:00
Rafa de la Torre
429a71ef37 Add a function to check for enough quota #302 2016-11-10 18:56:50 +01:00
Rafa de la Torre
b2cdb1c74b Move all into one func returning a tuple #302 2016-11-10 18:40:18 +01:00
Rafa de la Torre
84061dec4f Move everything to cdb_service_params (WIP) #302 2016-11-10 18:12:24 +01:00
Mario de Frutos
08debb83ed Server side change JSONB to JSON in the legacybuildermedatada function 2016-11-10 18:08:35 +01:00
Mario de Frutos
dac5e76e98 Changed JSONB in legacybuildermetadata function to JSON 2016-11-10 18:07:06 +01:00
Rafa de la Torre
7a32ace1ac Add the hires_geocoder to cdb_monthly_quota #302 2016-11-10 17:00:25 +01:00
Rafa de la Torre
7a56dc698f List of services bound to quota #302 2016-11-10 16:59:58 +01:00
Mario de Frutos
4945b4d0bf Server version 0.18.0 artifact 2016-11-10 16:03:08 +01:00
Mario de Frutos
e6963198dc Client version 0.12.0 artifact 2016-11-10 16:02:58 +01:00
Mario de Frutos
9ae04aaad2 Merge pull request #303 from CartoDB/287_wrapper_dimensional_obs_meta
287 wrapper dimensional obs meta
2016-11-10 16:01:45 +01:00
Mario de Frutos
b392eaf74b removed manual call to here geocoder 2016-11-10 16:00:25 +01:00
Mario de Frutos
040b094b01 New observatory meta functions for server side 2016-11-10 11:29:19 +01:00
Mario de Frutos
a006f76285 New server version 0.18.0 2016-11-10 11:29:18 +01:00
Mario de Frutos
38f2592b22 Client addition of observatory meta functions 2016-11-10 11:29:18 +01:00
Rafa de la Torre
eb7188235d Provider function #302 2016-11-10 11:14:15 +01:00
Rafa de la Torre
3e059003b6 Add soft limit function #302 2016-11-10 11:09:40 +01:00
Mario de Frutos
94099540d7 New version 0.12.0 sql files 2016-11-09 11:21:29 +01:00
Mario de Frutos
b403e1d69a Move old 0.11.1 version to a proper folder 2016-11-09 11:21:29 +01:00
Mario de Frutos
623faf1a22 Added make release option for client 2016-11-09 11:21:28 +01:00
Rafa de la Torre
0e38af6ecd Add cdb_remaining_quota to server #302 2016-11-08 18:47:22 +01:00
Rafa de la Torre
b00edf218a Fix: quotas should be integers #302 2016-11-08 18:46:58 +01:00
Rafa de la Torre
6f9feb07a0 Add cdb_monthly_quota (WIP) #302 2016-11-08 18:29:06 +01:00
Rafa de la Torre
2c76fa4501 Fix: quotas should be integers #302 2016-11-08 18:28:28 +01:00
Rafa de la Torre
4169bc0f88 Fix doc: how to run python unit tests #302 2016-11-08 17:52:18 +01:00
Mario de Frutos
7d9dc554c5 Update README.md 2016-11-07 12:14:05 +01:00
Mario de Frutos
fffb64de36 Update NEWS 2016-11-07 12:09:25 +01:00
Mario de Frutos
6177f0ac76 Remove info trace not needed in metrics 2016-11-07 11:02:09 +01:00
Mario de Frutos
2c49f09aad Merge pull request #301 from CartoDB/development
Release 0.17.0
2016-11-07 10:48:15 +01:00
Mario de Frutos
22fdbd0f4e Added schema option to define in the integration tests 2016-11-07 10:33:15 +01:00
Mario de Frutos
352d4217bc Fixed typo in the config cache for observatory snapshot functions 2016-11-07 10:31:53 +01:00
Mario de Frutos
2fd560f3cf Release 0.17.0 artifact 2016-11-04 13:41:12 +01:00
Mario de Frutos
a4858bbf3c Merge pull request #299 from CartoDB/add_metrics
Data services metrics enhanced
2016-11-04 13:40:31 +01:00
Mario de Frutos
88ed777785 Added plpy_mock and check multiple instances for metricsdatagatherer 2016-11-04 13:39:11 +01:00
Mario de Frutos
6f0db20163 Added here integration test for geocoder street 2016-11-04 13:39:11 +01:00
Mario de Frutos
73aa26590b Make the data gather singleton support multiple instances
Due to we use pgbouncer, we could share the same instance of the metrics
gatherer singleton in multiples requests. Added support to have
multiple instances identified by transaction id
2016-11-04 13:39:11 +01:00
Mario de Frutos
c571edb21e Split response and function data, added uuid and type of element 2016-11-04 13:39:11 +01:00
Mario de Frutos
e878031744 Added url to the response data 2016-11-04 13:39:11 +01:00
Mario de Frutos
49fd51f6da Added logger to metrics context manager 2016-11-04 13:39:10 +01:00
Mario de Frutos
708bee2912 Added metrics context manager to public functions 2016-11-04 13:39:10 +01:00
csobier
6b56c4ad0d Update overview.md 2016-11-03 08:38:12 -04:00
csobier
1f8fb28449 removed the 2016-11-03 08:36:48 -04:00
csobier
7fd13f416d applied some minor edits to overview section 2016-11-03 08:35:03 -04:00
csobier
f41a30316e included edit regarding docs update 1130 2016-11-02 10:37:05 -04:00
Mario de Frutos
cf3c6f2ce5 New metrics logger system
- It's not mandatory to have the log_path defined for all the services
- Now we add metrics to a MetricsGatherer using the add method in order
  to gather data from all the function scope, not just in one defined
  point
- There is a `metrics` context manager to wrap the function block. This
  context manager get the execution time for the block among other
  things
2016-11-02 15:26:39 +01:00
csobier
5499bd1e69 changed default tool from editor to builder 2016-11-02 10:22:42 -04:00
Mario de Frutos
93579532e3 Move old versions 2016-10-28 10:42:25 +02:00
Mario de Frutos
0533018326 Merge pull request #298 from CartoDB/development
Release Python 0.9.4
2016-10-27 16:21:16 +02:00
Mario de Frutos
e380d51bec Merge pull request #296 from CartoDB/add_timeouts_requests
Release python 0.9.4
2016-10-27 16:19:12 +02:00
Mario de Frutos
6058960ec5 Added timeout for all the third-party connections 2016-10-27 16:17:37 +02:00
Mario de Frutos
336d8be977 Hotfix: Typo in status code check 2016-10-26 17:49:07 +02:00
Mario de Frutos
75557837b0 Merge pull request #295 from CartoDB/development
Release python library 0.9.3
2016-10-26 16:58:39 +02:00
Mario de Frutos
e7c35457e1 Merge pull request #294 from CartoDB/293_matrix_without_json
Fix empty response from matrix
2016-10-26 16:41:17 +02:00
Mario de Frutos
80963e2589 504 errors return empty data instead of raise exception
Due to some problems in Mapzen, we're receiving 504 errors from their
servers. To mitigate this problem, instead of raise an exception, we're
going to return empty data for that point
2016-10-26 16:39:35 +02:00
Mario de Frutos
19d6cacdb3 Fix empty response from matrix
https://github.com/CartoDB/dataservices-api/issues/293
2016-10-26 16:00:50 +02:00
129 changed files with 42623 additions and 1033 deletions

11
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,11 @@
Contributing
---
The issue tracker is at [github.com/CartoDB/dataservices-api](https://github.com/CartoDB/dataservices-api).
We love pull requests from everyone, see [Contributing to Open Source on GitHub](https://guides.github.com/activities/contributing-to-open-source/#contributing).
## Submitting Contributions
* You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here](https://carto.com/contributions).

126
NEWS.md
View File

@@ -1,3 +1,53 @@
February 2st, 2017
===================
* Version 0.21.0 of the server and version 0.15.0 of the client
* Added functions `OBS_GetData` and `OBS_GetMeta`
* Default isolines provider changed to `mapzen` instead of `heremaps`
November 29st, 2016
===================
* Version 0.20.0 of the server and version 0.12.0 of the python library
* Added integration with the new Mapzen isochrones functionality
November 25st, 2016
===================
* Version 0.19.0 of the server, version 0.11.0 of the python library and version 0.13.0 of the client
* functions to check the quota, both server and client
* removed the no_params from the templates (this caused trouble, not needed anymore)
* bug fixes: observatory quota, quotas as integers, mapzen geocoder soft limit as bool
November 21st, 2016
===================
* Version 0.18.1 of the server and version 0.12.1 of the client
* Add new fields to the obs_meta_geometry due to new changes introduced in the DO 1.1.2 release
November 11st, 2016
===================
* Version 0.18.0 of the server and version 0.12.0 of the client
* Added obs_legacybuildermetada functions to grab the needed metadata in the builder while making a data enrichment analysis. Closes #286
* Added metadata functions that will be used in the future to gather the metadata for the new data enrichment UI. Closes #287
* Fixed integration test for street geocoding
* Makefile now has a new task to create a new release in the client part, as was in the server, using make release NEW_VERSION=x.x.x
November 7st, 2016
==================
* Version 0.17.0 of the server and version 0.10.0 of the python package
* Added metrics context manager to gather data from different parts of the server functions
* Support multiple response data for one server function call: For example in the one_to_many matrix client
* Metrics files configuration is not mandatory
* All the services covered and gathering metrics
October 27st, 2016
==================
* Version 0.9.4 of the python package
* Added timeouts to all the third-party connections using requests because requests by default doesn't add timeouts.
October 26st, 2016
==================
* Version 0.9.3 of the python package
* Fixes https://github.com/CartoDB/dataservices-api/issues/293
* Mitigate problem with 504 errors coming from Mapzen
October 21st, 2016
==================
* Version 0.9.2 of the python package
@@ -39,7 +89,7 @@ August 11, 2016
===========
* Released server version 0.14.2
* Released client version 0.10.2
* Always default arguments for DO functions to NULL, which prevents duplication & overwrite
* Always default arguments for DO functions to NULL, which prevents duplication & overwrite
August 5, 2016
===========
@@ -95,7 +145,7 @@ July 15, 2016:
* __OBS_ConnectUserTable
This change does not require any client change.
https://github.com/CartoDB/dataservices-api/releases/tag/0.13.1-server
Jul 12, 2016:
@@ -105,14 +155,14 @@ Jul 12, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.13.0-server
Jul 12, 2016:
Jul 12, 2016:
===========
* Release client 0.10.0
* [Client] Add beta augment functions, isoline fixes, observatory dump version
https://github.com/CartoDB/dataservices-api/releases/tag/0.10.0-client
Jul 7, 2016:
Jul 7, 2016:
===========
* Release client 0.9.0
* This release adds two new functions in the Data Services extension client:
@@ -122,7 +172,7 @@ Jul 7, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.9.0-client
Jul 7, 2016:
Jul 7, 2016:
===========
* Release server 0.12.0
* This release adds four new functions in the Data Services extension server:
@@ -134,7 +184,7 @@ Jul 7, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.12.0-server
Jul 5, 2016:
Jul 5, 2016:
===========
* Release server 0.11.0
* Added three new public functions for each geocoding provider:
@@ -147,40 +197,40 @@ Jul 5, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.11.0-server
Jul 5, 2016:
Jul 5, 2016:
===========
* Release client 0.8.0
* Expose providers in high-precision geocoder functions
https://github.com/CartoDB/dataservices-api/releases/tag/0.8.0-client
Jun 15, 2016:
Jun 15, 2016:
===========
* [server python] Write quota info from services with zero padding. Closes issue #204.
https://github.com/CartoDB/dataservices-api/releases/tag/0.10.0-server3
Jun 13, 2016:
Jun 13, 2016:
===========
* [server python] Read quota info from services with and without zero padding. Closes issue #201.
https://github.com/CartoDB/dataservices-api/releases/tag/0.10.0-server2
May 31, 2016:
May 31, 2016:
===========
* Release client 0.7.0
* Adds new function OBS_GetMeasureById
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.0-client
May 31, 2016:
May 31, 2016:
===========
* Release server 0.10.0
* Adds new function OBS_GetMeasureById
https://github.com/CartoDB/dataservices-api/releases/tag/0.10.0-server
May 25, 2016:
May 25, 2016:
===========
* Release server 0.9.0
* Added a new routing function which allows to generate routes from an origin to a destination, which passes through a set of defined locations:
@@ -197,7 +247,7 @@ May 25, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.9.0-server
May 25, 2016:
May 25, 2016:
===========
* Release client 0.6.0
* Includes new client function to obtain a route with waypoints:
@@ -205,7 +255,7 @@ May 25, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.6.0-client
May 18, 2016:
May 18, 2016:
===========
* Release client 0.5.0
* Added new functions for the data observatory:
@@ -228,7 +278,7 @@ May 18, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.5.0-client
May 18, 2016:
May 18, 2016:
===========
* Release server 0.8.0: Data Observatory release
* Added new functions for the data observatory:
@@ -252,28 +302,28 @@ May 18, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.8.0-server
May 10, 2016:
May 10, 2016:
===========
* Release server 0.7.4
* In case we receive a 4xx error from one of the services: isolines, here geocoder, etc we have to return an empty value an increment the empty counter. We have to raise exception in 5xx or unhandled exceptions
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.4-server
May 10, 2016:
May 10, 2016:
===========
* Release server 0.7.3
* Change how the blue/green system is working in the server side. Now the loopback is only in the observatory extension functions call instead in all the dataservices-api function for observatory
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.3-server
May 4, 2016:
May 4, 2016:
===========
* Release server 0.7.2
* Added Blue/Green capability to the data observatory functions in order to be able to use staging or production databases
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.2-server
Apr 25, 2016:
Apr 25, 2016:
===========
* Release server 0.7.1
* Use redis based config if exists, if not use the db config value
@@ -281,7 +331,7 @@ Apr 25, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.1-server
Apr 21, 2016:
Apr 21, 2016:
===========
* Release client 0.4.0
* Remove old versioning system for client side
@@ -291,7 +341,7 @@ Apr 21, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.4.0-client
Apr 21, 2016:
Apr 21, 2016:
===========
* Release server 0.7.0
* Added obs_get_demography_snapshot function
@@ -300,14 +350,14 @@ Apr 21, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.7.0-server
Apr 19, 2016:
Apr 19, 2016:
===========
* Release server 0.6.2
* Add Mapzen routing and geocoder quota check
https://github.com/CartoDB/dataservices-api/releases/tag/0.6.2-server
Apr 14, 2016:
Apr 14, 2016:
===========
* Release server 0.6.1
* Now the implementation knows how to get the iso3 for the passed country in order to pass it to Mapzen
@@ -328,8 +378,8 @@ Mar 28, 2016:
* Integrated Mapzen geocoder for street level geocoding function
https://github.com/CartoDB/dataservices-api/releases/tag/0.6.0-server
Mar 23, 2016:
Mar 23, 2016:
===========
* Release server 0.5.2
* Deleted old versioning system
@@ -338,7 +388,7 @@ Mar 23, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.5.2-server
Mar 17, 2016:
Mar 17, 2016:
===========
* Release server 0.5.1
* Renamed the python library metrics functions
@@ -348,7 +398,7 @@ Mar 17, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.5.1-server
Mar 14, 2016:
Mar 14, 2016:
===========
* Release server 0.5.0
* Mapzen routing functions to calculate a route point to point
@@ -356,28 +406,28 @@ Mar 14, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.5.0-server
Mar 14, 2016:
Mar 14, 2016:
===========
* Release client 0.3.0
* Added cdb_routing_point_to_point function using Mapzen as provider
https://github.com/CartoDB/dataservices-api/releases/tag/0.3.0-client
Feb 26, 2016:
Feb 26, 2016:
===========
* Release client 0.2.0
* Added routing isolines capabilities to the client and public API
https://github.com/CartoDB/dataservices-api/releases/tag/0.2.0-client
Feb 26, 2016:
Feb 26, 2016:
===========
* Release server 0.4.0
* Added routing isolines capabilities
https://github.com/CartoDB/dataservices-api/releases/tag/0.4.0-server
Feb 11, 2016:
Feb 11, 2016:
===========
* Release server 0.3.0
* Extension refactor, now is called cdb_dataservices_[client|server] in order to include more services aside the geocoder.
@@ -386,7 +436,7 @@ Feb 11, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.3.0-server
Feb 4, 2016:
Feb 4, 2016:
===========
* Release server 0.2.0
* Logic for the google geocoder so the users with this geocoder setted up can use street level geocoding too
@@ -394,7 +444,7 @@ Feb 4, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.2.0-server
Jan 25, 2016:
Jan 25, 2016:
===========
* Release Geocoder API 0.1.0
* Street geocoding available through the cdb_geocoder_street_point_v2 function (only working Heremaps geocoder)
@@ -403,27 +453,27 @@ Jan 25, 2016:
https://github.com/CartoDB/dataservices-api/releases/tag/0.1.0
Jan 25, 2016:
Jan 25, 2016:
===========
* Release Geocoder API 0.0.1 production ready
https://github.com/CartoDB/dataservices-api/releases/tag/0.0.1
Dec 23, 2015:
Dec 23, 2015:
===========
* Release Geocoder API 0.0.2 beta
https://github.com/CartoDB/dataservices-api/releases/tag/0.0.2
Dec 3, 2015:
Dec 3, 2015:
===========
* Release Geocoder API 0.0.1 Beta2
https://github.com/CartoDB/dataservices-api/releases/tag/0.0.1-beta2
Nov 27, 2015:
Nov 27, 2015:
===========
* Release Geocoder API BETA 1
* Release Geocoder API BETA 1
* Added the organization public user to the api key check
https://github.com/CartoDB/dataservices-api/releases/tag/0.0.1-beta

3
client/.gitignore vendored
View File

@@ -2,9 +2,10 @@ results/
regression.diffs
regression.out
20_public_functions.sql
25_exception_safe_private_functions.sql
30_plproxy_functions.sql
90_grant_execute.sql
cdb_geocoder_client--0.0.1.sql
cdb_geocoder_client--0.1.0.sql
cdb_geocoder_client--0.2.0.sql
cdb_geocoder_client--0.3.0.sql
cdb_geocoder_client--0.3.0.sql

View File

@@ -4,29 +4,31 @@ EXTENSION = cdb_dataservices_client
EXTVERSION = $(shell grep default_version $(EXTENSION).control | sed -e "s/default_version[[:space:]]*=[[:space:]]*'\([^']*\)'/\1/")
# The new version to be generated from templates
SED = sed
ERB = erb
REPLACEMENTS = -i 's/$(EXTVERSION)/$(NEW_VERSION)/g'
NEW_EXTENSION_ARTIFACT = $(EXTENSION)--$(EXTVERSION).sql
# OLD_VERSIONS = $(wildcard old_versions/*.sql)
# DATA = $(NEW_EXTENSION_ARTIFACT) \
# $(OLD_VERSIONS) \
# cdb_dataservices_client--0.11.0--0.11.1.sql \
# cdb_dataservices_client--0.11.1--0.11.0.sql
OLD_VERSIONS = $(wildcard old_versions/*.sql)
DATA = $(NEW_EXTENSION_ARTIFACT) \
$(EXTENSION)--*--*.sql \
$(OLD_VERSIONS)
SOURCES_DATA_DIR = sql/
REGRESS = $(notdir $(basename $(wildcard test/sql/*test.sql)))
TEST_DIR = test/
REGRESS_OPTS = --inputdir='$(TEST_DIR)' --outputdir='$(TEST_DIR)' --user='postgres'
# DATA is a special variable used by postgres build infrastructure
# These are the files to be installed in the server shared dir,
# for installation from scratch, upgrades and downgrades.
# @see http://www.postgresql.org/docs/current/static/extend-pgxs.html
DATA = $(NEW_EXTENSION_ARTIFACT) \
$(OLD_VERSIONS) \
cdb_dataservices_client--0.11.0--0.11.1.sql \
cdb_dataservices_client--0.11.1--0.11.0.sql
REGRESS = $(notdir $(basename $(wildcard test/sql/*test.sql)))
TEST_DIR = test/
REGRESS_OPTS = --inputdir='$(TEST_DIR)' --outputdir='$(TEST_DIR)'
# postgres build stuff
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
SOURCES_DATA_DIR = sql/
# The interface definition is used along with some templates to automatically generate code
RENDERER = renderer/sql-template-renderer
@@ -35,6 +37,11 @@ TEMPLATE_DIR = renderer/templates
TEMPLATE_FILES = $(wildcard $(TEMPLATE_DIR)/*.erb)
GENERATED_SQL_FILES = $(patsubst $(TEMPLATE_DIR)/%.erb, $(SOURCES_DATA_DIR)/%.sql, $(TEMPLATE_FILES))
# postgres build stuff
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
$(GENERATED_SQL_FILES): $(SOURCES_DATA_DIR)/%.sql: $(TEMPLATE_DIR)/%.erb $(INTERFACE_FILE) $(RENDERER)
$(RENDERER) $(INTERFACE_FILE) $< > $@
@@ -44,9 +51,22 @@ $(NEW_EXTENSION_ARTIFACT): $(SOURCES_DATA)
rm -f $@
cat $(SOURCES_DATA_DIR)/*.sql >> $@
.PHONY: all
all: $(DATA)
.PHONY: release
release: $(EXTENSION).control $(SOURCES_DATA)
test -n "$(NEW_VERSION)" # $$NEW_VERSION VARIABLE MISSING. Eg. make release NEW_VERSION=0.x.0
git mv *.sql old_versions
$(SED) $(REPLACEMENTS) $(EXTENSION).control
git add $(EXTENSION).control
cat $(SOURCES_DATA_DIR)/*.sql > $(EXTENSION)--$(NEW_VERSION).sql
git add $(EXTENSION)--$(NEW_VERSION).sql
$(ERB) version=$(NEW_VERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(EXTVERSION)--$(NEW_VERSION).sql
$(ERB) version=$(EXTVERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(NEW_VERSION)--$(EXTVERSION).sql
# Only meant for development time, do not use once a version is released
.PHONY: devclean
devclean:
rm -f $(NEW_EXTENSION_ARTIFACT)
rm -f $(GENERATED_SQL_FILES)

View File

@@ -0,0 +1,204 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.15.0'" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomvals geomval[] ,params json ,merge boolean DEFAULT true)
RETURNS TABLE(id int, data json) AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomrefs text[] ,params json)
RETURNS TABLE(id text, data json) AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeta (geom_ref Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL)
RETURNS json AS $$
DECLARE
ret json;
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomvals geomval[] ,params json ,merge boolean DEFAULT true)
RETURNS TABLE(id int, data json) AS $$
DECLARE
username text;
orgname text;
_returned_sqlstate TEXT;
_message_text TEXT;
_pg_exception_context TEXT;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
BEGIN
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
END;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
--
-- Exception-safe private DataServices API function
--
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomrefs text[] ,params json)
RETURNS TABLE(id text, data json) AS $$
DECLARE
username text;
orgname text;
_returned_sqlstate TEXT;
_message_text TEXT;
_pg_exception_context TEXT;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
BEGIN
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
END;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
--
-- Exception-safe private DataServices API function
--
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe (geom_ref Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL)
RETURNS json AS $$
DECLARE
ret json;
username text;
orgname text;
_returned_sqlstate TEXT;
_message_text TEXT;
_pg_exception_context TEXT;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
BEGIN
SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret;
RETURN ret;
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
RETURN ret;
END;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, organization_name text, geomvals geomval[], params json, merge boolean DEFAULT true)
RETURNS TABLE(id int, data json) AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getdata (username, organization_name, geomvals, params, merge);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, organization_name text, geomrefs text[], params json)
RETURNS TABLE(id text, data json) AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getdata (username, organization_name, geomrefs, params);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta (username text, organization_name text, geom_ref Geometry(Geometry, 4326), params json, max_timespan_rank integer DEFAULT NULL, max_score_rank integer DEFAULT NULL, target_geoms integer DEFAULT NULL)
RETURNS json AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT cdb_dataservices_server.obs_getmeta (username, organization_name, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms);
$$ LANGUAGE plproxy;

View File

@@ -0,0 +1,17 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.14.1'" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (text, text, geomval[], json, boolean);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (text, text, text[], json);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta (text, text, Geometry(Geometry, 4326), json, integer, integer, integer);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata_exception_safe (geomval[], json, boolean);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata_exception_safe (text[], json);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta_exception_safe (Geometry(Geometry, 4326), json , integer, integer, integer);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getdata (geomval[], json, boolean);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getdata (text[], json);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getmeta (Geometry(Geometry, 4326), json, integer, integer, integer);

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
comment = 'CartoDB dataservices client API extension'
default_version = '0.11.1'
default_version = '0.15.0'
requires = 'plproxy, cartodb'
superuser = true
schema = cdb_dataservices_client

View File

@@ -0,0 +1,172 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.12.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE TYPE cdb_dataservices_client.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean);
CREATE TYPE cdb_dataservices_client.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean);
CREATE TYPE cdb_dataservices_client.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean);
CREATE TYPE cdb_dataservices_client.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablenumerators (bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getavailablenumerators(username, orgname, bounds, filter_tags, denom_id, geom_id, timespan);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabledenominators (bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getavailabledenominators(username, orgname, bounds, filter_tags, numer_id, geom_id, timespan);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailablegeometries (bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getavailablegeometries(username, orgname, bounds, filter_tags, numer_id, denom_id, timespan);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getavailabletimespans (bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_getavailabletimespans(username, orgname, bounds, filter_tags, numer_id, denom_id, geom_id);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_legacybuildermetadata (aggregate_type text DEFAULT NULL)
RETURNS TABLE(name text, subsection json) AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._obs_legacybuildermetadata(username, orgname, aggregate_type);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablenumerators (username text, organization_name text, bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_numerator AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getavailablenumerators (username, organization_name, bounds, filter_tags, denom_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabledenominators (username text, organization_name text, bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, geom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_denominator AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getavailabledenominators (username, organization_name, bounds, filter_tags, numer_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailablegeometries (username text, organization_name text, bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, timespan text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_geometry AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getavailablegeometries (username, organization_name, bounds, filter_tags, numer_id, denom_id, timespan);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getavailabletimespans (username text, organization_name text, bounds geometry(Geometry, 4326) DEFAULT NULL, filter_tags text[] DEFAULT NULL, numer_id text DEFAULT NULL, denom_id text DEFAULT NULL, geom_id text DEFAULT NULL)
RETURNS SETOF cdb_dataservices_client.obs_meta_timespan AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_getavailabletimespans (username, organization_name, bounds, filter_tags, numer_id, denom_id, geom_id);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_legacybuildermetadata (username text, organization_name text, aggregate_type text DEFAULT NULL)
RETURNS TABLE(name text, subsection json) AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_legacybuildermetadata (username, organization_name, aggregate_type);
$$ LANGUAGE plproxy;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablenumerators(bounds geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabledenominators(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailablegeometries(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_getavailabletimespans(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.obs_legacybuildermetadata(aggregate_type text) TO publicuser;

View File

@@ -0,0 +1,21 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.11.1'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getavailablenumerators (geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getavailabledenominators (geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getavailablegeometries (geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getavailabletimespans (geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_legacybuildermetadata(text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablenumerators (text, text, geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabledenominators (text, text, geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablegeometries (text, text, geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabletimespans (text, text, geometry(Geometry, 4326), text[], text, text, text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_legacybuildermetadata(text, text, text);
DROP TYPE IF EXISTS cdb_dataservices_client.obs_meta_numerator;
DROP TYPE IF EXISTS cdb_dataservices_client.obs_meta_denominator;
DROP TYPE IF EXISTS cdb_dataservices_client.obs_meta_geometry;
DROP TYPE IF EXISTS cdb_dataservices_client.obs_meta_timespan;

View File

@@ -0,0 +1,12 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.12.1'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE score numeric;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE numtiles bigint;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE notnull_percent numeric;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE numgeoms numeric;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE percentfill numeric;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE estnumgeoms numeric;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry ADD ATTRIBUTE meanmediansize numeric;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.12.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE score;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE numtiles;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE notnull_percent;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE numgeoms;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE percentfill;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE estnumgeoms;
ALTER TYPE cdb_dataservices_client.obs_meta_geometry DROP ATTRIBUTE meanmediansize;

View File

@@ -0,0 +1,115 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.13.0'" to load this file. \quit
-- Added for consistency (SELECT func instead of SELECT * FROM)
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_dumpversion ()
RETURNS text AS $$
DECLARE
ret text;
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
SELECT cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion (username text, organization_name text)
RETURNS text AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT cdb_dataservices_server.obs_dumpversion (username, organization_name);
$$ LANGUAGE plproxy;
-- For quotas and services configuration
CREATE TYPE cdb_dataservices_client.service_type AS ENUM (
'isolines',
'hires_geocoder',
'routing',
'observatory'
);
CREATE TYPE cdb_dataservices_client.service_quota_info AS (
service cdb_dataservices_client.service_type,
monthly_quota NUMERIC,
used_quota NUMERIC,
soft_limit BOOLEAN,
provider TEXT
);
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info ()
RETURNS SETOF service_quota_info AS $$
DECLARE
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
RETURN QUERY
SELECT * FROM cdb_dataservices_client._cdb_service_quota_info(username, orgname);
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
RETURNS BOOLEAN AS $$
DECLARE
ret BOOLEAN;
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
SELECT cdb_dataservices_client._cdb_enough_quota(username, orgname, service, input_size) INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info (username text, organization_name text)
RETURNS SETOF service_quota_info AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.cdb_service_quota_info (username, organization_name);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_enough_quota (username text, organization_name text, service TEXT, input_size NUMERIC)
RETURNS BOOLEAN AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT cdb_dataservices_server.cdb_enough_quota (username, organization_name, service, input_size);
$$ LANGUAGE plproxy;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info() TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_enough_quota(service TEXT, input_size NUMERIC) TO publicuser;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.12.1'" to load this file. \quit
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_dumpversion ()
RETURNS text AS $$
DECLARE
ret text;
username text;
orgname text;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
SELECT * FROM cdb_dataservices_client._obs_dumpversion(username, orgname) INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_dumpversion (username text, organization_name text)
RETURNS text AS $$
CONNECT cdb_dataservices_client._server_conn_str();
SELECT * FROM cdb_dataservices_server.obs_dumpversion (username, organization_name);
$$ LANGUAGE plproxy;
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_enough_quota (username text, organization_name text, service TEXT, input_size NUMERIC);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info (username text, organization_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_service_quota_info ();
DROP TYPE IF EXISTS cdb_dataservices_client.service_quota_info;
DROP TYPE IF EXISTS cdb_dataservices_client.service_type;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.13.0'" to load this file. \quit
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin0_polygon_exception_safe(country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe(admin1_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_admin1_polygon_exception_safe(admin1_name text, country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe(city_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe(city_name text, country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_namedplace_point_exception_safe(city_name text, admin1_name text, country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_polygon_exception_safe(postal_code text, country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_postalcode_point_exception_safe(postal_code text, country_name text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_ipaddress_point_exception_safe(ip_address text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_here_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_google_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapzen_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_point_to_point_exception_safe(origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[], units text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_with_waypoints_exception_safe(waypoints geometry(Point, 4326)[], mode text, options text[], units text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_demographic_snapshot_exception_safe(geom geometry(Geometry, 4326), time_span text, geometry_level text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_get_segment_snapshot_exception_safe(geom geometry(Geometry, 4326), geometry_level text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdemographicsnapshot_exception_safe(geom geometry(Geometry, 4326), time_span text, geometry_level text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getsegmentsnapshot_exception_safe(geom geometry(Geometry, 4326), geometry_level text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundary_exception_safe(geom geometry(Geometry, 4326), boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundaryid_exception_safe(geom geometry(Geometry, 4326), boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundarybyid_exception_safe(geometry_id text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbygeometry_exception_safe(geom geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getboundariesbypointandradius_exception_safe(geom geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbygeometry_exception_safe(geom geometry(Geometry, 4326), boundary_id text, time_span text, overlap_type text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpointsbypointandradius_exception_safe(geom geometry(Geometry, 4326), radius numeric, boundary_id text, time_span text, overlap_type text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasure_exception_safe(geom Geometry, measure_id text, normalize text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeasurebyid_exception_safe(geom_ref text, measure_id text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getcategory_exception_safe(geom Geometry, category_id text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensusmeasure_exception_safe(geom Geometry, name text, normalize text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getuscensuscategory_exception_safe(geom Geometry, name text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getpopulation_exception_safe(geom Geometry, normalize text, boundary_id text, time_span text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_search_exception_safe(search_term text, relevant_boundary text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailableboundaries_exception_safe(geom Geometry, timespan text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_dumpversion_exception_safe();
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablenumerators_exception_safe(bounds geometry(Geometry, 4326), filter_tags text[], denom_id text, geom_id text, timespan text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabledenominators_exception_safe(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, geom_id text, timespan text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailablegeometries_exception_safe(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, timespan text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getavailabletimespans_exception_safe(bounds geometry(Geometry, 4326), filter_tags text[], numer_id text, denom_id text, geom_id text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_legacybuildermetadata_exception_safe(aggregate_type text);
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_exception_safe();
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_enough_quota_exception_safe(service TEXT, input_size NUMERIC);

View File

@@ -0,0 +1,9 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.14.1'" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
-- This release introduces no changes other than the use of
-- search path in the install and migration scripts

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.14.0'" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
-- This release introduces no changes other than the use of
-- search path in the install and migration scripts

File diff suppressed because it is too large Load Diff

View File

@@ -261,6 +261,38 @@
- { name: boundary_id, type: text}
- { name: time_span, type: text, default: 'NULL'}
- name: obs_getdata
return_type: TABLE(id int, data json)
multi_row: true
multi_field: true
table_fields:
- { name: id, type: integer }
- { name: data, type: json }
params:
- { name: geomvals, type: "geomval[]" }
- { name: params, type: json }
- { name: merge, type: boolean, default: true }
- name: obs_getdata
return_type: TABLE(id text, data json)
multi_row: true
multi_field: true
table_fields:
- { name: id, type: text }
- { name: data, type: json }
params:
- { name: geomrefs, type: "text[]" }
- { name: params, type: json }
- name: obs_getmeta
return_type: json
params:
- { name: geom_ref, type: "Geometry(Geometry, 4326)" }
- { name: params, type: json }
- { name: max_timespan_rank, type: integer, default: 'NULL' }
- { name: max_score_rank, type: integer, default: 'NULL' }
- { name: target_geoms, type: integer, default: 'NULL' }
- name: obs_getcategory
return_type: text
params:
@@ -323,6 +355,69 @@
- name: obs_dumpversion
return_type: text
no_params: true
params:
- {}
- name: obs_getavailablenumerators
return_type: SETOF cdb_dataservices_client.obs_meta_numerator
multi_row: true
multi_field: true
params:
- { name: bounds, type: "geometry(Geometry, 4326)", default: 'NULL' }
- { name: filter_tags, type: "text[]", default: 'NULL' }
- { name: denom_id, type: text, default: 'NULL' }
- { name: geom_id, type: text, default: 'NULL' }
- { name: timespan, type: text, default: 'NULL'}
- name: obs_getavailabledenominators
return_type: SETOF cdb_dataservices_client.obs_meta_denominator
multi_row: true
multi_field: true
params:
- { name: bounds, type: "geometry(Geometry, 4326)", default: 'NULL' }
- { name: filter_tags, type: "text[]", default: 'NULL' }
- { name: numer_id, type: text, default: 'NULL' }
- { name: geom_id, type: text, default: 'NULL' }
- { name: timespan, type: text, default: 'NULL'}
- name: obs_getavailablegeometries
return_type: SETOF cdb_dataservices_client.obs_meta_geometry
multi_row: true
multi_field: true
params:
- { name: bounds, type: "geometry(Geometry, 4326)", default: 'NULL' }
- { name: filter_tags, type: "text[]", default: 'NULL' }
- { name: numer_id, type: text, default: 'NULL' }
- { name: denom_id, type: text, default: 'NULL' }
- { name: timespan, type: text, default: 'NULL'}
- name: obs_getavailabletimespans
return_type: SETOF cdb_dataservices_client.obs_meta_timespan
multi_row: true
multi_field: true
params:
- { name: bounds, type: "geometry(Geometry, 4326)", default: 'NULL' }
- { name: filter_tags, type: "text[]", default: 'NULL' }
- { name: numer_id, type: text, default: 'NULL' }
- { name: denom_id, type: text, default: 'NULL' }
- { name: geom_id, type: text, default: 'NULL'}
- name: obs_legacybuildermetadata
return_type: TABLE(name text, subsection json)
multi_row: true
multi_field: true
params:
- { name: aggregate_type, type: text, default: 'NULL' }
- name: cdb_service_quota_info
return_type: SETOF service_quota_info
multi_row: true
multi_field: true
params:
- {}
- name: cdb_enough_quota
return_type: BOOLEAN
params:
- { name: service, type: TEXT }
- { name: input_size, type: NUMERIC }

View File

@@ -36,10 +36,6 @@ class SqlTemplateRenderer
@function_signature['multi_row']
end
def no_params
@function_signature['no_params']
end
def user_config_key
@function_signature['user_config_key']
end
@@ -49,11 +45,11 @@ class SqlTemplateRenderer
end
def params
@function_signature['params'].reject(&:empty?).map { |p| "#{p['name']}"}.join(', ')
@function_signature['params'].reject(&:empty?).map { |p| "#{p['name']}"}
end
def params_with_type
@function_signature['params'].reject(&:empty?).map { |p| "#{p['name']} #{p['type']}" }.join(', ')
@function_signature['params'].reject(&:empty?).map { |p| "#{p['name']} #{p['type']}" }
end
def params_with_type_and_default
@@ -64,7 +60,7 @@ class SqlTemplateRenderer
"#{p['name']} #{p['type']}"
end
end
return parameters.join(', ')
return parameters
end
end

View File

@@ -4,7 +4,7 @@
-- These are the only ones with permissions to publicuser role
-- and should also be the only ones with SECURITY DEFINER
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %> (<%= params_with_type_and_default %>)
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %> (<%= params_with_type_and_default.join(' ,') %>)
RETURNS <%= return_type %> AS $$
DECLARE
<% if not multi_row %>ret <%= return_type %>;<% end %>
@@ -21,15 +21,12 @@ BEGIN
END IF;
<% if multi_row %>
RETURN QUERY
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>);
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>);
<% elsif multi_field %>
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
RETURN ret;
<% elsif no_params %>
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname) INTO ret;
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
RETURN ret;
<% else %>
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
RETURN ret;
<% end %>
END;

View File

@@ -0,0 +1,61 @@
--
-- Exception-safe private DataServices API function
--
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>_exception_safe (<%= params_with_type_and_default.join(' ,') %>)
RETURNS <%= return_type %> AS $$
DECLARE
<% if not multi_row %>ret <%= return_type %>;<% end %>
username text;
orgname text;
_returned_sqlstate TEXT;
_message_text TEXT;
_pg_exception_context TEXT;
BEGIN
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
RAISE EXCEPTION 'The api_key must be provided';
END IF;
SELECT u, o INTO username, orgname FROM <%= DATASERVICES_CLIENT_SCHEMA %>._cdb_entity_config() AS (u text, o text);
-- JSON value stored "" is taken as literal
IF username IS NULL OR username = '' OR username = '""' THEN
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
END IF;
<% if multi_row %>
BEGIN
RETURN QUERY
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
END;
<% elsif multi_field %>
BEGIN
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
RETURN ret;
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
RETURN ret;
END;
<% else %>
BEGIN
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
RETURN ret;
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
_message_text = MESSAGE_TEXT,
_pg_exception_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
RETURN ret;
END;
<% end %>
END;
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;

View File

@@ -1,15 +1,9 @@
<% if no_params %>
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (username text, organization_name text)
<% else %>
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (username text, organization_name text, <%= params_with_type_and_default %>)
<% end %>
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (<%= ['username text', 'organization_name text'].concat(params_with_type_and_default).join(', ') %>)
RETURNS <%= return_type %> AS $$
CONNECT <%= DATASERVICES_CLIENT_SCHEMA %>._server_conn_str();
<% if multi_field %>
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
<% elsif no_params %>
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name);
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= ['username', 'organization_name'].concat(params).join(', ') %>);
<% else %>
SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= ['username', 'organization_name'].concat(params).join(', ') %>);
<% end %>
$$ LANGUAGE plproxy;

View File

@@ -1 +1,2 @@
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %>(<%= params_with_type %>) TO publicuser;
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %>(<%= params_with_type.join(', ') %>) TO publicuser;
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>_exception_safe(<%= params_with_type.join(', ') %>) TO publicuser;

View File

@@ -1,3 +1,6 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION cdb_dataservices_client" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;

View File

@@ -8,4 +8,30 @@ CREATE TYPE cdb_dataservices_client.simple_route AS (
shape geometry(LineString,4326),
length real,
duration integer
);
);
-- For the OBS_Meta functions
CREATE TYPE cdb_dataservices_client.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean);
CREATE TYPE cdb_dataservices_client.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean);
CREATE TYPE cdb_dataservices_client.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric);
CREATE TYPE cdb_dataservices_client.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean);
-- For quotas and services configuration
CREATE TYPE cdb_dataservices_client.service_type AS ENUM (
'isolines',
'hires_geocoder',
'routing',
'observatory'
);
CREATE TYPE cdb_dataservices_client.service_quota_info AS (
service cdb_dataservices_client.service_type,
monthly_quota NUMERIC,
used_quota NUMERIC,
soft_limit BOOLEAN,
provider TEXT
);

View File

@@ -0,0 +1,56 @@
SET client_min_messages TO warning;
SET search_path TO public,cartodb,cdb_dataservices_client;
-- Mock the server functions to raise exceptions
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
RETURNS Geometry AS $$
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username text, orgname text, source geometry, mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
RETURNS SETOF isoline AS $$
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
RETURNS cdb_dataservices_client.simple_route AS $$
DECLARE
ret cdb_dataservices_client.simple_route;
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
-- This code shall never be reached
SELECT NULL, 5.33, 100 INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql';
-- Use regular user role
SET ROLE test_regular_user;
-- Exercise the exception safe and the proxied functions
SELECT _cdb_geocode_street_point_exception_safe('One street, 1');
WARNING: cdb_dataservices_client._cdb_geocode_street_point(6): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
DETAIL: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country)"
PL/pgSQL function _cdb_geocode_street_point_exception_safe(text,text,text,text) line 21 at SQL statement
_cdb_geocode_street_point_exception_safe
------------------------------------------
(1 row)
SELECT * FROM _cdb_isodistance_exception_safe('POINT(-3.70568 40.42028)'::geometry, 'walk', ARRAY[300]::integer[]);
WARNING: cdb_dataservices_client._cdb_isodistance(6): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
DETAIL: PL/pgSQL function _cdb_isodistance_exception_safe(geometry,text,integer[],text[]) line 21 at RETURN QUERY
center | data_range | the_geom
--------+------------+----------
(0 rows)
SELECT * FROM _cdb_route_point_to_point_exception_safe('POINT(-3.70237112 40.41706163)'::geometry,'POINT(-3.69909883 40.41236875)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);
WARNING: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
DETAIL: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
PL/pgSQL function _cdb_route_point_to_point_exception_safe(geometry,geometry,text,text[],text) line 21 at SQL statement
shape | length | duration
-------+--------+----------
| |
(1 row)

View File

@@ -173,6 +173,27 @@ BEGIN
RETURN QUERY SELECT '0106000020E61000000100000001030000000100000019000000DD96C805677C52C0CBD8D0CDFE5A44407A19C5724B7C52C033BF9A03045B4440FF59F3E32F7C52C0CB290131095B4440247EC51A2E7C52C0548B8862F25A44401FF5D72B2C7C52C0CB811E6ADB5A444049F086342A7C52C09CC3B5DAC35A444044679945287C52C01F680586AC5A444012D90759167C52C09430D3F6AF5A44405698BED7107C52C04759BF99985A4440DEE522BE137C52C00664AF777F5A4440F92EA52E197C52C09BA73AE4665A4440C558A65F227C52C0D80DDB16655A4440373465A71F7C52C065A71FD4455A44404AED45B41D7C52C0785DBF60375A444083A3E4D5397C52C09946938B315A4440F2B4FCC0557C52C01FF5D72B2C5A444026C286A7577C52C02BDD5D67435A44405BCF108E597C52C0C651B9895A5A444030D461855B7C52C0D1393FC5715A444065E1EB6B5D7C52C078280AF4895A44403AE63C635F7C52C07D1F0E12A25A44403F6F2A52617C52C05983F755B95A44405C3AE63C637C52C04852D2C3D05A444049810530657C52C0FAEE5696E85A4440DD96C805677C52C0CBD8D0CDFE5A4440'::geometry as the_geom, '36047049300'::text as geom_refs;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getmeta(username text, orgname text, geom geometry(Geometry, 4326), params JSON, max_timespan_rank INTEGER DEFAULT NULL, max_score_rank INTEGER DEFAULT NULL, target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getmeta invoked with params (%, %, %, %, %, %, %)', username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms;
RETURN '[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]'::JSON;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomrefs text[], params json)
RETURNS TABLE (id TEXT, data JSON) AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %)', username, orgname, geomrefs, params;
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomvals geomval[], params json, merge boolean default true)
RETURNS TABLE (id TEXT, data JSON) AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %, %)', username, orgname, geomvals, params, merge;
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
END;
$$ LANGUAGE 'plpgsql';
-- Exercise the public and the proxied function
SELECT obs_get_demographic_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '2009 - 2013'::text, '"us.census.tiger".block_group'::text);
NOTICE: cdb_dataservices_client._obs_get_demographic_snapshot(5): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_get_demographic_snapshot invoked with params (test_user, <NULL>, 0101000020E6100000548B8862F27B52C0DDD1FF722D5A4440, 2009 - 2013, "us.census.tiger".block_group)
@@ -337,3 +358,34 @@ CONTEXT: PL/pgSQL function obs_getavailableboundaries(geometry,text) line 16 at
(us.census.tiger.place,"Incorporated places are those reported to the Census Bureau as legally in existence as of January 1, 2010, as reported in the latest Boundary and Annexation Survey (BAS), under the laws of their respective states.",2014,obs_7c9493c41fa8f4bd178ab993ea3d5891c1977667)
(1 row)
SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]', 1, 1, 1000);
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001"}], 1, 1, 1000)
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
obs_getmeta
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]
(1 row)
SELECT obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}]', 1, 1, 1000));
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}], 1, 1, 1000)
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
NOTICE: cdb_dataservices_client._obs_getdata(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getdata invoked with params (test_user, <NULL>, {36047}, [{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}])
CONTEXT: PL/pgSQL function obs_getdata(text[],json) line 16 at RETURN QUERY
obs_getdata
--------------------------------------------
(36047,"[{""value"" : 10349.1547875017}]")
(1 row)
SELECT obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]'));
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001"}], <NULL>, <NULL>, <NULL>)
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
NOTICE: cdb_dataservices_client._obs_getdata(5): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getdata invoked with params (test_user, <NULL>, {"(0101000020E61000009A999999997952C09A99999999594440,1)"}, [{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}], t)
CONTEXT: PL/pgSQL function obs_getdata(geomval[],json,boolean) line 16 at RETURN QUERY
obs_getdata
--------------------------------------------
(36047,"[{""value"" : 10349.1547875017}]")
(1 row)

View File

@@ -0,0 +1,41 @@
SET client_min_messages TO warning;
SET search_path TO public,cartodb,cdb_dataservices_client;
-- Mock the server functions to raise exceptions
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
RETURNS Geometry AS $$
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username text, orgname text, source geometry, mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
RETURNS SETOF isoline AS $$
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
RETURNS cdb_dataservices_client.simple_route AS $$
DECLARE
ret cdb_dataservices_client.simple_route;
BEGIN
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
-- This code shall never be reached
SELECT NULL, 5.33, 100 INTO ret;
RETURN ret;
END;
$$ LANGUAGE 'plpgsql';
-- Use regular user role
SET ROLE test_regular_user;
-- Exercise the exception safe and the proxied functions
SELECT _cdb_geocode_street_point_exception_safe('One street, 1');
SELECT * FROM _cdb_isodistance_exception_safe('POINT(-3.70568 40.42028)'::geometry, 'walk', ARRAY[300]::integer[]);
SELECT * FROM _cdb_route_point_to_point_exception_safe('POINT(-3.70237112 40.41706163)'::geometry,'POINT(-3.69909883 40.41236875)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);

View File

@@ -194,6 +194,30 @@ BEGIN
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getmeta(username text, orgname text, geom geometry(Geometry, 4326), params JSON, max_timespan_rank INTEGER DEFAULT NULL, max_score_rank INTEGER DEFAULT NULL, target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getmeta invoked with params (%, %, %, %, %, %, %)', username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms;
RETURN '[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]'::JSON;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomrefs text[], params json)
RETURNS TABLE (id TEXT, data JSON) AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %)', username, orgname, geomrefs, params;
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomvals geomval[], params json, merge boolean default true)
RETURNS TABLE (id TEXT, data JSON) AS $$
BEGIN
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %, %)', username, orgname, geomvals, params, merge;
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
END;
$$ LANGUAGE 'plpgsql';
-- Exercise the public and the proxied function
SELECT obs_get_demographic_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '2009 - 2013'::text, '"us.census.tiger".block_group'::text);
SELECT obs_get_segment_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '"us.census.tiger".block_group'::text);
@@ -214,3 +238,7 @@ SELECT obs_getuscensuscategory(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326
SELECT obs_getpopulation(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326));
SELECT obs_search('total_pop'::text);
SELECT obs_getavailableboundaries(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326));
SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]', 1, 1, 1000);
SELECT obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}]', 1, 1, 1000));
SELECT obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]'));

View File

@@ -0,0 +1,8 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '<%= version %>'" to load this file. \quit
-- Make sure we have a sane search path to create/update the extension
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
-- HERE goes your code to upgrade/downgrade

View File

@@ -215,7 +215,7 @@ INSERT INTO {tablename} (the_geom) SELECT cdb_geocode_namedplace_point('New York
## Postal Code Geocoder
This function geocodes your data into point, or polygon, geometries for postal codes. The postal code polygon geocoder covers the United States, France, Australia and Canada; a request for a different country will return an empty response.
These functions geocode your data into point, or polygon, geometries for postal codes. The postal code geocoder covers the United States, France, Australia and Canada; a request for a different country will return an empty response.
**Note:** For the USA, US Census [Zip Code Tabulation Areas](https://www.census.gov/geo/reference/zctas.html) (ZCTA) are used to reference geocodes for USPS postal codes service areas. See the [FAQs](https://carto.com/docs/faqs/datasets-and-data/#why-does-carto-use-census-bureau-zctas-and-not-usps-zip-codes-for-postal-codes) about datasets and data for details.

View File

@@ -0,0 +1,36 @@
# Exception-Safe functions
The public API dataservices functions emit exceptions in general when an error occurs
or a limiting condition is met (e.g. quotas are exceeded).
For each public function `func` we have a internal function named `_func_exception_safe` which
acts as a wrapper to the public function, with the same signature, but captures
exceptions generated during its execution (except those due to incomplete configuration or
authentication issues) and returns NULL or empty set values in those cases.
Please note these functions are considered **not public** and therefore their API (including which exceptions are wrapped and which ones are not) may change.
Instead of raising an exception they raise warnings, hopefully containing the same information of the original exception.
## Intended Use
These functions are useful in cases when it is undesirable to rollback a transaction.
Fo example if a table is geocoded with:
```sql
UPDATE table SET the_geom=cdb_geocode_street_point(user,NULL,address,city,NULL,country);
```
In case of the user geocoding quota being exhausted mid-process, the user could
incur in external service expenses but any geocoded data would be lost due to the
transaction rollback.
We can avoid the problem using the corresponding exception-safe function:
```sql
UPDATE table SET the_geom=_cdb_geocode_street_point_exception_safe(user,NULL,address,city,NULL,country);
```
# Addition Information
See https://github.com/CartoDB/dataservices-api/issues/314 for more information.

View File

@@ -10,7 +10,7 @@ _The Data Services API is collaborating with [Mapzen](https://mapzen.com/), and
By using the SQL API to query the Data Services API functions, you can manage specific operations and the corresponding geometries (a `polygon` or a `point`), according to the input information.
The Data Services API decouples the geocoding and isoline services from the CARTO Editor. The API allows you to geocode data (from single rows, complete datasets, or simple inputs) and to perform trade areas analysis (computing isodistances or isochrones) programatically, through authenticated requests.
The Data Services API also exposes its services directly through CARTO Builder. For example, you can geocode data (from single rows, complete datasets, or simple inputs) and perform trade areas analysis (computing isodistances or isochrones) programatically, through authenticated SQL requests, or by using the ANALYSIS options.
The geometries provided by this API are projected in the projection [WGS 84 SRID 4326](http://spatialreference.org/ref/epsg/wgs-84/).

View File

@@ -12,3 +12,124 @@ Quota consumption is calculated based on the number of request made for each fun
**Note:** Queries to the Data Services API, and any of its functions in your maps, may be forbidden in the future
* It is advised to store results of these queries into your datasets, and refresh them as needed. This ensure more control of quota credits for your account
## Quota Information Functions
There are several SQL functions that you can run to obtain quota information about your services.
## cdb_service_quota_info()
Returns information about per-service quotas (available and used) for the account.
#### Returns
This function returns a set of service quota information records, one per service.
Name | Type | Description
--------------- | --------- | ------------
`service` | `text` | Type of service.
`monthly_quota` | `numeric` | Quota available to the user (number of calls) per monthly period.
`used_quota` | `numeric` | Quota used by the user in the present period.
`soft_limit` | `boolean` | Set to `True`, if the user has *soft-limit* quota.
`provider` | `text` | Service provider for this type of service.
Service Types:
* `'isolines'` [Isoline/Isochrones (isochrone/isodistance lines) service](https://carto.com/docs/carto-engine/dataservices-api/isoline_functions/)
* `'hires_geocoder'` [Street level geocoding](https://carto.com/docs/carto-engine/dataservices-api/geocoding-functions#street-level-geocoder)
* `'routing'` [Routing functions](https://carto.com/docs/carto-engine/dataservices-api/routing_functions/)
* `'observatory'` Data Observatory services ([demographic](https://carto.com/docs/carto-engine/dataservices-api/demographic_functions/) and [segmentation](https://carto.com/docs/carto-engine/dataservices-api/segmentation_functions/) functions)
**Notes**
Users who have *soft-quota* activated never run out of quota, but they may incur extra
expenses when the regular quota is exceeded.
A zero value of `monthly_quota` indicates that the service has not been activated for the user.
#### Example
```sql
SELECT * FROM cdb_service_quota_info();
```
Result:
```sql
service | monthly_quota | used_quota | soft_limit | provider
----------------+---------------+------------+------------+------------------
isolines | 100 | 0 | f | mapzen
hires_geocoder | 100 | 0 | f | mapzen
routing | 50 | 0 | f | mapzen
observatory | 0 | 0 | f | data observatory
(4 rows)
```
In this case, notice that the user has no access to the observatory services. All quotas are *hard-limited* (no soft limits), and no quota has been used in the present period.
## cdb_enough_quota(service text ,input_size numeric)
This function is useful to check if enough quota is available for completing a job.
This is specifically relevant if a number of service calls are to be performed inside a transaction. If any of the calls fails (due to exceeded quota), the transaction will be rolled back; resulting in partial quota consumption, but no saved results from the services consumed.
**Tip:** If you are requesting repeating quota-consuming functions (e.g. to geocode a whole table), it is extremely important to check if enough quota is available to complete the job _before_ applying this function.
Note that some services consume more than one credit per row/call. For example, isolines (with more than one range/track) consume (N rows x M ranges) credits; indicating that the input size should be N x M.
#### Arguments
Name | Type | Description
------------ | --------- | -----------
`service` | `text` | Service to check; see the list of valid services above.
`input_size` | `numeric` | Number of service calls required, i.e. size of the input to be processed.
#### Returns
The result is a *boolean* value. A *true* value (`'t'`) indicates that the available quota
for the service is enough for the input size requested. A *false* value (`'f'`) indicates
insufficient quota.
#### Example
Suppose you want to geocode a whole table. In order to check that you have enough quota, and avoid a "quota exhausted" exception, first find out how many records you need to geocode:
```sql
SELECT COUNT(*) FROM {tablename} WHERE {street_name_column} IS NOT NULL;
```
Result: here's a sample result of 10000 records:
```sql
count
-------
10000
(1 row)
```
The result shows how much quota is needed to complete this job. In this case,
each call to `cdb_geocode_street_point` consumes one quota credit. This indicates that we need one credit per row to geocode the whole table.
```sql
SELECT cdb_enough_quota('hires_geocoder', {number_of_records});
```
The result is similar to the following:
```sql
cdb_enough_quota
------------------
t
```
If the result of this query is *true* (`'t'`), you can safely proceed. If a *false* value (`'f'`) is returned, you should avoid processing any more requests that consume quota. Apply the `cdb_service_quota_info` function to get more information about your services.
**Note:** Remember to apply any filtering conditions that you used to count the records (in this case, `{street_name_column} IS NOT NULL`):
```sql
UPDATE {tablename} SET the_geom = cdb_geocode_street_point({street_name_column})
WHERE {street_name_column} IS NOT NULL;
```

View File

@@ -12,7 +12,7 @@ Name | Type | Description | Accepted values
--- | --- | --- | ---
`origin` | `geometry(Point)` | Origin point, in 4326 projection, which defines the start location. |
`destination` | `geometry(Point)` | Destination point, in 4326 projection, which defines the end location. |
`mode` | `text` | Type of transport used to calculate the isolines. | `car`, `walk`, `bicycle` or `public_transport`
`mode` | `text` | Type of transport used to calculate the routes. | `car`, `walk`, `bicycle` or `public_transport`
`options` | `text[]` | (Optional) Multiple options to add more capabilities to the analysis. See [Optional routing parameters](#optional-routing-parameters) for details.
`units` | `text` | Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`
@@ -47,7 +47,7 @@ Returns a route that goes from origin to destination and whose path travels thro
Name | Type | Description | Accepted values
--- | --- | --- | ---
`waypoints` | `geometry(Point)[]` | Array of ordered points, in 4326 projection, which defines the origin point, one or more locations for the route path to travel through, and the destination. The first element of the array defines the origin and the last element the destination of the route. |
`mode` | `text` | Type of transport used to calculate the isolines. | `car`, `walk`, `bicycle` or `public_transport`
`mode` | `text` | Type of transport used to calculate the routes. | `car`, `walk`, `bicycle` or `public_transport`
`options` | `text[]` | (Optional) Multiple options to add more capabilities to the analysis. See [Optional routing parameters](#optional-routing-parameters) for details.
`units` | `text` | Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`

View File

@@ -0,0 +1,174 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.21.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
username TEXT,
orgname TEXT,
geomvals geomval[],
params JSON,
merge BOOLEAN DEFAULT True)
RETURNS TABLE (
id INT,
data JSON
) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
username TEXT,
orgname TEXT,
geomvals geomval[],
params JSON,
merge BOOLEAN DEFAULT True)
RETURNS TABLE (
id INT,
data JSON
) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
with metrics('obs_getdata', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"])
result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge])
empty_results = len(geomvals) - len(result)
if empty_results > 0:
quota_service.increment_empty_service_use(empty_results)
if result:
quota_service.increment_success_service_use(len(result))
return result
else:
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use(len(geomvals))
logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetData')
finally:
quota_service.increment_total_service_use(len(geomvals))
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
username TEXT,
orgname TEXT,
geomrefs TEXT[],
params JSON)
RETURNS TABLE (
id TEXT,
data JSON
) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
username TEXT,
orgname TEXT,
geomrefs TEXT[],
params JSON)
RETURNS TABLE (
id TEXT,
data JSON
) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
with metrics('obs_getdata', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"])
result = plpy.execute(obs_plan, [username, orgname, geomrefs, params])
empty_results = len(geomrefs) - len(result)
if empty_results > 0:
quota_service.increment_empty_service_use(empty_results)
if result:
quota_service.increment_success_service_use(len(result))
return result
else:
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use(len(geomrefs))
exc_info = sys.exc_info()
logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2]))
logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetData')
finally:
quota_service.increment_total_service_use(len(geomrefs))
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta(
username TEXT,
orgname TEXT,
geom Geometry(Geometry, 4326),
params JSON,
max_timespan_rank INTEGER DEFAULT NULL,
max_score_rank INTEGER DEFAULT NULL,
target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta(
username TEXT,
orgname TEXT,
geom Geometry(Geometry, 4326),
params JSON,
max_timespan_rank INTEGER DEFAULT NULL,
max_score_rank INTEGER DEFAULT NULL,
target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
with metrics('obs_getmeta', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"])
result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms])
if result:
return result[0]['meta']
else:
return None
except BaseException as e:
import sys
logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeta')
$$ LANGUAGE plpythonu;

View File

@@ -0,0 +1,11 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.20.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetData(TEXT, TEXT, geomval[], JSON, BOOLEAN);
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetData(TEXT, TEXT, geomval[], JSON, BOOLEAN);
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetData(TEXT, TEXT, TEXT[], JSON);
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetData(TEXT, TEXT, TEXT[], JSON);
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetMeta(TEXT, TEXT, Geometry(Geometry, 4326), JSON, INTEGER, INTEGER, INTEGER);
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetMeta(TEXT, TEXT, Geometry(Geometry, 4326), JSON, INTEGER, INTEGER, INTEGER);

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
comment = 'CartoDB dataservices server extension'
default_version = '0.16.0'
default_version = '0.21.0'
requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
superuser = true
schema = cdb_dataservices_server

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.18.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE TYPE cdb_dataservices_server.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableNumerators(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableNumerators(bounds, filter_tags, denom_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableDenominators(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_denominator AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableDenominators(bounds, filter_tags, numer_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableGeometries(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_geometry AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableGeometries(bounds, filter_tags, numer_id, denom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableTimespans(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_timespan AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableTimespans(bounds, filter_tags, numer_id, denom_id, geom_id);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_LegacyBuilderMetadata(
username TEXT,
orgname TEXT,
aggregate_type TEXT DEFAULT NULL)
RETURNS TABLE(name TEXT, subsection JSON) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_LegacyBuilderMetadata(aggregate_type);
$$ LANGUAGE plproxy;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.17.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_server.obs_getavailablenumerators(TEXT, TEXT, geometry(Geometry, 4326), TEXT[], TEXT, TEXT, TEXT);
DROP FUNCTION IF EXISTS cdb_dataservices_server.obs_getavailabledenominators(TEXT, TEXT, geometry(Geometry, 4326), TEXT[], TEXT, TEXT, TEXT);
DROP FUNCTION IF EXISTS cdb_dataservices_server.obs_getavailablegeometries(TEXT, TEXT, geometry(Geometry, 4326), TEXT[], TEXT, TEXT, TEXT);
DROP FUNCTION IF EXISTS cdb_dataservices_server.obs_getavailabletimespans(TEXT, TEXT, geometry(Geometry, 4326), TEXT[], TEXT, TEXT, TEXT);
DROP FUNCTION IF EXISTS cdb_dataservices_server.obs_legacybuildermetadata(TEXT, TEXT, TEXT);
DROP TYPE IF EXISTS cdb_dataservices_server.obs_meta_numerator;
DROP TYPE IF EXISTS cdb_dataservices_server.obs_meta_denominator;
DROP TYPE IF EXISTS cdb_dataservices_server.obs_meta_geometry;
DROP TYPE IF EXISTS cdb_dataservices_server.obs_meta_timespan;

View File

@@ -0,0 +1,12 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.18.1'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE score numeric;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE numtiles bigint;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE notnull_percent numeric;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE numgeoms numeric;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE percentfill numeric;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE estnumgeoms numeric;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry ADD ATTRIBUTE meanmediansize numeric;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.18.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE score;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE numtiles;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE notnull_percent;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE numgeoms;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE percentfill;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE estnumgeoms;
ALTER TYPE cdb_dataservices_server.obs_meta_geometry DROP ATTRIBUTE meanmediansize;

View File

@@ -0,0 +1,109 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.19.0'" to load this file. \quit
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_type') THEN
CREATE TYPE cdb_dataservices_server.service_type AS ENUM (
'isolines',
'hires_geocoder',
'routing',
'observatory'
);
END IF;
END $$;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_quota_info') THEN
CREATE TYPE cdb_dataservices_server.service_quota_info AS (
service cdb_dataservices_server.service_type,
monthly_quota NUMERIC,
used_quota NUMERIC,
soft_limit BOOLEAN,
provider TEXT
);
END IF;
END $$;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info(
username TEXT,
orgname TEXT)
RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$
from cartodb_services.metrics.user import UserMetricsService
from datetime import date
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
today = date.today()
ret = []
#-- Isolines
service = 'isolines'
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
user_service = UserMetricsService(user_isolines_config, redis_conn)
monthly_quota = user_isolines_config.isolines_quota
used_quota = user_service.used_quota(user_isolines_config.service_type, today)
soft_limit = user_isolines_config.soft_isolines_limit
provider = user_isolines_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Hires Geocoder
service = 'hires_geocoder'
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
user_service = UserMetricsService(user_geocoder_config, redis_conn)
monthly_quota = user_geocoder_config.geocoding_quota
used_quota = user_service.used_quota(user_geocoder_config.service_type, today)
soft_limit = user_geocoder_config.soft_geocoding_limit
provider = user_geocoder_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Routing
service = 'routing'
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_routing_config = GD["user_routing_config_{0}".format(username)]
user_service = UserMetricsService(user_routing_config, redis_conn)
monthly_quota = user_routing_config.monthly_quota
used_quota = user_service.used_quota(user_routing_config.service_type, today)
soft_limit = user_routing_config.soft_limit
provider = user_routing_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Observatory
service = 'observatory'
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
user_service = UserMetricsService(user_obs_config, redis_conn)
monthly_quota = user_obs_config.monthly_quota
used_quota = user_service.used_quota(user_obs_config.service_type, today)
soft_limit = user_obs_config.soft_limit
provider = user_obs_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
return ret
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota(
username TEXT,
orgname TEXT,
service_ TEXT,
input_size NUMERIC)
returns BOOLEAN AS $$
DECLARE
params cdb_dataservices_server.service_quota_info;
BEGIN
SELECT * INTO params
FROM cdb_dataservices_server.cdb_service_quota_info(username, orgname) AS p
WHERE p.service = service_::cdb_dataservices_server.service_type;
RETURN params.soft_limit OR ((params.used_quota + input_size) <= params.monthly_quota);
END
$$ LANGUAGE plpgsql;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.18.1'" to load this file. \quit
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_enough_quota(
username TEXT,
orgname TEXT,
service_ TEXT,
input_size NUMERIC);
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_service_quota_info(
username TEXT,
orgname TEXT);
DROP TYPE IF EXISTS cdb_dataservices_server.service_quota_info;
DROP TYPE IF EXISTS cdb_dataservices_server.service_type;

View File

@@ -0,0 +1,187 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.20.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapzen_isolines(TEXT, TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsolines
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger)
mapzen_isolines = MapzenIsolines(client, logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
# -- TODO Support options properly
isolines = {}
for r in data_range:
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
isolines[r] = isoline
result = []
for r in data_range:
if len(isolines[r]) >= 3:
# -- TODO encapsulate this block into a func/method
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations])
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
multipolygon = plpy.execute(sql, 1)[0]['geom']
else:
multipolygon = None
result.append([source, r, multipolygon])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(isolines))
return result
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isolines')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
from cartodb_services.mapzen.types import coordinates_to_polygon
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
# -- Check the quota
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon])
else:
quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(result))
return result
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isochrones')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
if user_isolines_config.google_services_user:
raise Exception('This service is not available for google service users.')
with metrics('cb_isodistance', user_isolines_config, logger):
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
$$ LANGUAGE plpythonu;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.19.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapzen_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapzen_isochrones(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isolines(
username TEXT,
orgname TEXT,
isotype TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsolines
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger)
mapzen_isolines = MapzenIsolines(client, logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
# -- TODO Support options properly
isolines = {}
for r in data_range:
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
isolines[r] = isoline
result = []
for r in data_range:
if len(isolines[r]) >= 3:
# -- TODO encapsulate this block into a func/method
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations])
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
multipolygon = plpy.execute(sql, 1)[0]['geom']
else:
multipolygon = None
result.append([source, r, multipolygon])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(isolines))
return result
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isolines')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
type = 'isochrone'
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, type, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapzen_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
type = 'isodistance'
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, type, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
if user_isolines_config.google_services_user:
raise Exception('This service is not available for google service users.')
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
$$ LANGUAGE plpythonu;

File diff suppressed because it is too large Load Diff

View File

@@ -7,15 +7,21 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
options text[] DEFAULT ARRAY[]::text[],
units text DEFAULT 'kilometers')
RETURNS cdb_dataservices_server.simple_route AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_routing_config = GD["user_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
waypoints = [origin, destination]
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
with metrics('cdb_route_with_point', user_routing_config, logger):
waypoints = [origin, destination]
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
$$ LANGUAGE plpythonu;
@@ -27,12 +33,18 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
options text[] DEFAULT ARRAY[]::text[],
units text DEFAULT 'kilometers')
RETURNS cdb_dataservices_server.simple_route AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_routing_config = GD["user_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
with metrics('cdb_route_with_waypoints', user_routing_config, logger):
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
$$ LANGUAGE plpythonu;

View File

@@ -11,9 +11,9 @@ RETURNS text AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_snapshot_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_snapshot_config = GD["user_obs_snapshot_config_{0}".format(username)]
user_obs_config = GD["user_obs_snapshot_config_{0}".format(username)]
return user_obs_snapshot_config.connection_str
return user_obs_config.connection_str
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshotJSON(
@@ -34,6 +34,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_demographic_snapshot(
time_span TEXT DEFAULT NULL,
geometry_level TEXT DEFAULT NULL)
RETURNS json AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
import json
@@ -41,31 +42,32 @@ RETURNS json AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_snapshot_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_snapshot_config = GD["user_obs_snapshot_config_{0}".format(username)]
user_obs_config = GD["user_obs_snapshot_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_snapshot_config, redis_conn)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshotJSON($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level])
if result:
quota_service.increment_success_service_use()
return result[0]['snapshot']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_demographic_snapshot')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getdemographicsnapshot', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshotJSON($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level])
if result:
quota_service.increment_success_service_use()
return result[0]['snapshot']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_demographic_snapshot')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetDemographicSnapshot(
@@ -86,41 +88,43 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetDemographicSnapshot(
time_span TEXT DEFAULT NULL,
geometry_level TEXT DEFAULT NULL)
RETURNS SETOF JSON AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_snapshot_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_snapshot_config = GD["user_obs_snapshot_config_{0}".format(username)]
user_obs_config = GD["user_obs_snapshot_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_snapshot_config, redis_conn)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshot($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level])
if result:
resp = []
for element in result:
value = element['snapshot']
resp.append(value)
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_demographic_snapshot')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getdemographicsnapshot', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetDemographicSnapshot($1, $2, $3, $4, $5) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span, geometry_level])
if result:
resp = []
for element in result:
value = element['snapshot']
resp.append(value)
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_demographic_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_demographic_snapshot')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshotJSON(
@@ -139,6 +143,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_get_segment_snapshot(
geom geometry(Geometry, 4326),
geometry_level TEXT DEFAULT NULL)
RETURNS json AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
import json
@@ -146,31 +151,32 @@ RETURNS json AS $$
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_snapshot_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_snapshot_config = GD["user_obs_snapshot_config_{0}".format(username)]
user_obs_config = GD["user_obs_snapshot_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_snapshot_config, redis_conn)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetSegmentSnapshotJSON($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level])
if result:
quota_service.increment_success_service_use()
return result[0]['snapshot']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_segment_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_segment_snapshot')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getsegmentsnapshot', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetSegmentSnapshotJSON($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level])
if result:
quota_service.increment_success_service_use()
return result[0]['snapshot']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to obs_get_segment_snapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to obs_get_segment_snapshot')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetSegmentSnapshot(
@@ -189,41 +195,43 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetSegmentSnapshot(
geom geometry(Geometry, 4326),
geometry_level TEXT DEFAULT NULL)
RETURNS SETOF JSON AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_snapshot_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_snapshot_config = GD["user_obs_snapshot_config_{0}".format(username)]
user_obs_config = GD["user_obs_snapshot_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_snapshot_config, redis_conn)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetSegmentSnapshot($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level])
if result:
resp = []
for element in result:
value = element['snapshot']
resp.append(value)
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetSegmentSnapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetSegmentSnapshot')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getsegmentsnapshot', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetSegmentSnapshot($1, $2, $3, $4) as snapshot;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, geometry_level])
if result:
resp = []
for element in result:
value = element['snapshot']
resp.append(value)
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetSegmentSnapshot', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetSegmentSnapshot')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasure(
@@ -248,6 +256,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasure(
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL)
RETURNS NUMERIC AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -263,22 +272,23 @@ RETURNS NUMERIC AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasure($1, $2, $3, $4, $5, $6, $7) as measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, measure_id, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasure', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasure')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getmeasure', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasure($1, $2, $3, $4, $5, $6, $7) as measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, measure_id, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasure', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasure')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetCategory(
@@ -301,6 +311,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetCategory(
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL)
RETURNS TEXT AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -316,22 +327,23 @@ RETURNS TEXT AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetCategory($1, $2, $3, $4, $5, $6) as category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, category_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['category']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetCategory', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetCategory')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getcategory', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetCategory($1, $2, $3, $4, $5, $6) as category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, category_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['category']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetCategory', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetCategory')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusMeasure(
@@ -356,6 +368,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusMeasure(
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL)
RETURNS NUMERIC AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -371,22 +384,23 @@ RETURNS NUMERIC AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusMeasure($1, $2, $3, $4, $5, $6, $7) as census_measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, name, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['census_measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetUSCensusMeasure', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetUSCensusMeasure')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getuscensusmeasure', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusMeasure($1, $2, $3, $4, $5, $6, $7) as census_measure;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, name, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['census_measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetUSCensusMeasure', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetUSCensusMeasure')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetUSCensusCategory(
@@ -409,6 +423,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetUSCensusCategory(
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL)
RETURNS TEXT AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -424,22 +439,23 @@ RETURNS TEXT AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusCategory($1, $2, $3, $4, $5, $6) as census_category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, name, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['census_category']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetUSCensusCategory', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetUSCensusCategory')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getuscensuscategory', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetUSCensusCategory($1, $2, $3, $4, $5, $6) as census_category;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, name, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['census_category']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetUSCensusCategory', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetUSCensusCategory')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPopulation(
@@ -462,6 +478,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPopulation(
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL)
RETURNS NUMERIC AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -477,22 +494,23 @@ RETURNS NUMERIC AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetPopulation($1, $2, $3, $4, $5, $6) as population;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['population']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPopulation', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPopulation')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getpopulation', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetPopulation($1, $2, $3, $4, $5, $6) as population;", ["text", "text", "geometry(Geometry, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, normalize, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['population']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPopulation', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPopulation')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeasureById(
@@ -515,6 +533,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeasureById(
boundary_id TEXT,
time_span TEXT DEFAULT NULL)
RETURNS NUMERIC AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -530,20 +549,191 @@ RETURNS NUMERIC AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasureById($1, $2, $3, $4, $5, $6) as measure;", ["text", "text", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom_ref, measure_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasureById')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getmeasurebyid', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeasureById($1, $2, $3, $4, $5, $6) as measure;", ["text", "text", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom_ref, measure_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['measure']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasureById')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
username TEXT,
orgname TEXT,
geomvals geomval[],
params JSON,
merge BOOLEAN DEFAULT True)
RETURNS TABLE (
id INT,
data JSON
) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
username TEXT,
orgname TEXT,
geomvals geomval[],
params JSON,
merge BOOLEAN DEFAULT True)
RETURNS TABLE (
id INT,
data JSON
) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
with metrics('obs_getdata', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"])
result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge])
empty_results = len(geomvals) - len(result)
if empty_results > 0:
quota_service.increment_empty_service_use(empty_results)
if result:
quota_service.increment_success_service_use(len(result))
return result
else:
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use(len(geomvals))
logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetData')
finally:
quota_service.increment_total_service_use(len(geomvals))
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
username TEXT,
orgname TEXT,
geomrefs TEXT[],
params JSON)
RETURNS TABLE (
id TEXT,
data JSON
) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
username TEXT,
orgname TEXT,
geomrefs TEXT[],
params JSON)
RETURNS TABLE (
id TEXT,
data JSON
) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_obs_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
with metrics('obs_getdata', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"])
result = plpy.execute(obs_plan, [username, orgname, geomrefs, params])
empty_results = len(geomrefs) - len(result)
if empty_results > 0:
quota_service.increment_empty_service_use(empty_results)
if result:
quota_service.increment_success_service_use(len(result))
return result
else:
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use(len(geomrefs))
exc_info = sys.exc_info()
logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2]))
logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetData')
finally:
quota_service.increment_total_service_use(len(geomrefs))
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta(
username TEXT,
orgname TEXT,
geom Geometry(Geometry, 4326),
params JSON,
max_timespan_rank INTEGER DEFAULT NULL,
max_score_rank INTEGER DEFAULT NULL,
target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta(
username TEXT,
orgname TEXT,
geom Geometry(Geometry, 4326),
params JSON,
max_timespan_rank INTEGER DEFAULT NULL,
max_score_rank INTEGER DEFAULT NULL,
target_geoms INTEGER DEFAULT NULL)
RETURNS JSON AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
with metrics('obs_getmeta', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"])
result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms])
if result:
return result[0]['meta']
else:
return None
except BaseException as e:
import sys
logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeta')
$$ LANGUAGE plpythonu;

View File

@@ -14,6 +14,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_Search(
search_term TEXT,
relevant_boundary TEXT DEFAULT NULL)
RETURNS TABLE(id text, description text, name text, aggregate text, source text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -29,30 +30,31 @@ RETURNS TABLE(id text, description text, name text, aggregate text, source text)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_Search($1, $2, $3, $4);", ["text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, search_term, relevant_boundary])
if result:
resp = []
for element in result:
id = element['id']
description = element['description']
name = element['name']
aggregate = element['aggregate']
source = element['source']
resp.append([id, description, name, aggregate, source])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return [None, None, None, None, None]
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_Search', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_Search')
finally:
quota_service.increment_total_service_use()
with metrics('obs_search', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_Search($1, $2, $3, $4);", ["text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, search_term, relevant_boundary])
if result:
resp = []
for element in result:
id = element['id']
description = element['description']
name = element['name']
aggregate = element['aggregate']
source = element['source']
resp.append([id, description, name, aggregate, source])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return [None, None, None, None, None]
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_Search', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_Search')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetAvailableBoundaries(
@@ -71,6 +73,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableBoundaries(
geom geometry(Geometry, 4326),
time_span TEXT DEFAULT NULL)
RETURNS TABLE(boundary_id text, description text, time_span text, tablename text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -86,27 +89,28 @@ RETURNS TABLE(boundary_id text, description text, time_span text, tablename text
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetAvailableBoundaries($1, $2, $3, $4) as available_boundaries;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span])
if result:
resp = []
for element in result:
id = element['boundary_id']
description = element['description']
tspan = element['time_span']
tablename = element['tablename']
resp.append([id, description, tspan, tablename])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasureById')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getavailableboundaries', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetAvailableBoundaries($1, $2, $3, $4) as available_boundaries;", ["text", "text", "geometry(Geometry, 4326)", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, time_span])
if result:
resp = []
for element in result:
id = element['boundary_id']
description = element['description']
tspan = element['time_span']
tablename = element['tablename']
resp.append([id, description, tspan, tablename])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetMeasureById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetMeasureById')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;

View File

@@ -16,6 +16,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundary(
boundary_id TEXT,
time_span TEXT DEFAULT NULL)
RETURNS geometry(Geometry, 4326) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -31,22 +32,23 @@ RETURNS geometry(Geometry, 4326) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundary($1, $2, $3, $4) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundary', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundary')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getboundary', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundary($1, $2, $3, $4) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundary', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundary')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryId(
@@ -67,6 +69,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryId(
boundary_id TEXT,
time_span TEXT DEFAULT NULL)
RETURNS TEXT AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -82,22 +85,23 @@ RETURNS TEXT AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryId($1, $2, $3, $4, $5) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundaryId', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundaryId')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getboundaryid', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryId($1, $2, $3, $4, $5) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundaryId', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundaryId')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundaryById(
@@ -118,6 +122,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundaryById(
boundary_id TEXT,
time_span TEXT DEFAULT NULL)
RETURNS geometry(Geometry, 4326) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -133,22 +138,23 @@ RETURNS geometry(Geometry, 4326) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryById($1, $2, $3, $4, $5) as boundary;", ["text", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geometry_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundaryById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundaryById')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getboundarybyid', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetBoundaryById($1, $2, $3, $4, $5) as boundary;", ["text", "text", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geometry_id, boundary_id, time_span])
if result:
quota_service.increment_success_service_use()
return result[0]['boundary']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundaryById', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundaryById')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByGeometry(
@@ -171,6 +177,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByGeometry(
time_span TEXT DEFAULT NULL,
overlap_type TEXT DEFAULT NULL)
RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -186,27 +193,28 @@ RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundariesByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundariesByGeometry')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getboundariesbygeometry', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundariesByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundariesByGeometry')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius(
@@ -231,6 +239,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetBoundariesByPointAndRa
time_span TEXT DEFAULT NULL,
overlap_type TEXT DEFAULT NULL)
RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -246,27 +255,28 @@ RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundariesByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundariesByPointAndRadius')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getboundariesbypointandradius', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetBoundariesByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetBoundariesByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetBoundariesByPointAndRadius')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByGeometry(
@@ -289,6 +299,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByGeometry(
time_span TEXT DEFAULT NULL,
overlap_type TEXT DEFAULT NULL)
RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -304,27 +315,28 @@ RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPointsByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPointsByGeometry')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getpointsbygeometry', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByGeometry($1, $2, $3, $4, $5, $6) as boundary;", ["text", "text", "geometry(Point, 4326)", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPointsByGeometry', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPointsByGeometry')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetPointsByPointAndRadius(
@@ -349,6 +361,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetPointsByPointAndRadius
time_span TEXT DEFAULT NULL,
overlap_type TEXT DEFAULT NULL)
RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
@@ -364,25 +377,26 @@ RETURNS TABLE(the_geom geometry, geom_refs text) AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPointsByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPointsByPointAndRadius')
finally:
quota_service.increment_total_service_use()
with metrics('obs_getpointsbypointandradius', user_obs_config, logger):
try:
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetPointsByPointAndRadius($1, $2, $3, $4, $5, $6, $7) as boundary;", ["text", "text", "geometry(Point, 4326)", "numeric", "text", "text", "text"])
result = plpy.execute(obs_plan, [username, orgname, geom, radius, boundary_id, time_span, overlap_type])
if result:
resp = []
for element in result:
the_geom = element['the_geom']
geom_refs = element['geom_refs']
resp.append([the_geom, geom_refs])
quota_service.increment_success_service_use()
return resp
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to OBS_GetPointsByPointAndRadius', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to OBS_GetPointsByPointAndRadius')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;

View File

@@ -3,3 +3,73 @@ RETURNS text AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT cdb_observatory.obs_dumpversion();
$$ LANGUAGE plproxy;
-- We could create a super type for the common data like id, name and so on but we need to parse inside the functions because the -- the return data tha comes from OBS is a TABLE() with them
CREATE TYPE cdb_dataservices_server.obs_meta_numerator AS (numer_id text, numer_name text, numer_description text, numer_weight text, numer_license text, numer_source text, numer_type text, numer_aggregate text, numer_extra jsonb, numer_tags jsonb, valid_denom boolean, valid_geom boolean, valid_timespan boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableNumerators(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_numerator AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableNumerators(bounds, filter_tags, denom_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_denominator AS (denom_id text, denom_name text, denom_description text, denom_weight text, denom_license text, denom_source text, denom_type text, denom_aggregate text, denom_extra jsonb, denom_tags jsonb, valid_numer boolean, valid_geom boolean, valid_timespan boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableDenominators(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_denominator AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableDenominators(bounds, filter_tags, numer_id, geom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_geometry AS (geom_id text, geom_name text, geom_description text, geom_weight text, geom_aggregate text, geom_license text, geom_source text, valid_numer boolean, valid_denom boolean, valid_timespan boolean, score numeric, numtiles bigint, notnull_percent numeric, numgeoms numeric, percentfill numeric, estnumgeoms numeric, meanmediansize numeric);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableGeometries(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
timespan TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_geometry AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableGeometries(bounds, filter_tags, numer_id, denom_id, timespan);
$$ LANGUAGE plproxy;
CREATE TYPE cdb_dataservices_server.obs_meta_timespan AS (timespan_id text, timespan_name text, timespan_description text, timespan_weight text, timespan_aggregate text, timespan_license text, timespan_source text, valid_numer boolean, valid_denom boolean, valid_geom boolean);
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetAvailableTimespans(
username TEXT,
orgname TEXT,
bounds geometry(Geometry, 4326) DEFAULT NULL,
filter_tags TEXT[] DEFAULT NULL,
numer_id TEXT DEFAULT NULL,
denom_id TEXT DEFAULT NULL,
geom_id TEXT DEFAULT NULL)
RETURNS SETOF cdb_dataservices_server.obs_meta_timespan AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_GetAvailableTimespans(bounds, filter_tags, numer_id, denom_id, geom_id);
$$ LANGUAGE plproxy;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_LegacyBuilderMetadata(
username TEXT,
orgname TEXT,
aggregate_type TEXT DEFAULT NULL)
RETURNS TABLE(name TEXT, subsection JSON) AS $$
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
SELECT * FROM cdb_observatory.OBS_LegacyBuilderMetadata(aggregate_type);
$$ LANGUAGE plproxy;

View File

@@ -0,0 +1,105 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_type') THEN
CREATE TYPE cdb_dataservices_server.service_type AS ENUM (
'isolines',
'hires_geocoder',
'routing',
'observatory'
);
END IF;
END $$;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_quota_info') THEN
CREATE TYPE cdb_dataservices_server.service_quota_info AS (
service cdb_dataservices_server.service_type,
monthly_quota NUMERIC,
used_quota NUMERIC,
soft_limit BOOLEAN,
provider TEXT
);
END IF;
END $$;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info(
username TEXT,
orgname TEXT)
RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$
from cartodb_services.metrics.user import UserMetricsService
from datetime import date
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
today = date.today()
ret = []
#-- Isolines
service = 'isolines'
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
user_service = UserMetricsService(user_isolines_config, redis_conn)
monthly_quota = user_isolines_config.isolines_quota
used_quota = user_service.used_quota(user_isolines_config.service_type, today)
soft_limit = user_isolines_config.soft_isolines_limit
provider = user_isolines_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Hires Geocoder
service = 'hires_geocoder'
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
user_service = UserMetricsService(user_geocoder_config, redis_conn)
monthly_quota = user_geocoder_config.geocoding_quota
used_quota = user_service.used_quota(user_geocoder_config.service_type, today)
soft_limit = user_geocoder_config.soft_geocoding_limit
provider = user_geocoder_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Routing
service = 'routing'
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_routing_config = GD["user_routing_config_{0}".format(username)]
user_service = UserMetricsService(user_routing_config, redis_conn)
monthly_quota = user_routing_config.monthly_quota
used_quota = user_service.used_quota(user_routing_config.service_type, today)
soft_limit = user_routing_config.soft_limit
provider = user_routing_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
#-- Observatory
service = 'observatory'
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_obs_config = GD["user_obs_config_{0}".format(username)]
user_service = UserMetricsService(user_obs_config, redis_conn)
monthly_quota = user_obs_config.monthly_quota
used_quota = user_service.used_quota(user_obs_config.service_type, today)
soft_limit = user_obs_config.soft_limit
provider = user_obs_config.provider
ret += [[service, monthly_quota, used_quota, soft_limit, provider]]
return ret
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota(
username TEXT,
orgname TEXT,
service_ TEXT,
input_size NUMERIC)
returns BOOLEAN AS $$
DECLARE
params cdb_dataservices_server.service_quota_info;
BEGIN
SELECT * INTO params
FROM cdb_dataservices_server.cdb_service_quota_info(username, orgname) AS p
WHERE p.service = service_::cdb_dataservices_server.service_type;
RETURN params.soft_limit OR ((params.used_quota + input_size) <= params.monthly_quota);
END
$$ LANGUAGE plpgsql;

View File

@@ -1,22 +1,28 @@
-- Geocodes a street address given a searchtext and a state and/or country
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
if user_geocoder_config.heremaps_geocoder:
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
elif user_geocoder_config.google_geocoder:
google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
elif user_geocoder_config.mapzen_geocoder:
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
else:
raise Exception('Requested geocoder is not available')
with metrics('cdb_geocode_street_point', user_geocoder_config, logger):
if user_geocoder_config.heremaps_geocoder:
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
elif user_geocoder_config.google_geocoder:
google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
elif user_geocoder_config.mapzen_geocoder:
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
else:
raise Exception('Requested geocoder is not available')
$$ LANGUAGE plpythonu;

View File

@@ -2,6 +2,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin0_polygon(us
RETURNS Geometry AS $$
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
@@ -13,23 +14,24 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin0_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [country_name], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode admin0 polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode admin0 polygon')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_admin0_polygon', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin0_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [country_name], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode admin0 polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode admin0 polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;

View File

@@ -1,6 +1,7 @@
---- cdb_geocode_admin1_polygon(admin1_name text)
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -14,44 +15,11 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [admin1_name], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode admin1 polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
---- cdb_geocode_admin1_polygon(admin1_name text, country_name text)
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text, country_name text)
RETURNS Geometry AS $$
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1), trim($2)) AS mypolygon", ["text", "text"])
rv = plpy.execute(plan, [admin1_name, country_name], 1)
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [admin1_name], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
@@ -68,6 +36,44 @@ RETURNS Geometry AS $$
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
---- cdb_geocode_admin1_polygon(admin1_name text, country_name text)
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_admin1_polygon(username text, orgname text, admin1_name text, country_name text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_internal_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_internal_geocoder_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
with metrics('cdb_geocode_admin1_polygon', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_admin1_polygon(trim($1), trim($2)) AS mypolygon", ["text", "text"])
rv = plpy.execute(plan, [admin1_name, country_name], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode admin1 polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode admin1 polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
--------------------------------------------------------------------------------
-- Implementation of the server extension

View File

@@ -35,7 +35,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_namedplac
RETURNS Geometry AS $$
from cartodb_services.mapzen import MapzenGeocoder
from cartodb_services.mapzen.types import country_to_iso3
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import QuotaService, metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
@@ -50,35 +50,36 @@ RETURNS Geometry AS $$
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
geocoder = MapzenGeocoder(user_geocoder_config.mapzen_api_key, logger)
country_iso3 = None
if country_name:
country_iso3 = country_to_iso3(country_name)
coordinates = geocoder.geocode(searchtext=city_name, city=None,
state_province=admin1_name,
country=country_iso3, search_type='locality')
if coordinates:
quota_service.increment_success_service_use()
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
return point['st_setsrid']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode city point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode city point using mapzen')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_namedplace_point', user_geocoder_config, logger):
try:
geocoder = MapzenGeocoder(user_geocoder_config.mapzen_api_key, logger)
country_iso3 = None
if country_name:
country_iso3 = country_to_iso3(country_name)
coordinates = geocoder.geocode(searchtext=city_name, city=None,
state_province=admin1_name,
country=country_iso3, search_type='locality')
if coordinates:
quota_service.increment_success_service_use()
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
return point['st_setsrid']
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode city point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode city point using mapzen')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_internal_geocode_namedplace(username text, orgname text, city_name text, admin1_name text DEFAULT NULL, country_name text DEFAULT NULL)
RETURNS Geometry AS $$
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.metrics import InternalGeocoderConfig, metrics
from cartodb_services.tools import Logger,LoggerConfig
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
@@ -90,30 +91,32 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
if admin1_name and country_name:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2), trim($3)) AS mypoint", ["text", "text", "text"])
rv = plpy.execute(plan, [city_name, admin1_name, country_name], 1)
elif country_name:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2)) AS mypoint", ["text", "text"])
rv = plpy.execute(plan, [city_name, country_name], 1)
else:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1)) AS mypoint", ["text"])
rv = plpy.execute(plan, [city_name], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode namedplace point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode namedplace point')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_namedplace_point', user_geocoder_config, logger):
try:
if admin1_name and country_name:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2), trim($3)) AS mypoint", ["text", "text", "text"])
rv = plpy.execute(plan, [city_name, admin1_name, country_name], 1)
elif country_name:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1), trim($2)) AS mypoint", ["text", "text"])
rv = plpy.execute(plan, [city_name, country_name], 1)
else:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_namedplace_point(trim($1)) AS mypoint", ["text"])
rv = plpy.execute(plan, [city_name], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode namedplace point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode namedplace point')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
--------------------------------------------------------------------------------

View File

@@ -1,5 +1,6 @@
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -13,27 +14,29 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1)) AS mypoint", ["text"])
rv = plpy.execute(plan, [code], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code point')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1)) AS mypoint", ["text"])
rv = plpy.execute(plan, [code], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code point')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_point(username text, orgname text, code text, country text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -47,27 +50,29 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1), trim($2)) AS mypoint", ["TEXT", "TEXT"])
rv = plpy.execute(plan, [code, country], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code point')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_point(trim($1), trim($2)) AS mypoint", ["TEXT", "TEXT"])
rv = plpy.execute(plan, [code, country], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code point', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code point')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -81,27 +86,29 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [code], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1)) AS mypolygon", ["text"])
rv = plpy.execute(plan, [code], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_postalcode_polygon(username text, orgname text, code text, country text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -115,23 +122,24 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1), trim($2)) AS mypolygon", ["TEXT", "TEXT"])
rv = plpy.execute(plan, [code, country], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_postalcode_point', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_postalcode_polygon(trim($1), trim($2)) AS mypolygon", ["TEXT", "TEXT"])
rv = plpy.execute(plan, [code, country], 1)
result = rv[0]["mypolygon"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
--------------------------------------------------------------------------------

View File

@@ -1,5 +1,6 @@
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_ipaddress_point(username text, orgname text, ip text)
RETURNS Geometry AS $$
from cartodb_services.metrics import metrics
from cartodb_services.metrics import QuotaService
from cartodb_services.metrics import InternalGeocoderConfig
from cartodb_services.tools import Logger,LoggerConfig
@@ -13,23 +14,24 @@ RETURNS Geometry AS $$
logger_config = GD["logger_config"]
logger = Logger(logger_config)
quota_service = QuotaService(user_geocoder_config, redis_conn)
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_ipaddress_point(trim($1)) AS mypoint", ["TEXT"])
rv = plpy.execute(plan, [ip], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
with metrics('cdb_geocode_ipaddress_point', user_geocoder_config, logger):
try:
plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_geocode_ipaddress_point(trim($1)) AS mypoint", ["TEXT"])
rv = plpy.execute(plan, [ip], 1)
result = rv[0]["mypoint"]
if result:
quota_service.increment_success_service_use()
return result
else:
quota_service.increment_empty_service_use()
return None
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to geocode postal code polygon', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to geocode postal code polygon')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu;
--------------------------------------------------------------------------------

View File

@@ -57,11 +57,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isolines(
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance(
username TEXT,
orgname TEXT,
isotype TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
@@ -78,7 +76,6 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
# -- Check the quota
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
@@ -96,14 +93,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
# -- TODO Support options properly
isolines = {}
if isotype == 'isodistance':
for r in data_range:
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
isolines[r] = isoline
elif isotype == 'isochrone':
for r in data_range:
isoline = mapzen_isolines.calculate_isochrone(origin, mode, r)
isolines[r] = isoline
for r in data_range:
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
isolines[r] = isoline
result = []
for r in data_range:
@@ -130,3 +122,67 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
from cartodb_services.mapzen.types import coordinates_to_polygon
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
# -- Check the quota
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon])
else:
quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(result))
return result
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isochrones')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER;

View File

@@ -1,21 +1,28 @@
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
if user_isolines_config.google_services_user:
raise Exception('This service is not available for google service users.')
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
with metrics('cb_isodistance', user_isolines_config, logger):
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
$$ LANGUAGE plpythonu;
-- heremaps isodistance
@@ -40,10 +47,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
type = 'isodistance'
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, type, source, mode, range, options])
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;

View File

@@ -1,21 +1,28 @@
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
if user_isolines_config.google_services_user:
raise Exception('This service is not available for google service users.')
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
with metrics('cb_isochrone', user_isolines_config, logger):
if user_isolines_config.heremaps_provider:
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
elif user_isolines_config.mapzen_provider:
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
else:
raise Exception('Requested isolines provider is not available')
$$ LANGUAGE plpythonu;
-- heremaps isochrone
@@ -40,9 +47,8 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
type = 'isochrone'
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, type, source, mode, range, options])
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
return result
$$ LANGUAGE plpythonu;

View File

@@ -141,6 +141,39 @@ SELECT exists(SELECT *
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getmeta'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, json, integer, integer, integer');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getdata'
AND oidvectortypes(p.proargtypes) = 'text, text, geomval[], json, boolean');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getdata'
AND oidvectortypes(p.proargtypes) = 'text, text, text[], json');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
@@ -185,3 +218,58 @@ SELECT exists(SELECT *
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailablenumerators'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailabledenominators'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailablegeometries'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailabletimespans'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
exists
--------
t
(1 row)
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_legacybuildermetadata'
AND oidvectortypes(p.proargtypes) = 'text, text, text');
exists
--------
t
(1 row)

View File

@@ -89,6 +89,27 @@ SELECT exists(SELECT *
AND proname = 'obs_getboundarybyid'
AND oidvectortypes(p.proargtypes) = 'text, text, text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getmeta'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, json, integer, integer, integer');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getdata'
AND oidvectortypes(p.proargtypes) = 'text, text, geomval[], json, boolean');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getdata'
AND oidvectortypes(p.proargtypes) = 'text, text, text[], json');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
@@ -115,4 +136,39 @@ SELECT exists(SELECT *
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getpointsbypointandradius'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, numeric, text, text, text');
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, numeric, text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailablenumerators'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailabledenominators'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailablegeometries'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_getavailabletimespans'
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, text[], text, text, text');
SELECT exists(SELECT *
FROM pg_proc p
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'cdb_dataservices_server'
AND proname = 'obs_legacybuildermetadata'
AND oidvectortypes(p.proargtypes) = 'text, text, text');

View File

@@ -29,12 +29,12 @@ NOTE: a system installation is required at present because the library is meant
## Running the unit tests
Just run `nosetests`
Just run `nosetests test/`
```shell
$ nosetests
.................................................
$ nosetests test/
......................................................................................................
----------------------------------------------------------------------
Ran 49 tests in 0.131s
Ran 102 tests in 0.122s
OK
```
@@ -46,5 +46,7 @@ cd $(git rev-parse --show-toplevel)/test
python run_tests.py --host=$YOUR_HOST $YOUR_USERNAME $YOUR_API_KEY
```
## TODO
- Move dependencies expressed in `requirements.txt` to `setup.py`
## Versioning
Once you're satisfied with your changes, it is time to bump the version number in the `setup.py`. A couple of rules:
- **Backwards compatibility**: in general all changes shall be backwards compatible. Do not remove any code used from the server public `pl/python` functions or you'll run into problems when deploying.
- **Semantic versioning**: we try to stick to [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html)

View File

@@ -4,16 +4,21 @@
import json
import requests
from requests.adapters import HTTPAdapter
from exceptions import *
from cartodb_services.metrics import Traceable
class HereMapsGeocoder:
class HereMapsGeocoder(Traceable):
'A Here Maps Geocoder wrapper for python'
PRODUCTION_GEOCODE_JSON_URL = 'https://geocoder.api.here.com/6.2/geocode.json'
STAGING_GEOCODE_JSON_URL = 'https://geocoder.cit.api.here.com/6.2/geocode.json'
DEFAULT_MAXRESULTS = 1
DEFAULT_GEN = 9
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
MAX_RETRIES=1
ADDRESS_PARAMS = [
'city',
@@ -85,7 +90,12 @@ class HereMapsGeocoder:
'gen': self.gen
}
request_params.update(params)
response = requests.get(self.host, params=request_params)
# TODO Extract HTTP client wrapper
session = requests.Session()
session.mount(self.host, HTTPAdapter(max_retries=self.MAX_RETRIES))
response = session.get(self.host, params=request_params,
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
self.add_response_data(response, self._logger)
if response.status_code == requests.codes.ok:
return json.loads(response.text)
elif response.status_code == requests.codes.bad_request:

View File

@@ -2,14 +2,19 @@ import requests
import json
from exceptions import WrongParams
from requests.adapters import HTTPAdapter
from cartodb_services.metrics import Traceable
class HereMapsRoutingIsoline:
class HereMapsRoutingIsoline(Traceable):
'A Here Maps Routing wrapper for python'
PRODUCTION_ROUTING_BASE_URL = 'https://isoline.route.api.here.com'
STAGING_ROUTING_BASE_URL = 'https://isoline.route.cit.api.here.com'
ISOLINE_PATH = '/routing/7.2/calculateisoline.json'
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
MAX_RETRIES = 1
ACCEPTED_MODES = {
"walk": "pedestrian",
@@ -50,7 +55,12 @@ class HereMapsRoutingIsoline:
data_range,
range_type,
parsed_options)
response = requests.get(self._url, params=request_params)
# TODO Extract HTTP client wrapper
session = requests.Session()
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
response = requests.get(self._url, params=request_params,
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
self.add_response_data(response, self._logger)
if response.status_code == requests.codes.ok:
return self.__parse_isolines_response(response.text)
elif response.status_code == requests.codes.bad_request:

View File

@@ -2,3 +2,4 @@ from routing import MapzenRouting, MapzenRoutingResponse
from isolines import MapzenIsolines
from geocoder import MapzenGeocoder
from matrix_client import MatrixClient
from isochrones import MapzenIsochrones

View File

@@ -2,15 +2,20 @@ import requests
import json
import re
from requests.adapters import HTTPAdapter
from exceptions import WrongParams, MalformedResult, ServiceException
from qps import qps_retry
from cartodb_services.tools import Coordinate, PolyLine
from cartodb_services.metrics import Traceable
class MapzenGeocoder:
class MapzenGeocoder(Traceable):
'A Mapzen Geocoder wrapper for python'
BASE_URL = 'https://search.mapzen.com/v1/search'
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
MAX_RETRIES = 1
def __init__(self, app_key, logger, base_url=BASE_URL):
self._app_key = app_key
@@ -24,7 +29,12 @@ class MapzenGeocoder:
state_province,
country, search_type)
try:
response = requests.get(self._url, params=request_params)
# TODO Extract HTTP client wrapper
session = requests.Session()
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
response = session.get(self._url, params=request_params,
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
self.add_response_data(response, self._logger)
if response.status_code == requests.codes.ok:
return self.__parse_response(response.text)
elif response.status_code == requests.codes.bad_request:
@@ -41,6 +51,12 @@ class MapzenGeocoder:
"state_province": state_province})
raise ServiceException('Error trying to geocode {0} using mapzen'.format(searchtext),
response)
except requests.Timeout as te:
# In case of timeout we want to stop the job because the server
# could be down
self._logger.error('Timeout connecting to Mapzen geocoding server', te)
raise ServiceException('Error trying to geocode {0} using mapzen'.format(searchtext),
None)
except requests.ConnectionError as e:
# Don't raise the exception to continue with the geocoding job
self._logger.error('Error connecting to Mapzen geocoding server',

View File

@@ -0,0 +1,135 @@
import requests
import json
import re
from requests.adapters import HTTPAdapter
from exceptions import WrongParams, MalformedResult, ServiceException
from qps import qps_retry
class MapzenIsochrones:
'A Mapzen Isochrones wrapper for python'
BASE_URL = 'https://matrix.mapzen.com/isochrone'
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
MAX_RETRIES = 1
ACCEPTED_MODES = {
"walk": "pedestrian",
"car": "auto"
}
def __init__(self, app_key, logger, base_url=BASE_URL):
self._app_key = app_key
self._url = base_url
self._logger = logger
@qps_retry(qps=7)
def isochrone(self, locations, costing, ranges):
request_params = self._parse_request_params(locations, costing,
ranges)
try:
# TODO Extract HTTP client wrapper
session = requests.Session()
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
response = session.get(self._url, params=request_params,
timeout=(self.CONNECT_TIMEOUT,
self.READ_TIMEOUT))
if response.status_code is requests.codes.ok:
return self._parse_response(response)
elif response.status_code == requests.codes.bad_request:
return []
else:
self._logger.error('Error trying to get isochrones from mapzen',
data={"response_status": response.status_code,
"response_reason": response.reason,
"response_content": response.text,
"reponse_url": response.url,
"response_headers": response.headers,
"locations": locations,
"costing": costing})
raise ServiceException('Error trying to get isochrones from mapzen',
response)
except requests.Timeout as te:
# In case of timeout we want to stop the job because the server
# could be down
self._logger.error('Timeout connecting to Mapzen isochrones server', exception=te)
raise ServiceException('Error trying to calculate isochrones using mapzen',
None)
except requests.ConnectionError as e:
# Don't raise the exception to continue with the geocoding job
self._logger.error('Error connecting to Mapzen isochrones server',
exception=e)
return []
def _parse_request_params(self, locations, costing, ranges):
if costing in self.ACCEPTED_MODES:
mode_source = self.ACCEPTED_MODES[costing]
else:
raise WrongParams("{0} is not an accepted mode".format(costing))
contours = []
for r in ranges:
# range is in seconds but mapzen uses minutes
range_minutes = r / 60
contours.append({"time": range_minutes, "color": 'tbd'})
request_params = {
'json': json.dumps({'locations': [locations],
'costing': mode_source,
'contours': contours,
'generalize': 50,
'denoise': .3}),
'api_key': self._app_key
}
return request_params
def _parse_response(self, response):
try:
json_response = response.json()
isochrones = []
for feature in json_response['features']:
# Coordinates could have more than one isochrone. For the
# moment we're getting the first polygon only
coordinates = feature['geometry']['coordinates']
duration = feature['properties']['contour']
mapzen_response = MapzenIsochronesResponse(coordinates,
duration)
isochrones.append(mapzen_response)
return isochrones
except IndexError:
return []
except KeyError:
self._logger.error('Non existing key for mapzen isochrones response',
data={"response_status": response.status_code,
"response_reason": response.reason,
"response_content": response.text,
"reponse_url": response.url,
"response_headers": response.headers})
raise MalformedResult()
except ValueError:
# JSON decode error
self._logger.error('JSON decode error for Mapzen isochrones',
data={"response_status": response.status_code,
"response_reason": response.reason,
"response_content": response.text,
"reponse_url": response.url,
"response_headers": response.headers})
return []
class MapzenIsochronesResponse:
def __init__(self, coordinates, duration):
self._coordinates = coordinates
self._duration = duration
@property
def coordinates(self):
return self._coordinates
@property
def duration(self):
return self._duration

View File

@@ -86,7 +86,7 @@ class MapzenIsolines:
def calculate_isoline(self, origin, costing_model, isorange, upper_rmax, cost_variable, unit_factor=1.0):
# NOTE: not for production
self._logger.debug('Calculate isoline', data={"origin": origin, "costing_model": costing_model, "isorange": isorange})
# self._logger.debug('Calculate isoline', data={"origin": origin, "costing_model": costing_model, "isorange": isorange})
# Formally, a solution is an array of {angle, radius, lat, lon, cost} with cardinality NUMBER_OF_ANGLES
# we're looking for a solution in which abs(cost - isorange) / isorange <= TOLERANCE
@@ -105,14 +105,16 @@ class MapzenIsolines:
response = self._matrix_client.one_to_many([origin] + location_estimates, costing_model)
costs = [None] * self.NUMBER_OF_ANGLES
if not response:
# In case the matrix client doesn't return any data
break
for idx, c in enumerate(response['one_to_many'][0][1:]):
if c[cost_variable]:
costs[idx] = c[cost_variable]*unit_factor
else:
costs[idx] = isorange
# self._logger.debug('i = %d, costs = %s' % (i, costs))
errors = [(cost - isorange) / float(isorange) for cost in costs]
max_abs_error = max([abs(e) for e in errors])
if max_abs_error <= self.TOLERANCE:

View File

@@ -2,9 +2,10 @@ import requests
import json
from qps import qps_retry
from exceptions import ServiceException
from cartodb_services.metrics import Traceable
class MatrixClient:
class MatrixClient(Traceable):
"""
A minimal client for Mapzen Time-Distance Matrix Service
@@ -19,6 +20,8 @@ class MatrixClient:
"""
ONE_TO_MANY_URL = 'https://matrix.mapzen.com/one_to_many'
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
def __init__(self, matrix_key, logger):
self._matrix_key = matrix_key
@@ -41,9 +44,11 @@ class MatrixClient:
'costing': costing,
'api_key': self._matrix_key
}
response = requests.get(self.ONE_TO_MANY_URL, params=request_params)
response = requests.get(self.ONE_TO_MANY_URL, params=request_params,
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
self.add_response_data(response, self._logger)
if not requests.codes.ok:
if response.status_code != requests.codes.ok:
self._logger.error('Error trying to get matrix distance from mapzen',
data={"response_status": response.status_code,
"response_reason": response.reason,
@@ -52,6 +57,22 @@ class MatrixClient:
"response_headers": response.headers,
"locations": locations,
"costing": costing})
raise ServiceException("Error trying to get matrix distance from mapzen", response)
# In case 4xx error we return empty because the error comes from
# the provided info by the user and we don't want to top the
# isolines generation
if response.status_code == requests.codes.bad_request:
return {}
elif response.status_code == 504:
# Due to some unsolved problems in the Mapzen Matrix API we're
# getting randomly 504, probably timeouts. To avoid raise an
# exception in all the jobs, for now we're going to return
# empty in that case
return {}
else:
raise ServiceException("Error trying to get matrix distance from mapzen", response)
return response.json()
# response could return with empty json
try:
return response.json()
except:
return {}

View File

@@ -55,7 +55,7 @@ class QPSService:
def retry(self, first_request_time, retry_count):
elapsed = datetime.now() - first_request_time
if elapsed.microseconds > (self._retry_timeout * 1000.0):
if elapsed.total_seconds() > self._retry_timeout:
raise TimeoutException()
# inverse qps * (1.5 ^ i) is an increased sleep time of 1.5x per

View File

@@ -2,15 +2,20 @@ import requests
import json
import re
from requests.adapters import HTTPAdapter
from exceptions import WrongParams, MalformedResult, ServiceException
from qps import qps_retry
from cartodb_services.tools import Coordinate, PolyLine
from cartodb_services.metrics import MetricsDataGatherer, Traceable
class MapzenRouting:
class MapzenRouting(Traceable):
'A Mapzen Routing wrapper for python'
PRODUCTION_ROUTING_BASE_URL = 'https://valhalla.mapzen.com/route'
READ_TIMEOUT = 60
CONNECT_TIMEOUT = 10
MAX_RETRIES=1
ACCEPTED_MODES = {
"walk": "pedestrian",
@@ -43,7 +48,12 @@ class MapzenRouting:
mode_param,
units)
request_params = self.__parse_request_parameters(json_request_params)
response = requests.get(self._url, params=request_params)
# TODO Extract HTTP client wrapper
session = requests.Session()
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
response = session.get(self._url, params=request_params,
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
self.add_response_data(response, self._logger)
if response.status_code == requests.codes.ok:
return self.__parse_routing_response(response.text)
elif response.status_code == requests.codes.bad_request:

View File

@@ -19,6 +19,24 @@ def polyline_to_linestring(polyline):
return geometry
def coordinates_to_polygon(coordinates):
"""Convert a Mapzen coordinates to a PostGIS polygon"""
result_coordinates = []
for coordinate in coordinates:
result_coordinates.append("%s %s" % (coordinate[0], coordinate[1]))
wkt_coordinates = ','.join(result_coordinates)
try:
sql = "SELECT ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326)) as geom".format(wkt_coordinates)
geometry = plpy.execute(sql, 1)[0]['geom']
except BaseException as e:
plpy.warning("Can't generate POLYGON from coordinates: {0}".format(e))
geometry = None
return geometry
def country_to_iso3(country):
""" Convert country to its iso3 code """
try:

View File

@@ -1,3 +1,4 @@
from config import GeocoderConfig, IsolinesRoutingConfig, InternalGeocoderConfig, RoutingConfig, ConfigException, ObservatorySnapshotConfig, ObservatoryConfig
from quota import QuotaService
from user import UserMetricsService
from log import metrics, MetricsDataGatherer, Traceable

View File

@@ -15,6 +15,7 @@ class ServiceConfig(object):
self._username = username
self._orgname = orgname
self._db_config = ServicesDBConfig(db_conn, username, orgname)
self._metrics_log_path = self.__get_metrics_log_path()
self._environment = self._db_config._server_environment
if redis_connection:
self._redis_config = ServicesRedisConfig(redis_connection).build(
@@ -38,9 +39,28 @@ class ServiceConfig(object):
def environment(self):
return self._environment
@property
def metrics_log_path(self):
return self._metrics_log_path
def _get_effective_monthly_quota(self, quota_key, default=0):
quota_from_redis = self._redis_config.get(quota_key, None)
if quota_from_redis and quota_from_redis <> '':
return int(quota_from_redis)
else:
return default
def __get_metrics_log_path(self):
if self.METRICS_LOG_KEY:
return self._db_config.logger_config.get(self.METRICS_LOG_KEY, None)
else:
return None
class DataObservatoryConfig(ServiceConfig):
METRICS_LOG_KEY = 'do_log_path'
def __init__(self, redis_connection, db_conn, username, orgname=None):
super(DataObservatoryConfig, self).__init__(redis_connection, db_conn,
username, orgname)
@@ -61,6 +81,10 @@ class DataObservatoryConfig(ServiceConfig):
def connection_str(self):
return self._connection_str
@property
def provider(self):
return 'data observatory'
class ObservatorySnapshotConfig(DataObservatoryConfig):
@@ -76,9 +100,7 @@ class ObservatorySnapshotConfig(DataObservatoryConfig):
self._soft_limit = True
else:
self._soft_limit = False
self._monthly_quota = 0
if self.QUOTA_KEY in self._redis_config:
self._monthly_quota = float(self._redis_config[self.QUOTA_KEY])
self._monthly_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
self._connection_str = self._db_config.data_observatory_connection_str
@property
@@ -100,9 +122,7 @@ class ObservatoryConfig(DataObservatoryConfig):
self._soft_limit = True
else:
self._soft_limit = False
self._monthly_quota = 0
if self.QUOTA_KEY in self._redis_config:
self._monthly_quota = float(self._redis_config[self.QUOTA_KEY])
self._monthly_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
self._connection_str = self._db_config.data_observatory_connection_str
@property
@@ -118,6 +138,7 @@ class RoutingConfig(ServiceConfig):
DEFAULT_PROVIDER = 'mapzen'
QUOTA_KEY = 'mapzen_routing_quota'
SOFT_LIMIT_KEY = 'soft_mapzen_routing_limit'
METRICS_LOG_KEY = 'routing_log_path'
def __init__(self, redis_connection, db_conn, username, orgname=None):
super(RoutingConfig, self).__init__(redis_connection, db_conn,
@@ -135,6 +156,10 @@ class RoutingConfig(ServiceConfig):
if self._routing_provider == self.MAPZEN_PROVIDER:
return 'routing_mapzen'
@property
def provider(self):
return self._routing_provider
@property
def mapzen_api_key(self):
return self._mapzen_api_key
@@ -151,16 +176,8 @@ class RoutingConfig(ServiceConfig):
def soft_limit(self):
return self._soft_limit
def _set_monthly_quota(self):
self._monthly_quota = self._get_effective_monthly_quota()
def _get_effective_monthly_quota(self):
quota_from_redis = self._redis_config.get(self.QUOTA_KEY)
if quota_from_redis and quota_from_redis <> '':
return int(quota_from_redis)
else:
return self._db_config.mapzen_routing_monthly_quota
self._monthly_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
def _set_soft_limit(self):
if self.SOFT_LIMIT_KEY in self._redis_config and self._redis_config[self.SOFT_LIMIT_KEY].lower() == 'true':
@@ -169,7 +186,6 @@ class RoutingConfig(ServiceConfig):
self._soft_limit = False
class IsolinesRoutingConfig(ServiceConfig):
ISOLINES_CONFIG_KEYS = ['here_isolines_quota', 'soft_here_isolines_limit',
@@ -183,7 +199,8 @@ class IsolinesRoutingConfig(ServiceConfig):
GEOCODER_PROVIDER_KEY = 'geocoder_provider'
MAPZEN_PROVIDER = 'mapzen'
HEREMAPS_PROVIDER = 'heremaps'
DEFAULT_PROVIDER = 'heremaps'
DEFAULT_PROVIDER = 'mapzen'
METRICS_LOG_KEY = 'isolines_log_path'
def __init__(self, redis_connection, db_conn, username, orgname=None):
super(IsolinesRoutingConfig, self).__init__(redis_connection, db_conn,
@@ -197,18 +214,16 @@ class IsolinesRoutingConfig(ServiceConfig):
self._isolines_provider = self.DEFAULT_PROVIDER
self._geocoder_provider = filtered_config[self.GEOCODER_PROVIDER_KEY].lower()
self._period_end_date = date_parse(filtered_config[self.PERIOD_END_DATE])
self._isolines_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
if filtered_config[self.SOFT_LIMIT_KEY].lower() == 'true':
self._soft_isolines_limit = True
else:
self._soft_isolines_limit = False
if self._isolines_provider == self.HEREMAPS_PROVIDER:
self._isolines_quota = float(filtered_config[self.QUOTA_KEY])
self._heremaps_app_id = db_config.heremaps_isolines_app_id
self._heremaps_app_code = db_config.heremaps_isolines_app_code
if filtered_config[self.SOFT_LIMIT_KEY].lower() == 'true':
self._soft_isolines_limit = True
else:
self._soft_isolines_limit = False
elif self._isolines_provider == self.MAPZEN_PROVIDER:
self._mapzen_matrix_api_key = self._db_config.mapzen_matrix_api_key
self._isolines_quota = self._db_config.mapzen_matrix_monthly_quota
self._soft_isolines_limit = False
@property
def service_type(self):
@@ -260,11 +275,12 @@ class IsolinesRoutingConfig(ServiceConfig):
class InternalGeocoderConfig(ServiceConfig):
METRICS_LOG_KEY = 'geocoder_log_path'
def __init__(self, redis_connection, db_conn, username, orgname=None):
# For now, internal geocoder doesn't use the redis config
super(InternalGeocoderConfig, self).__init__(None, db_conn,
username, orgname)
self._log_path = self._db_config.geocoder_log_path
@property
def service_type(self):
@@ -283,8 +299,8 @@ class InternalGeocoderConfig(ServiceConfig):
return None
@property
def log_path(self):
return self._log_path
def provider(self):
return 'internal'
class GeocoderConfig(ServiceConfig):
@@ -310,6 +326,7 @@ class GeocoderConfig(ServiceConfig):
ORGNAME_KEY = 'orgname'
PERIOD_END_DATE = 'period_end_date'
DEFAULT_PROVIDER = 'mapzen'
METRICS_LOG_KEY = 'geocoder_log_path'
def __init__(self, redis_connection, db_conn, username, orgname=None, forced_provider=None):
super(GeocoderConfig, self).__init__(redis_connection, db_conn,
@@ -339,9 +356,10 @@ class GeocoderConfig(ServiceConfig):
self._geocoder_provider = filtered_config[self.GEOCODER_PROVIDER].lower()
else:
self._geocoder_provider = self.DEFAULT_PROVIDER
self._geocoding_quota = float(filtered_config[self.QUOTA_KEY])
self._geocoding_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
self._period_end_date = date_parse(filtered_config[self.PERIOD_END_DATE])
self._log_path = db_config.geocoder_log_path
if filtered_config[self.SOFT_LIMIT_KEY].lower() == 'true':
self._soft_geocoding_limit = True
else:
@@ -356,7 +374,6 @@ class GeocoderConfig(ServiceConfig):
self._cost_per_hit = 0
elif self._geocoder_provider == self.MAPZEN_GEOCODER:
self._mapzen_api_key = db_config.mapzen_geocoder_api_key
self._geocoding_quota = db_config.mapzen_geocoder_monthly_quota
self._cost_per_hit = 0
@property
@@ -424,8 +441,8 @@ class GeocoderConfig(ServiceConfig):
return self._cost_per_hit
@property
def log_path(self):
return self._log_path
def provider(self):
return self._geocoder_provider
class ServicesDBConfig:
@@ -440,7 +457,6 @@ class ServicesDBConfig:
self._get_server_config()
self._get_here_config()
self._get_mapzen_config()
self._get_logger_config()
self._get_data_observatory_config()
def _get_server_config(self):
@@ -493,13 +509,6 @@ class ServicesDBConfig:
else:
self._data_observatory_connection_str = do_conf['connection']['production']
def _get_logger_config(self):
logger_conf_json = self._get_conf('logger_conf')
if not logger_conf_json:
raise ConfigException('Logger configuration missing')
else:
logger_conf = json.loads(logger_conf_json)
self._geocoder_log_path = logger_conf['geocoder_log_path']
def _get_conf(self, key):
try:
@@ -507,7 +516,7 @@ class ServicesDBConfig:
conf = self._db_conn.execute(sql, 1)
return conf[0]['conf']
except Exception as e:
raise ConfigException("Malformed config for {0}: {1}".format(key, e))
raise ConfigException("Error trying to get config for {0}: {1}".format(key, e))
@property
def server_environment(self):
@@ -557,14 +566,18 @@ class ServicesDBConfig:
def mapzen_geocoder_monthly_quota(self):
return self._mapzen_geocoder_quota
@property
def geocoder_log_path(self):
return self._geocoder_log_path
@property
def data_observatory_connection_str(self):
return self._data_observatory_connection_str
@property
def logger_config(self):
logger_conf_json = self._get_conf('logger_conf')
if not logger_conf_json:
raise ConfigException('Logger configuration missing')
else:
return json.loads(logger_conf_json)
class ServicesRedisConfig:

View File

@@ -1,15 +1,130 @@
from datetime import datetime
import abc
import json
import re
import time
import uuid
import plpy
from datetime import datetime
from contextlib import contextmanager
from urlparse import urlparse
class MetricsLoggerFactory:
@contextmanager
def metrics(function, service_config, logger=None):
try:
start_time = time.time()
yield
finally:
end_time = time.time()
MetricsDataGatherer.add('uuid', str(uuid.uuid1()))
MetricsDataGatherer.add('function_name', function)
MetricsDataGatherer.add('function_execution_time', (end_time - start_time))
metrics_logger = MetricsServiceLoggerFactory.build(service_config,
logger)
if metrics_logger:
data = MetricsDataGatherer.get()
metrics_logger.log(data)
MetricsDataGatherer.clean()
class Traceable:
"""
Module to add metrics traceability, for example to get response object
in order to add to the metrics dump
"""
def add_response_data(self, response, logger=None):
try:
response_data = {}
response_data['type'] = "request"
response_data['date'] = datetime.now().isoformat()
response_data['elapsed_time'] = response.elapsed.total_seconds()
response_data['code'] = response.status_code
response_data['message'] = response.reason
response_data['url'] = self._parse_response_url(response.url)
stored_data = MetricsDataGatherer.get_element('response')
if stored_data:
stored_data.append(response_data)
else:
MetricsDataGatherer.add('response', [response_data])
except BaseException as e:
# We don't want to stop the job for some error processing response
if logger:
logger.error("Error trying to process response metricd data",
exception=e)
def _parse_response_url(self, url):
u = urlparse(url)
return "{0}://{1}{2}".format(u.scheme, u.netloc, u.path)
class MetricsDataGatherer:
"""
Metrics gatherer used as a singleton. The intend is to use it as a global
storage for the metrics along the function request.
"""
class __MetricsDataGatherer:
def __init__(self):
self.data = {}
def add(self, key, value):
self.data[key] = value
def get(self):
return self.data
def get_element(self, key):
return self.data.get(key, None)
def clean(self):
self.data = {}
# We use pgbouncer so we need to have multiples instances per request id
__instance = {}
@classmethod
def build(self, service_config):
if re.match('geocoder_*', service_config.service_type):
return MetricsGeocoderLogger(service_config)
def add(self, key, value):
MetricsDataGatherer.instance().add(key, value)
@classmethod
def get(self):
return MetricsDataGatherer.instance().get()
@classmethod
def get_element(self, key):
return MetricsDataGatherer.instance().get_element(key)
@classmethod
def clean(self):
MetricsDataGatherer.instance().clean()
@classmethod
def instance(self):
txid = MetricsDataGatherer._get_txid()
if txid not in MetricsDataGatherer.__instance:
MetricsDataGatherer.__instance[txid] = MetricsDataGatherer.__MetricsDataGatherer()
return MetricsDataGatherer.__instance[txid]
@classmethod
def _get_txid(self):
result = plpy.execute('select txid_current() as txid')
return result[0]['txid']
class MetricsServiceLoggerFactory:
@classmethod
def build(self, service_config, logger=None):
if re.search('^geocoder_*', service_config.service_type):
return MetricsGeocoderLogger(service_config, logger)
elif re.search('^routing_*', service_config.service_type):
return MetricsGenericLogger(service_config, logger)
elif re.search('_isolines$', service_config.service_type):
return MetricsIsolinesLogger(service_config, logger)
elif re.search('^obs_*', service_config.service_type):
return MetricsGenericLogger(service_config, logger)
else:
return None
@@ -17,58 +132,119 @@ class MetricsLoggerFactory:
class MetricsLogger(object):
__metaclass__ = abc.ABCMeta
def __init__(self, file_path):
self._file_path = file_path
def __init__(self, service_config, logger):
self._service_config = service_config
self._logger = logger
def dump_to_file(self, data):
with open(self._file_path, 'a') as logfile:
json.dump(data, logfile)
logfile.write('\n')
try:
log_path = self.service_config.metrics_log_path
response_data = data.pop('response', [])
uuid = data.get('uuid')
if log_path:
with open(log_path, 'a') as logfile:
self._dump_response_to_file(uuid, response_data, logfile)
json.dump(data, logfile)
logfile.write('\n')
except BaseException as e:
self._logger("Error dumping metrics to file {0}".format(log_path),
exception=e)
def collect_data(self, data):
return {
"uuid": data.get('uuid', uuid.uuid1()),
"type": 'function',
"function_name": data.get('function_name', None),
"function_execution_time": data.get('function_execution_time',
None),
"service": self._service_config.service_type,
"processable_rows": 1,
"success": data.get('success', False),
"successful_rows": data.get('successful_rows', 0),
"failed_rows": data.get('failed_rows', 0),
"empty_rows": data.get('empty_rows', 0),
"created_at": datetime.now().isoformat(),
"provider": self._service_config.provider,
"username": self._service_config.username,
"organization": self._service_config.organization,
"response": data.get('response', [])
}
def _dump_response_to_file(self, uuid, response_data, log_file):
for r in response_data:
r['uuid'] = uuid
json.dump(r, log_file)
log_file.write('\n')
@property
def service_config(self):
return self._service_config
@abc.abstractproperty
def log(self, **data):
def log(self, data):
raise NotImplementedError('log method must be defined')
class MetricsGeocoderLogger(MetricsLogger):
def __init__(self, service_config):
super(MetricsGeocoderLogger, self).__init__(service_config.log_path)
self._service_config = service_config
def __init__(self, service_config, logger):
super(MetricsGeocoderLogger, self).__init__(service_config, logger)
def log(self, **data):
dump_data = self._dump_data(**data)
def log(self, data):
dump_data = self.collect_data(data)
self.dump_to_file(dump_data)
def _dump_data(self, **data):
if data['success']:
cost = self._service_config.cost_per_hit
failed_rows = 0
successful_rows = 1
def collect_data(self, data):
dump_data = super(MetricsGeocoderLogger, self).collect_data(data)
if data.get('success', False):
cost = self.service_config.cost_per_hit
else:
cost = 0
failed_rows = 1
successful_rows = 0
if self._service_config.is_high_resolution:
if self.service_config.is_high_resolution:
kind = 'high-resolution'
else:
kind = 'internal'
return {
dump_data.update({
"batched": False,
"cache_hits": 0, # Always 0 because no cache involved
# https://github.com/CartoDB/cartodb/blob/master/app/models/geocoding.rb#L208-L211
"cost": cost,
"created_at": datetime.now().isoformat(),
"failed_rows": failed_rows,
"geocoder_type": self._service_config.service_type,
"geocoder_type": self.service_config.service_type,
"kind": kind,
"processable_rows": 1,
"processed_rows": successful_rows,
"real_rows": successful_rows,
"success": data['success'],
"successful_rows": successful_rows,
"username": self._service_config.username,
"organization": self._service_config.organization
}
"processed_rows": data.get('successful_rows', 0),
"real_rows": data.get('successful_rows', 0),
})
return dump_data
class MetricsGenericLogger(MetricsLogger):
def __init__(self, service_config, logger):
super(MetricsGenericLogger, self).__init__(service_config, logger)
def log(self, data):
dump_data = self.collect_data(data)
self.dump_to_file(dump_data)
def collect_data(self, data):
return super(MetricsGenericLogger, self).collect_data(data)
class MetricsIsolinesLogger(MetricsLogger):
def __init__(self, service_config, logger):
super(MetricsIsolinesLogger, self).__init__(service_config, logger)
def log(self, data):
dump_data = self.collect_data(data)
self.dump_to_file(dump_data)
def collect_data(self, data):
dump_data = super(MetricsIsolinesLogger, self).collect_data(data)
dump_data.update({
"isolines_generated": data.get('isolines_generated', 0)
})
return dump_data

View File

@@ -1,5 +1,5 @@
from user import UserMetricsService
from log import MetricsLoggerFactory
from log import MetricsDataGatherer
from datetime import date
import re
@@ -14,7 +14,6 @@ class QuotaService:
redis_connection)
self._user_service = UserMetricsService(self._user_service_config,
redis_connection)
self._metrics_logger = MetricsLoggerFactory.build(user_service_config)
def check_user_quota(self):
return self._quota_checker.check()
@@ -46,13 +45,19 @@ class QuotaService:
self._user_service.increment_service_use(
self._user_service_config.service_type, "isolines_generated",
amount=amount)
MetricsDataGatherer.add('isolines_generated', amount)
def _log_service_process(self, event):
if self._metrics_logger:
if event is 'success' or event is 'empty':
self._metrics_logger.log(success=True)
elif event is 'empty':
self._metrics_logger.log(success=False)
if event is 'success':
MetricsDataGatherer.add('success', True)
MetricsDataGatherer.add('successful_rows', 1)
elif event is 'empty':
MetricsDataGatherer.add('success', True)
MetricsDataGatherer.add('successful_rows', 1)
MetricsDataGatherer.add('empty_rows', 1)
elif event is 'fail':
MetricsDataGatherer.add('success', False)
MetricsDataGatherer.add('failed_rows', 1)
class QuotaChecker:

View File

@@ -1,5 +1,17 @@
from datetime import date, timedelta
from dateutil.relativedelta import relativedelta
from calendar import monthrange
def last_day_of_month(year, month):
"""last valid day of a month"""
return monthrange(year, month)[1]
def latest_valid_date(year, month, day):
"""latest date not later than the day specified"""
valid_day = min(day, last_day_of_month(year, month))
return date(year, month, valid_day)
class UserMetricsService:
@@ -8,7 +20,9 @@ class UserMetricsService:
SERVICE_GEOCODER_NOKIA = 'geocoder_here'
SERVICE_GEOCODER_CACHE = 'geocoder_cache'
SERVICE_HERE_ISOLINES = 'here_isolines'
SERVICE_MAPZEN_ISOLINES = 'mapzen_isolines'
SERVICE_MAPZEN_ROUTING = 'routing_mapzen'
SERVICE_OBSERVATORY = 'obs_general'
DAY_OF_MONTH_ZERO_PADDED = '%d'
def __init__(self, user_geocoder_config, redis_connection):
@@ -20,8 +34,12 @@ class UserMetricsService:
def used_quota(self, service_type, date):
if service_type == self.SERVICE_HERE_ISOLINES:
return self.__used_isolines_quota(service_type, date)
if service_type == self.SERVICE_MAPZEN_ISOLINES:
return self.__used_isolines_quota(service_type, date)
elif service_type == self.SERVICE_MAPZEN_ROUTING:
return self.__used_routing_quota(service_type, date)
elif service_type == self.SERVICE_OBSERVATORY:
return self.__used_observatory_quota(service_type, date)
else:
return self.__used_geocoding_quota(service_type, date)
@@ -72,6 +90,19 @@ class UserMetricsService:
return current_use
def __used_observatory_quota(self, service_type, date):
date_from, date_to = self.__current_billing_cycle()
current_use = 0
success_responses = self.get_metrics(service_type,
'success_responses', date_from,
date_to)
empty_responses = self.get_metrics(service_type,
'empty_responses', date_from,
date_to)
current_use += (success_responses + empty_responses)
return current_use
def increment_service_use(self, service_type, metric, date=date.today(),
amount=1):
""" Increment the services uses in monthly and daily basis"""
@@ -88,11 +119,11 @@ class UserMetricsService:
redis_prefix = self.__parse_redis_prefix(key_prefix, entity_name,
service, metric, date)
score = self._redis_connection.zscore(redis_prefix, date.day)
aggregated_metric += score if score else 0
aggregated_metric += int(score) if score else 0
zero_padded_day = date.strftime(self.DAY_OF_MONTH_ZERO_PADDED)
if str(date.day) != zero_padded_day:
score = self._redis_connection.zscore(redis_prefix, zero_padded_day)
aggregated_metric += score if score else 0
aggregated_metric += int(score) if score else 0
return aggregated_metric
@@ -127,9 +158,9 @@ class UserMetricsService:
today = date.today()
if end_period_day > today.day:
temp_date = today + relativedelta(months=-1)
date_from = date(temp_date.year, temp_date.month, end_period_day)
date_from = latest_valid_date(temp_date.year, temp_date.month, end_period_day)
else:
date_from = date(today.year, today.month, end_period_day)
date_from = latest_valid_date(today.year, today.month, end_period_day)
return date_from, today

View File

@@ -67,6 +67,7 @@ class MapzenGeocoderConfig(object):
@property
def username(self):
return self._username
@property
def organization(self):
return self._organization
@@ -86,21 +87,18 @@ class MapzenGeocoderConfigBuilder(object):
self._username = username
self._orgname = orgname
def get(self):
mapzen_server_conf = self._server_conf.get('mapzen_conf')
geocoding_quota = mapzen_server_conf['geocoder']['monthly_quota']
mapzen_api_key = mapzen_server_conf['geocoder']['api_key']
soft_geocoding_limit = self._user_conf.get('soft_geocoding_limit')
cost_per_hit=0
geocoding_quota = self._get_quota(mapzen_server_conf)
soft_geocoding_limit = self._user_conf.get('soft_geocoding_limit').lower() == 'true'
cost_per_hit = 0
period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date')
period_end_date = date_parse(period_end_date_str)
logger_conf = self._server_conf.get('logger_conf')
log_path = logger_conf['geocoder_log_path']
log_path = logger_conf.get('geocoder_log_path', None)
return MapzenGeocoderConfig(geocoding_quota,
soft_geocoding_limit,
@@ -110,3 +108,10 @@ class MapzenGeocoderConfigBuilder(object):
mapzen_api_key,
self._username,
self._orgname)
def _get_quota(self, mapzen_server_conf):
geocoding_quota = self._org_conf.get('geocoding_quota') or self._user_conf.get('geocoding_quota')
if geocoding_quota is '':
return 0
return int(geocoding_quota)

Some files were not shown because too many files have changed in this diff Show More