Compare commits
293 Commits
0.22.0-cli
...
0.32.0-ser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f86558c30b | ||
|
|
0bd2fbf80a | ||
|
|
887fc15915 | ||
|
|
5c09a2eb29 | ||
|
|
b0c1948c14 | ||
|
|
0c5e9da028 | ||
|
|
f534da906c | ||
|
|
5e34faefe5 | ||
|
|
5e8dbaf239 | ||
|
|
b90d402fa9 | ||
|
|
d060bd8229 | ||
|
|
c104f6f34b | ||
|
|
e9ed3bca18 | ||
|
|
e2762a6e03 | ||
|
|
8cb9e123b1 | ||
|
|
e82346e7f6 | ||
|
|
080de34163 | ||
|
|
0a92ae1445 | ||
|
|
0b635377ef | ||
|
|
f2197d4b2a | ||
|
|
6e78da55b2 | ||
|
|
4123a4c442 | ||
|
|
dbb4f9204a | ||
|
|
67fee1cce8 | ||
|
|
b779742585 | ||
|
|
da78b0bc65 | ||
|
|
d46d51c3bb | ||
|
|
0b2ee85c11 | ||
|
|
825e3b7ee8 | ||
|
|
2af9204542 | ||
|
|
34e622b809 | ||
|
|
531ad28158 | ||
|
|
286a75fa8e | ||
|
|
a6c5c21131 | ||
|
|
f6b7c13dde | ||
|
|
1ffe3658fe | ||
|
|
8e430ce1c1 | ||
|
|
8ebd22bc26 | ||
|
|
0ff950d01e | ||
|
|
fed8894c33 | ||
|
|
cce5f92312 | ||
|
|
40ace9cfaa | ||
|
|
f618e4aec3 | ||
|
|
ae84122c3d | ||
|
|
b8475bac30 | ||
|
|
bf8b76b5fe | ||
|
|
31afc82b56 | ||
|
|
5be43e15c0 | ||
|
|
6da70fd8ea | ||
|
|
d00a48f16e | ||
|
|
91012ea62d | ||
|
|
23e3de9da5 | ||
|
|
6c89ca8d70 | ||
|
|
3c07133912 | ||
|
|
5b46c1527e | ||
|
|
89e9bf1ed6 | ||
|
|
ff6cbd1d5b | ||
|
|
8968f0e6ec | ||
|
|
44744de73d | ||
|
|
754c364d22 | ||
|
|
9856adb7ce | ||
|
|
e416a8a641 | ||
|
|
fc610313bf | ||
|
|
18e2349713 | ||
|
|
e884b1d1f4 | ||
|
|
45b8fc4ecf | ||
|
|
379257b4b4 | ||
|
|
8fe9903e7a | ||
|
|
d0b04a97b8 | ||
|
|
a931086e29 | ||
|
|
8f4249ee24 | ||
|
|
71b87834b3 | ||
|
|
9c90c539f8 | ||
|
|
ed828c3b89 | ||
|
|
675ef72e30 | ||
|
|
c13d29e4c2 | ||
|
|
d5e47e39ab | ||
|
|
c2a207b1cd | ||
|
|
e280444479 | ||
|
|
9b64d91998 | ||
|
|
91d93bef79 | ||
|
|
bbbf70f3ac | ||
|
|
4d2abc7667 | ||
|
|
58d70e252f | ||
|
|
e85f43f1d1 | ||
|
|
f3f2b213e7 | ||
|
|
34fc6439d2 | ||
|
|
3f08d37ef7 | ||
|
|
be446c1bf2 | ||
|
|
5251534283 | ||
|
|
2687f0c73a | ||
|
|
6b117e26b1 | ||
|
|
9c428dbf31 | ||
|
|
20a610d1d8 | ||
|
|
4b599ecf78 | ||
|
|
3a240bf6ad | ||
|
|
7577936c33 | ||
|
|
193513bfea | ||
|
|
c3c28dfd5e | ||
|
|
e5d2182da3 | ||
|
|
33f23e0902 | ||
|
|
94aeceb894 | ||
|
|
e21d3e2e70 | ||
|
|
adde2d3a46 | ||
|
|
6143c04c82 | ||
|
|
3b121c8793 | ||
|
|
e70aefba1d | ||
|
|
423fe42007 | ||
|
|
5e141e3a10 | ||
|
|
50aa537a7a | ||
|
|
e25e2c26a0 | ||
|
|
8025f657b8 | ||
|
|
2a47000f32 | ||
|
|
53e9ad4d2e | ||
|
|
ea5818f08f | ||
|
|
2f8edbe5ce | ||
|
|
552a7d4886 | ||
|
|
a34da0adb5 | ||
|
|
ab5ef64e83 | ||
|
|
f0cef02dfc | ||
|
|
e78063ae75 | ||
|
|
d66804b93d | ||
|
|
6572891036 | ||
|
|
59940ea994 | ||
|
|
b9da6c9ec5 | ||
|
|
ace7683ffe | ||
|
|
6017b53ea0 | ||
|
|
e15c6127d3 | ||
|
|
4bd8726720 | ||
|
|
5d20d0bdf5 | ||
|
|
db5ead6f98 | ||
|
|
44fae489a3 | ||
|
|
71c93fe13a | ||
|
|
d9c569881a | ||
|
|
244d579f6f | ||
|
|
c90859e58b | ||
|
|
12eecc271d | ||
|
|
f216b6d922 | ||
|
|
573a304bd2 | ||
|
|
f5cbc195cc | ||
|
|
e324afd77f | ||
|
|
0196292093 | ||
|
|
f652a52a8d | ||
|
|
1c38b33501 | ||
|
|
59751d7c9c | ||
|
|
ffa1080277 | ||
|
|
b279fafbc5 | ||
|
|
07ed2a4112 | ||
|
|
da7d43cc08 | ||
|
|
39800122b2 | ||
|
|
12ac2c269d | ||
|
|
74c0bb6f26 | ||
|
|
c9d0f0447f | ||
|
|
596189185f | ||
|
|
35f743164e | ||
|
|
4308b5f351 | ||
|
|
9fb04fdc24 | ||
|
|
a2fd0bf142 | ||
|
|
6534b12606 | ||
|
|
8d9c3a4bf7 | ||
|
|
ad46de1156 | ||
|
|
97f1611d62 | ||
|
|
bc4c9fea33 | ||
|
|
177c19f935 | ||
|
|
e110ab4cc3 | ||
|
|
e646000f24 | ||
|
|
05e2cc981e | ||
|
|
cbc19b869c | ||
|
|
199788748b | ||
|
|
e3f23adfdd | ||
|
|
39dabffb85 | ||
|
|
03e1d1ca61 | ||
|
|
90d8d207eb | ||
|
|
c14fb057d3 | ||
|
|
9e247685b8 | ||
|
|
1fdb4d3b3a | ||
|
|
029541f298 | ||
|
|
45d9edbba6 | ||
|
|
39c54f3e0c | ||
|
|
54e40645fa | ||
|
|
a86b8e86f9 | ||
|
|
8674dabeb2 | ||
|
|
080a386b8f | ||
|
|
972aba6cfb | ||
|
|
9b43e8a92e | ||
|
|
4e311aef47 | ||
|
|
b65d003742 | ||
|
|
b171951bc7 | ||
|
|
462773a138 | ||
|
|
fad2f25183 | ||
|
|
2f54ef7e4e | ||
|
|
ab4d77edf2 | ||
|
|
0b12f26f47 | ||
|
|
a116aba660 | ||
|
|
29d5a332b6 | ||
|
|
b2825f46a4 | ||
|
|
a791d02dcc | ||
|
|
e2612645c3 | ||
|
|
c5fed2cc80 | ||
|
|
a1f339376e | ||
|
|
019df2b4e0 | ||
|
|
9e67beab3d | ||
|
|
5c7d1e9ac1 | ||
|
|
6e54507b5a | ||
|
|
14925ea448 | ||
|
|
26e0a5e00f | ||
|
|
a99e0cb513 | ||
|
|
1e4fef5868 | ||
|
|
3973483af2 | ||
|
|
88edad9414 | ||
|
|
88ad551e4a | ||
|
|
94eaf84f91 | ||
|
|
0df0b0d49c | ||
|
|
b260c29b8c | ||
|
|
da8aa5a8c0 | ||
|
|
423534068a | ||
|
|
6f508b550d | ||
|
|
1462f87d97 | ||
|
|
6ae8aa45fd | ||
|
|
02cb4862f9 | ||
|
|
07f00cc0ae | ||
|
|
544e0fa763 | ||
|
|
2bbd6bac91 | ||
|
|
2f8dbbb5dc | ||
|
|
3484cce88b | ||
|
|
56c90cc541 | ||
|
|
3583cc6f47 | ||
|
|
850dc09a4f | ||
|
|
876bae6b56 | ||
|
|
8f30359cc7 | ||
|
|
7be27969fa | ||
|
|
502039796f | ||
|
|
e0b1632fa8 | ||
|
|
51bf6c2a43 | ||
|
|
5f9185ee6b | ||
|
|
08e21e3999 | ||
|
|
212cbda9a0 | ||
|
|
05718ce58c | ||
|
|
fed444ff6c | ||
|
|
d1c8f8ced0 | ||
|
|
96d2bf6218 | ||
|
|
b4dc616590 | ||
|
|
4f907053f5 | ||
|
|
1a2785dff4 | ||
|
|
d442fab9da | ||
|
|
236837ebb6 | ||
|
|
6edad7b810 | ||
|
|
7d8cc4ae87 | ||
|
|
41916eed18 | ||
|
|
9921f0f394 | ||
|
|
72b99a1729 | ||
|
|
6c53846e33 | ||
|
|
5781f78c7f | ||
|
|
8127314965 | ||
|
|
9c1ec1ddde | ||
|
|
d1d8713f05 | ||
|
|
0ed477d264 | ||
|
|
42abfd962c | ||
|
|
61e8273a47 | ||
|
|
6339623ad9 | ||
|
|
ae32f91c7c | ||
|
|
a02a634e76 | ||
|
|
7dc87ad38e | ||
|
|
af0125197d | ||
|
|
b10f48166d | ||
|
|
051453898e | ||
|
|
6047300259 | ||
|
|
b282c7db5b | ||
|
|
84749a2631 | ||
|
|
c0cc5fe6a7 | ||
|
|
7d99ede28d | ||
|
|
cd5dba920e | ||
|
|
6d978deb16 | ||
|
|
d3e01b4d53 | ||
|
|
dd6ad0119c | ||
|
|
3bbb3c6bcc | ||
|
|
fa3f2fbc3a | ||
|
|
dc5dbe8c0a | ||
|
|
e7c0628751 | ||
|
|
7775d2373d | ||
|
|
51d97228dc | ||
|
|
cc34a8b19b | ||
|
|
801c5a3cee | ||
|
|
941af522ae | ||
|
|
bb86f080fc | ||
|
|
15340fedad | ||
|
|
c46174210d | ||
|
|
af07def7fc | ||
|
|
bc9dbdbb72 | ||
|
|
dabd596271 | ||
|
|
8c0af7d51d | ||
|
|
b16f7e6ed5 | ||
|
|
9b8045f2ed |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ cartodb_services.egg-info/
|
||||
build/
|
||||
dist/
|
||||
.vscode/
|
||||
.idea/
|
||||
venv/
|
||||
|
||||
106
NEWS.md
106
NEWS.md
@@ -1,3 +1,109 @@
|
||||
Jul 19th, 2018
|
||||
==============
|
||||
* Version `0.25.0` of the client, `0.32.0` of the server, and `0.19.0` of the Python library.
|
||||
* Support for batch street-level geocoding.
|
||||
|
||||
May 7th, 2018
|
||||
=============
|
||||
* Version `0.24.0` of the client, `0.31.0` of the server, and `0.18.0` of the python library.
|
||||
* Support for TomTom routing, geocoding and isolines.
|
||||
|
||||
March 28th, 2018
|
||||
================
|
||||
* Version `0.30.5` of server side and `0.17.6` of the python library
|
||||
* All the returned polygons are now always MULTIPOLYGON #488
|
||||
|
||||
March 27th, 2018
|
||||
================
|
||||
* Version `0.17.5` of python library
|
||||
* Avoid reaching provider for empty geocodings (but still incrementing empty service use) #476
|
||||
|
||||
March 16th, 2018
|
||||
================
|
||||
* Version `0.30.3` of server side
|
||||
* Fix problem with invalid Mapbox isolines #483
|
||||
* Version `0.30.4` of server side
|
||||
* Added ST_CollectionExtract to ST_MakeValid for Mapbox isolines to avoid non-polygonal geometries #486
|
||||
|
||||
March 14th, 2018
|
||||
================
|
||||
* Version `0.17.4` of the python library
|
||||
* Fix bug with previous version when checking quotas #480
|
||||
* Version `0.17.3` of the python library
|
||||
* Fix bug with Mapbox routing not using the proper quota value #477
|
||||
|
||||
February 22th, 2018
|
||||
==================
|
||||
* Version `0.17.2` of the python library
|
||||
* Fix bug with Mapbox isolines not stopping at the seacoast #471
|
||||
|
||||
February 27th, 2018
|
||||
==================
|
||||
* Version `0.17.1` of the python library
|
||||
* Fix bug when the mapzen credentials are not in the db config and we keep getting them
|
||||
|
||||
February 22th, 2018
|
||||
==================
|
||||
* Version `0.17.0` of the python library
|
||||
* Change default provider to Mapbox
|
||||
* Remove the obligatory nature of the Mapzen configuration due to its deprecation as provider
|
||||
|
||||
February 13th, 2018
|
||||
==================
|
||||
* Version `0.16.7` of the python library
|
||||
* Pick the first result when Mapbox geocoder returns multiple results #462
|
||||
* Normalize input for Mapbox geocoder #462
|
||||
|
||||
February 12th, 2018
|
||||
==================
|
||||
* Version `0.16.6` of the python library
|
||||
* Using Mapbox permanent geocoder #455
|
||||
|
||||
February 5th, 2018
|
||||
==================
|
||||
* Version `0.16.5` of the python library
|
||||
* Fix displaced routing shape #443
|
||||
* Check for empty coordinates object before converting it to polygon
|
||||
* 422 errors that come from Mapbox now returns an empty result because is a bad input from the user data
|
||||
|
||||
February 2th, 2018
|
||||
==================
|
||||
* Version `0.16.4` of the python library
|
||||
* Create a QuotaExceededException instead of using a generic one
|
||||
* Version `0.30.2` of server side
|
||||
* Return empty value when the quota is exceeded and don't send the exception to external loggers
|
||||
to avoid noise
|
||||
|
||||
January 31th, 2018
|
||||
==================
|
||||
* Version `0.16.3` of the python library
|
||||
* Fix for Mapbox geocoder to handle empty requests and empty responses
|
||||
* Remove raising an exception when non parameters are passed to the HERE geocoder
|
||||
* Fix for HERE geocoder with non empty requests
|
||||
* Added more coverage to the google geocoder credentials parse logic
|
||||
|
||||
January 29th, 2018
|
||||
==================
|
||||
* Version `0.30.1` of server side
|
||||
* Fix for Mapbox geocoding function due to the iso3166 library doesn't support UTF-8 names for the countries
|
||||
* Version `0.16.2` of the python library
|
||||
* Fix for Mapbox cycling profile
|
||||
|
||||
January 18th, 2018
|
||||
==================
|
||||
* Version `0.16.1` of the python library
|
||||
* Fixed encoding problem with Mapbox geocoding (using the Mapbox Python library)
|
||||
|
||||
January 17th, 2018
|
||||
==================
|
||||
* Version `0.16.0` of the python library
|
||||
* Added Mapbox provider for routing, geocoding and isolines
|
||||
* Version `0.30.0` of the server extension
|
||||
* Added Mapbox provider for routing, geocoding and isolines
|
||||
* Fixed a bug that makes impossible to install server side if the client is already installed due a namespace problem
|
||||
* Version `0.23.0` of the client
|
||||
* Added Mapbox provider for routing, geocoding and isolines
|
||||
|
||||
December 1st, 2017
|
||||
==================
|
||||
* Version `0.29.0` of the server extension
|
||||
|
||||
45
README.md
45
README.md
@@ -38,14 +38,14 @@ Steps to deploy a new Data Services API version :
|
||||
|
||||
```
|
||||
# in dataservices-api repo root path:
|
||||
cd server/lib/python/cartodb_services && pip install -r requirements.txt && sudo pip install . --upgrade
|
||||
cd server/lib/python/cartodb_services && sudo pip install -r requirements.txt && sudo pip install . --upgrade
|
||||
```
|
||||
|
||||
- Create a database to hold all the server part and a user for it
|
||||
|
||||
```sql
|
||||
CREATE DATABASE dataservices_db ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
|
||||
CREATE USER dataservices_user;
|
||||
CREATE USER geocoder_api;
|
||||
```
|
||||
|
||||
- Install needed extensions in `dataservices_db` database
|
||||
@@ -90,19 +90,23 @@ Steps to deploy a new Data Services API version :
|
||||
```
|
||||
psql -U postgres -d dataservices_db -f src/pg/test/fixtures/load_fixtures.sql
|
||||
```
|
||||
- Give permission to execute and select to the `dataservices_user` user:
|
||||
- Give permission to execute and select to the `geocoder_api` user:
|
||||
```
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;CREATE EXTENSION IF NOT EXISTS observatory VERSION 'dev'; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA cdb_observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT USAGE ON SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT USAGE ON SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
```
|
||||
|
||||
### Server configuration
|
||||
|
||||
Configuration for the different services must be stored in the server database using `CDB_Conf_SetConf()`.
|
||||
|
||||
**All the configuration inside brackets [] is optional**
|
||||
|
||||
#### Redis configuration
|
||||
|
||||
If sentinel is used:
|
||||
@@ -158,6 +162,24 @@ SELECT CDB_Conf_SetConf(
|
||||
);
|
||||
```
|
||||
|
||||
#### Mapbox configuration
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapbox_conf',
|
||||
'{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "matrix": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### TomTom configuration
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'tomtom_conf',
|
||||
'{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Data Observatory
|
||||
|
||||
```sql
|
||||
@@ -172,10 +194,12 @@ SELECT CDB_Conf_SetConf(
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'logger_conf',
|
||||
'{"geocoder_log_path": "/tmp/geocodings.log", [ "min_log_level": "[debug|info|warning|error]", "rollbar_api_key": "SERVER_SIDE_API_KEY", "log_file_path": "LOG_FILE_PATH"]}'
|
||||
'{"geocoder_log_path": "/tmp/geocodings.log", "min_log_level": "LOG_LEVEL", "rollbar_api_key": "SERVER_SIDE_API_KEY", "log_file_path": "LOG_FILE_PATH"}'
|
||||
);
|
||||
```
|
||||
|
||||
Where `LOG_LEVEL` can be `debug`, `info`, `warning` or `error`.
|
||||
|
||||
#### Environment
|
||||
|
||||
The execution environment (development/staging/production) affects rollbar messages and other details.
|
||||
@@ -284,4 +308,7 @@ ALTER ROLE "<USER_ROLE>" SET search_path="$user", public, cartodb, cdb_dataservi
|
||||
|
||||
#### Option 2 (from builder)
|
||||
|
||||
See [the **Configuring Dataservices** documentation](http://cartodb.readthedocs.io/en/latest/operations/configure_data_services.html)
|
||||
See [the **Configuring Dataservices** documentation](http://cartodb.readthedocs.io/en/latest/operations/configure_data_services.html)
|
||||
|
||||
### Rate limits
|
||||
See [docs](https://github.com/CartoDB/dataservices-api/blob/master/doc/rate_limits.md)
|
||||
|
||||
276
client/cdb_dataservices_client--0.24.0--0.25.0.sql
Normal file
276
client/cdb_dataservices_client--0.24.0--0.25.0.sql
Normal file
@@ -0,0 +1,276 @@
|
||||
--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
|
||||
-- Taken from https://wiki.postgresql.org/wiki/Count_estimate
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) RETURNS INTEGER AS
|
||||
$func$
|
||||
DECLARE
|
||||
rec record;
|
||||
ROWS INTEGER;
|
||||
BEGIN
|
||||
FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP
|
||||
ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)');
|
||||
EXIT WHEN ROWS IS NOT NULL;
|
||||
END LOOP;
|
||||
|
||||
RETURN ROWS;
|
||||
END
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
-- Taken from https://stackoverflow.com/a/48013356/351721
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) RETURNS text[] AS $f$
|
||||
SELECT array_agg(x) || ARRAY[]::text[] FROM jsonb_array_elements_text($1) t(x);
|
||||
$f$ LANGUAGE sql IMMUTABLE;--
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.service_quota_info_batch AS (
|
||||
service cdb_dataservices_client.service_type,
|
||||
monthly_quota NUMERIC,
|
||||
used_quota NUMERIC,
|
||||
soft_limit BOOLEAN,
|
||||
provider TEXT,
|
||||
max_batch_size NUMERIC
|
||||
);
|
||||
|
||||
--
|
||||
-- Public dataservices API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point (searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding 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_bulk_geocode_street_point(username, orgname, searches);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
--
|
||||
-- Public dataservices API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch ()
|
||||
RETURNS SETOF service_quota_info_batch 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_batch(username, orgname);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
BEGIN
|
||||
SELECT csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Multipolygon,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
--
|
||||
-- Exception-safe private DataServices API function
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe (searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding 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.__cdb_bulk_geocode_street_point(username, orgname, searches);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
--
|
||||
-- Exception-safe private DataServices API function
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe ()
|
||||
RETURNS SETOF service_quota_info_batch 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._cdb_service_quota_info_batch(username, orgname);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server._cdb_bulk_geocode_street_point (username, orgname, searches);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch (username text, orgname text)
|
||||
RETURNS SETOF service_quota_info_batch AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_service_quota_info_batch (username, orgname);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe(searches jsonb ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch() TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe( ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point(query text, street_column text, city_column text, state_column text, country_column text, batch_size integer) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.__cdb_bulk_geocode_street_point (username text, orgname text, searches jsonb) TO publicuser;
|
||||
29
client/cdb_dataservices_client--0.25.0--0.24.0.sql
Normal file
29
client/cdb_dataservices_client--0.25.0--0.24.0.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
--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
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_count_estimate(query text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_bulk_geocode_street_point (jsonb);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_service_quota_info_batch();
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_bulk_geocode_street_point (text, text, text, text, text, integer);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.__cdb_bulk_geocode_street_point_exception_safe (jsonb);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_batch_exception_safe ();
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.__cdb_bulk_geocode_street_point (text, text, jsonb);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_service_quota_info_batch (text, text);
|
||||
|
||||
DROP TYPE IF EXISTS cdb_dataservices_client.service_quota_info_batch;
|
||||
|
||||
DROP TYPE IF EXISTS cdb_dataservices_client.geocoding;
|
||||
5218
client/cdb_dataservices_client--0.25.0.sql
Normal file
5218
client/cdb_dataservices_client--0.25.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB dataservices client API extension'
|
||||
default_version = '0.22.0'
|
||||
default_version = '0.25.0'
|
||||
requires = 'plproxy, cartodb'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_client
|
||||
|
||||
200
client/old_versions/cdb_dataservices_client--0.22.0--0.23.0.sql
Executable file
200
client/old_versions/cdb_dataservices_client--0.22.0--0.23.0.sql
Executable file
@@ -0,0 +1,200 @@
|
||||
--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.23.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.cdb_mapbox_geocode_street_point (searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
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_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone (source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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_mapbox_isochrone(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance (source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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_mapbox_isodistance(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe (searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
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._cdb_mapbox_geocode_street_point(username, orgname, searchtext, city, state_province, country) 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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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._cdb_mapbox_isochrone(username, orgname, source, mode, range, options);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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._cdb_mapbox_isodistance(username, orgname, source, mode, range, options);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_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 $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_mapbox_geocode_street_point (username, orgname, searchtext, city, state_province, country);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isochrone(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_mapbox_isodistance(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
18
client/old_versions/cdb_dataservices_client--0.23.0--0.22.0.sql
Executable file
18
client/old_versions/cdb_dataservices_client--0.23.0--0.22.0.sql
Executable file
@@ -0,0 +1,18 @@
|
||||
--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.22.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
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_geocode_street_point (searchtext text, city text, state_province text, country text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_isochrone (source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_mapbox_isodistance (source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_geocode_street_point_exception_safe (searchtext text, city text, state_province text, country text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_mapbox_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
202
client/old_versions/cdb_dataservices_client--0.23.0--0.24.0.sql
Normal file
202
client/old_versions/cdb_dataservices_client--0.23.0--0.24.0.sql
Normal file
@@ -0,0 +1,202 @@
|
||||
--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.24.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.cdb_tomtom_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
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_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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_tomtom_isochrone(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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_tomtom_isodistance(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
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._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) 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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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._cdb_tomtom_isochrone(username, orgname, source, mode, range, options);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline 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._cdb_tomtom_isodistance(username, orgname, source, mode, range, options);
|
||||
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 STABLE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_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 $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_tomtom_geocode_street_point (username, orgname, searchtext, city, state_province, country);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
4742
client/old_versions/cdb_dataservices_client--0.23.0.sql
Normal file
4742
client/old_versions/cdb_dataservices_client--0.23.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
--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.23.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
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_geocode_street_point (text, text, text, text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_isochrone (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_isodistance (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (text, text, text, text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
4960
client/old_versions/cdb_dataservices_client--0.24.0.sql
Normal file
4960
client/old_versions/cdb_dataservices_client--0.24.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -70,6 +70,13 @@
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: _cdb_bulk_geocode_street_point
|
||||
return_type: SETOF cdb_dataservices_client.geocoding
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: searches, type: jsonb } # Array of JSON objects with id, address, city, state and country fields
|
||||
|
||||
- name: cdb_here_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
@@ -86,6 +93,22 @@
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_mapbox_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: searchtext, type: text}
|
||||
- { name: city, type: text, default: 'NULL'}
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_tomtom_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: searchtext, type: text}
|
||||
- { name: city, type: text, default: 'NULL'}
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_mapzen_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
@@ -114,6 +137,26 @@
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapbox_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_tomtom_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapzen_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
@@ -124,6 +167,26 @@
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapbox_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_tomtom_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapzen_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
@@ -454,6 +517,13 @@
|
||||
params:
|
||||
- {}
|
||||
|
||||
- name: cdb_service_quota_info_batch
|
||||
return_type: SETOF service_quota_info_batch
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- {}
|
||||
|
||||
- name: cdb_enough_quota
|
||||
return_type: BOOLEAN
|
||||
params:
|
||||
|
||||
20
client/sql/05_utils.sql
Normal file
20
client/sql/05_utils.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- Taken from https://wiki.postgresql.org/wiki/Count_estimate
|
||||
CREATE FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) RETURNS INTEGER AS
|
||||
$func$
|
||||
DECLARE
|
||||
rec record;
|
||||
ROWS INTEGER;
|
||||
BEGIN
|
||||
FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP
|
||||
ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)');
|
||||
EXIT WHEN ROWS IS NOT NULL;
|
||||
END LOOP;
|
||||
|
||||
RETURN ROWS;
|
||||
END
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
-- Taken from https://stackoverflow.com/a/48013356/351721
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) RETURNS text[] AS $f$
|
||||
SELECT array_agg(x) || ARRAY[]::text[] FROM jsonb_array_elements_text($1) t(x);
|
||||
$f$ LANGUAGE sql IMMUTABLE;
|
||||
@@ -4,6 +4,12 @@ CREATE TYPE cdb_dataservices_client.isoline AS (
|
||||
the_geom geometry(Multipolygon,4326)
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
@@ -35,3 +41,12 @@ CREATE TYPE cdb_dataservices_client.service_quota_info AS (
|
||||
soft_limit BOOLEAN,
|
||||
provider TEXT
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.service_quota_info_batch AS (
|
||||
service cdb_dataservices_client.service_type,
|
||||
monthly_quota NUMERIC,
|
||||
used_quota NUMERIC,
|
||||
soft_limit BOOLEAN,
|
||||
provider TEXT,
|
||||
max_batch_size NUMERIC
|
||||
);
|
||||
|
||||
76
client/sql/21_bulk_geocoding_functions.sql
Normal file
76
client/sql/21_bulk_geocoding_functions.sql
Normal file
@@ -0,0 +1,76 @@
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
BEGIN
|
||||
SELECT csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Multipolygon,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
@@ -1,3 +1,7 @@
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure(output_table_name text, params json) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure(table_name text, output_table_name text, params json) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._OBS_PreCheck(source_query text, params JSON) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point(query text, street_column text, city_column text, state_column text, country_column text, batch_size integer) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_count_estimate(query text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_jsonb_array_casttext(jsonb) TO publicuser;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
|
||||
21
client/test/expected/21_bulk_geocoding_functions_test.out
Normal file
21
client/test/expected/21_bulk_geocoding_functions_test.out
Normal file
@@ -0,0 +1,21 @@
|
||||
\set VERBOSITY terse
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch() RENAME TO cdb_service_quota_info_batch_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch ()
|
||||
RETURNS SETOF cdb_dataservices_client.service_quota_info_batch AS $$
|
||||
SELECT 'hires_geocoder'::cdb_dataservices_client.service_type AS service, 0::NUMERIC AS monthly_quota, 0::NUMERIC AS used_quota, FALSE AS soft_limit, 'google' AS provider, 1::NUMERIC AS max_batch_size;
|
||||
$$ LANGUAGE SQL;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
|
||||
RETURNS BOOLEAN as $$
|
||||
SELECT FALSE;
|
||||
$$ LANGUAGE SQL;
|
||||
-- Test bulk size not mandatory (it will get the optimal)
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''', null, null, null, null);
|
||||
ERROR: Remaining quota: 0. Estimated cost: 1
|
||||
-- Test quota check by mocking quota 0
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
ERROR: Remaining quota: 0. Estimated cost: 1
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch;
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_enough_quota;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota_mocked (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch_mocked() RENAME TO cdb_service_quota_info_batch;
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
|
||||
26
client/test/sql/21_bulk_geocoding_functions_test.sql
Normal file
26
client/test/sql/21_bulk_geocoding_functions_test.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
\set VERBOSITY terse
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch() RENAME TO cdb_service_quota_info_batch_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch ()
|
||||
RETURNS SETOF cdb_dataservices_client.service_quota_info_batch AS $$
|
||||
SELECT 'hires_geocoder'::cdb_dataservices_client.service_type AS service, 0::NUMERIC AS monthly_quota, 0::NUMERIC AS used_quota, FALSE AS soft_limit, 'google' AS provider, 1::NUMERIC AS max_batch_size;
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
|
||||
RETURNS BOOLEAN as $$
|
||||
SELECT FALSE;
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
-- Test bulk size not mandatory (it will get the optimal)
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''', null, null, null, null);
|
||||
|
||||
-- Test quota check by mocking quota 0
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch;
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_enough_quota;
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota_mocked (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch_mocked() RENAME TO cdb_service_quota_info_batch;
|
||||
|
||||
@@ -4,7 +4,7 @@ The [geocoder](https://carto.com/data/geocoder-api/) functions allow you to matc
|
||||
|
||||
_**This service is subject to quota limitations and extra fees may apply**. View the [Quota Information](https://carto.com/docs/carto-engine/dataservices-api/quota-information/) section for details and recommendations about to quota consumption._
|
||||
|
||||
Here is an example of how to geocode a single country:
|
||||
The following example displays how to geocode a single country:
|
||||
|
||||
```bash
|
||||
https://{username}.carto.com/api/v2/sql?q=SELECT cdb_geocode_admin0_polygon('USA')&api_key={api_key}
|
||||
@@ -312,7 +312,7 @@ INSERT INTO {tablename} (the_geom) SELECT cdb_geocode_ipaddress_point('102.23.34
|
||||
|
||||
## Street-Level Geocoder
|
||||
|
||||
This function geocodes your data into a point geometry for a street address. CARTO uses several different service providers for street-level geocoding, depending on your platform. If you access CARTO on a Google Cloud Platform, [Google Maps geocoding](https://developers.google.com/maps/documentation/geocoding/intro) is applied. All other platform users are provided with [HERE geocoding services](https://developer.here.com/rest-apis/documentation/geocoder/topics/quick-start.html). Additional service providers will be implemented in the future.
|
||||
This function geocodes your data into a point geometry for a street address. CARTO uses several different service providers for street-level geocoding, depending on your platform. If you access CARTO on a Google Cloud Platform, [Google Maps geocoding](https://developers.google.com/maps/documentation/geocoding/intro) is applied. All other platform users are provided with [Mapbox geocoding services](https://www.mapbox.com/). [Contact us](mailto:sales@carto.com) if you have any specific questions or requirements about the location data service provider being used with your account._.
|
||||
|
||||
**This service is subject to quota limitations, and extra fees may apply**. View the [Quota information](https://carto.com/docs/carto-engine/dataservices-api/quota-information/) for details and recommendations about quota consumption.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ You can use the isoline functions to retrieve, for example, isochrone lines from
|
||||
https://{username}.carto.com/api/v2/sql?q=INSERT INTO {table} (the_geom) SELECT the_geom FROM cdb_isodistance('POINT(-3.70568 40.42028)'::geometry, 'car', ARRAY[300, 600, 900]::integer[])&api_key={api_key}
|
||||
```
|
||||
|
||||
The following functions provide an isoline generator service, based on time or distance. This service uses the isolines service defined for your account. The default service limits the usage of displayed polygons represented on top of [HERE](https://developer.here.com/coverage-info) maps.
|
||||
The following functions provide an isoline generator service, based on time or distance. This service uses the isolines service defined for your account. The default service limits the usage of displayed polygons represented on top of [Mapbox](https://www.mapbox.com/) maps.
|
||||
|
||||
## cdb_isodistance(_source geometry, mode text, range integer[], [options text[]]_)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ By using CARTO libraries and the SQL API, you can apply location data services t
|
||||
|
||||
**Note:** Based on your account plan, some of these data services are subject to different [quota limitations](https://carto.com/docs/carto-engine/dataservices-api/quota-information/#quota-information).
|
||||
|
||||
_The Data Services API is collaborating with [Mapzen](https://mapzen.com/), and several other geospatial service providers, in order to supply the best location data services from within our CARTO Engine._
|
||||
_In order to supply the best location data services from within our CARTO Engine, the Data Services API collaborates with [Mapbox](https://www.mapbox.com/) and several other geospatial service providers. [Contact us](mailto:sales@carto.com) if you have any specific questions or requirements about the location data service provider being used with your account._
|
||||
|
||||
## Data Services Integration
|
||||
|
||||
|
||||
@@ -59,9 +59,9 @@ 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
|
||||
isolines | 100 | 0 | f | mapbox
|
||||
hires_geocoder | 100 | 0 | f | mapbox
|
||||
routing | 50 | 0 | f | mapbox
|
||||
observatory | 0 | 0 | f | data observatory
|
||||
(4 rows)
|
||||
|
||||
@@ -100,7 +100,7 @@ Suppose you want to geocode a whole table. In order to check that you have enoug
|
||||
SELECT COUNT(*) FROM {tablename} WHERE {street_name_column} IS NOT NULL;
|
||||
```
|
||||
|
||||
Result: here's a sample result of 10000 records:
|
||||
Result: A sample result of 10000 records:
|
||||
|
||||
```sql
|
||||
count
|
||||
|
||||
@@ -14,7 +14,7 @@ Name | Type | Description | Accepted values
|
||||
`destination` | `geometry(Point)` | Destination point, in 4326 projection, which defines the end location. |
|
||||
`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`
|
||||
`units` | `text` | (Optional) Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`. This option is not supported by Mapbox provider
|
||||
|
||||
|
||||
#### Returns
|
||||
@@ -22,7 +22,7 @@ Name | Type | Description | Accepted values
|
||||
Name | Type | Description
|
||||
--- | --- | ---
|
||||
`duration` | `integer` | Duration in seconds of the calculated route.
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `kilometers` by default .
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `meters` by default .
|
||||
`the_geom` | `geometry(LineString)` | LineString geometry of the calculated route in the 4326 projection.
|
||||
|
||||
#### Examples
|
||||
@@ -49,7 +49,7 @@ 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 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`
|
||||
`units` | `text` | (Optional) Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`. This option is not supported by Mapbox provider
|
||||
|
||||
|
||||
#### Returns
|
||||
@@ -57,7 +57,7 @@ Name | Type | Description | Accepted values
|
||||
Name | Type | Description
|
||||
--- | --- | ---
|
||||
`duration` | `integer` | Duration in seconds of the calculated route.
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `kilometers` by default .
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `meters` by default .
|
||||
`the_geom` | `geometry(LineString)` | LineString geometry of the calculated route in the 4326 projection.
|
||||
|
||||
*Note*: A request to the function _cdb\_route\_with\_waypoints(waypoints geometry(Point)[], mode text, [options text[], units text])_ with only two points in the geometry array are automatically defined as origin and destination. It is equivalent to performing the following request with these two locations as parameters: _cdb\_route\_point\_to\_point(origin geometry(Point), destination geometry(Point), mode text, [options text[], units text])_.
|
||||
@@ -75,10 +75,9 @@ INSERT INTO <TABLE> (duration, length, the_geom) SELECT duration, length, shape
|
||||
UPDATE <TABLE> SET the_geom = (SELECT shape FROM cdb_route_with_waypoints(Array['POINT(-3.7109 40.4234)'::GEOMETRY, 'POINT(-3.7059 40.4203)'::geometry, 'POINT(-3.7046 40.4180)'::geometry]::geometry[], 'car', ARRAY['mode_type=shortest']::text[]))
|
||||
```
|
||||
|
||||
|
||||
### Optional routing parameters
|
||||
|
||||
The optional value parameters must be passed using the format: `option=value`.
|
||||
The optional value parameters must be passed using the format: `option=value`. Not all are available for all the routing providers
|
||||
|
||||
Name | Type | Description | Accepted values
|
||||
--- | --- | --- | ---
|
||||
|
||||
0
server/__init__.py
Normal file
0
server/__init__.py
Normal file
@@ -83,3 +83,6 @@ deploy: release_remove_parallel_deploy
|
||||
$(INSTALL_DATA) old_versions/*.sql *.sql '$(DESTDIR)$(datadir)/extension/'
|
||||
|
||||
install: deploy
|
||||
|
||||
reinstall: install
|
||||
psql -U postgres -d dataservices_db -c "drop extension if exists cdb_dataservices_server; create extension cdb_dataservices_server;"
|
||||
|
||||
148
server/extension/cdb_dataservices_server--0.31.0--0.32.0.sql
Normal file
148
server/extension/cdb_dataservices_server--0.31.0--0.32.0.sql
Normal file
@@ -0,0 +1,148 @@
|
||||
--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 '<%= version %>'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid)
|
||||
WHERE pg_type.typname = 'service_quota_info_batch'
|
||||
AND pg_namespace.nspname = 'cdb_dataservices_server') THEN
|
||||
CREATE TYPE cdb_dataservices_server.service_quota_info_batch AS (
|
||||
service cdb_dataservices_server.service_type,
|
||||
monthly_quota NUMERIC,
|
||||
used_quota NUMERIC,
|
||||
soft_limit BOOLEAN,
|
||||
provider TEXT,
|
||||
max_batch_size NUMERIC
|
||||
);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info_batch(
|
||||
username TEXT,
|
||||
orgname TEXT)
|
||||
RETURNS SETOF cdb_dataservices_server.service_quota_info_batch AS $$
|
||||
from cartodb_services.bulk_geocoders import BATCH_GEOCODER_CLASS_BY_PROVIDER
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
sqi = plpy.execute("SELECT * from cdb_dataservices_server.cdb_service_quota_info({0},{1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
|
||||
ret = []
|
||||
for info in sqi:
|
||||
if info['service'] == 'hires_geocoder':
|
||||
provider = info['provider']
|
||||
batch_geocoder_class = BATCH_GEOCODER_CLASS_BY_PROVIDER.get(provider, None)
|
||||
if batch_geocoder_class and hasattr(batch_geocoder_class, 'MAX_BATCH_SIZE'):
|
||||
max_batch_size = batch_geocoder_class.MAX_BATCH_SIZE
|
||||
else:
|
||||
max_batch_size = 1
|
||||
|
||||
info['max_batch_size'] = max_batch_size
|
||||
else:
|
||||
info['max_batch_size'] = 1
|
||||
|
||||
ret += [[info['service'], info['monthly_quota'], info['used_quota'], info['soft_limit'], info['provider'], info['max_batch_size']]]
|
||||
|
||||
return ret
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset?
|
||||
CREATE TYPE cdb_dataservices_server.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding 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_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)
|
||||
|
||||
params = {'searches': searches}
|
||||
|
||||
with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params):
|
||||
if user_geocoder_config.google_geocoder:
|
||||
provider_function = "_cdb_bulk_google_geocode_street_point";
|
||||
elif user_geocoder_config.heremaps_geocoder:
|
||||
provider_function = "_cdb_bulk_heremaps_geocode_street_point";
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
provider_function = "_cdb_bulk_tomtom_geocode_street_point";
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
provider_function = "_cdb_bulk_mapbox_geocode_street_point";
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"])
|
||||
return plpy.execute(plan, [username, orgname, searches])
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_google_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.google import GoogleMapsBulkGeocoder
|
||||
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
geocoder = GoogleMapsBulkGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.here import HereMapsBulkGeocoder
|
||||
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
geocoder = HereMapsBulkGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
from cartodb_services.tomtom import TomTomBulkGeocoder
|
||||
from cartodb_services.tools import Logger
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
geocoder = TomTomBulkGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
from cartodb_services.mapbox import MapboxBulkGeocoder
|
||||
from cartodb_services.tools import Logger
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
geocoder = MapboxBulkGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
15
server/extension/cdb_dataservices_server--0.32.0--0.31.0.sql
Normal file
15
server/extension/cdb_dataservices_server--0.32.0--0.31.0.sql
Normal 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 '<%= version %>'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_service_quota_info_batch(TEXT, TEXT);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_bulk_geocode_street_point(TEXT, TEXT, jsonb);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_bulk_google_geocode_street_point(TEXT, TEXT, jsonb);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(TEXT, TEXT, jsonb);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(TEXT, TEXT, jsonb);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(TEXT, TEXT, jsonb);
|
||||
DROP TYPE IF EXISTS cdb_dataservices_server.geocoding;
|
||||
DROP TYPE IF EXISTS cdb_dataservices_server.service_quota_info_batch;
|
||||
3801
server/extension/cdb_dataservices_server--0.32.0.sql
Normal file
3801
server/extension/cdb_dataservices_server--0.32.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB dataservices server extension'
|
||||
default_version = '0.29.0'
|
||||
default_version = '0.32.0'
|
||||
requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_server
|
||||
|
||||
@@ -0,0 +1,656 @@
|
||||
--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.30.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate Mapbox routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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_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)
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
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)
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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)
|
||||
|
||||
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']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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 $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
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)]
|
||||
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_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']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.tools import ServiceManager
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3166 = countries.get(country).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text, country_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) 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])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- mapbox isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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)]
|
||||
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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.')
|
||||
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- mapbox isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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)]
|
||||
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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, params):
|
||||
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 []
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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, params):
|
||||
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 []
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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, params):
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,400 @@
|
||||
--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.29.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_route_with_waypoints(username TEXT, orgname TEXT, waypoints geometry(Point, 4326)[], mode TEXT);
|
||||
|
||||
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_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)
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
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)
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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)
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT, state_province TEXT, country TEXT);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.tools import ServiceManager
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT, state_province TEXT, country TEXT);
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text, country_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
---- cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_geocode_namedplace(username text, orgname text, city_name text, admin1_name text, country_name text);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
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))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1}, {2})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname), plpy.quote_nullable('mapzen')))
|
||||
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)
|
||||
quota_service = QuotaService(user_geocoder_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, data_range integer[], options text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_isochrones(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, data_range integer[], options text[]);
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[]);
|
||||
|
||||
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.')
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_mapbox_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[]);
|
||||
|
||||
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 []
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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 []
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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 STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,47 @@
|
||||
--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.30.1'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
3344
server/extension/old_versions/cdb_dataservices_server--0.30.0.sql
Normal file
3344
server/extension/old_versions/cdb_dataservices_server--0.30.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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_server UPDATE TO '0.30.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3166 = countries.get(country).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,156 @@
|
||||
--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.30.2'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_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.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import QuotaExceededException
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using here maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_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.tools import LegacyServiceManager, QuotaExceededException
|
||||
from cartodb_services.google import GoogleMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using google maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using google maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
3347
server/extension/old_versions/cdb_dataservices_server--0.30.1.sql
Normal file
3347
server/extension/old_versions/cdb_dataservices_server--0.30.1.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,114 @@
|
||||
--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.30.1'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_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.tools import LegacyServiceManager
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using here maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.tools import ServiceManager
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,70 @@
|
||||
--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.30.3'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MakeValid(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])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3357
server/extension/old_versions/cdb_dataservices_server--0.30.2.sql
Normal file
3357
server/extension/old_versions/cdb_dataservices_server--0.30.2.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
--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.30.2'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) 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])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,69 @@
|
||||
--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.30.4'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.3.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.3.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
--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.30.3'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MakeValid(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])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,68 @@
|
||||
--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.30.5'" to load this file. \quit
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.4.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.4.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
--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.30.4'" to load this file. \quit
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,470 @@
|
||||
--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.31.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
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_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)
|
||||
|
||||
params = {'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
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)
|
||||
|
||||
params = {'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
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)
|
||||
|
||||
params = {'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country}
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params):
|
||||
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']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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 $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.tomtom import TomTomGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using TomTom')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = tomtom_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
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.')
|
||||
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isodistance', user_isolines_config, logger, params):
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
-- tomtom isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
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.')
|
||||
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isochrone', user_isolines_config, logger, params):
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
-- tomtom isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.5.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.5.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,182 @@
|
||||
--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.30.5'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_route_with_waypoints(TEXT, TEXT, geometry(Point, 4326)[], TEXT);
|
||||
|
||||
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_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)
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
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)
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_geocode_street_point(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_geocode_street_point(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_isochrones(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
|
||||
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.')
|
||||
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_isochrone(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
3658
server/extension/old_versions/cdb_dataservices_server--0.31.0.sql
Normal file
3658
server/extension/old_versions/cdb_dataservices_server--0.31.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,128 @@ CREATE TYPE cdb_dataservices_server.simple_route AS (
|
||||
duration integer
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate Mapbox routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
|
||||
@@ -9,6 +9,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
|
||||
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)))
|
||||
@@ -17,11 +18,25 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger):
|
||||
params = {'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
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']]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
@@ -35,6 +50,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
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)))
|
||||
@@ -43,8 +59,21 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
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']]
|
||||
params = {'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -608,7 +608,7 @@ RETURNS TABLE (
|
||||
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):
|
||||
with metrics('obs_getdata', user_obs_config, logger, params):
|
||||
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])
|
||||
@@ -667,7 +667,7 @@ RETURNS TABLE (
|
||||
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):
|
||||
with metrics('obs_getdata', user_obs_config, logger, params):
|
||||
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])
|
||||
@@ -724,7 +724,7 @@ RETURNS JSON AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('obs_getmeta', user_obs_config, logger):
|
||||
with metrics('obs_getmeta', user_obs_config, logger, params):
|
||||
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])
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_type') THEN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid)
|
||||
WHERE pg_type.typname = 'service_type'
|
||||
AND pg_namespace.nspname = 'cdb_dataservices_server') THEN
|
||||
CREATE TYPE cdb_dataservices_server.service_type AS ENUM (
|
||||
'isolines',
|
||||
'hires_geocoder',
|
||||
@@ -12,7 +14,9 @@ END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_quota_info') THEN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid)
|
||||
WHERE pg_type.typname = 'service_quota_info'
|
||||
AND pg_namespace.nspname = 'cdb_dataservices_server') THEN
|
||||
CREATE TYPE cdb_dataservices_server.service_quota_info AS (
|
||||
service cdb_dataservices_server.service_type,
|
||||
monthly_quota NUMERIC,
|
||||
@@ -23,6 +27,23 @@ BEGIN
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type inner join pg_namespace ON (pg_type.typnamespace = pg_namespace.oid)
|
||||
WHERE pg_type.typname = 'service_quota_info_batch'
|
||||
AND pg_namespace.nspname = 'cdb_dataservices_server') THEN
|
||||
CREATE TYPE cdb_dataservices_server.service_quota_info_batch AS (
|
||||
service cdb_dataservices_server.service_type,
|
||||
monthly_quota NUMERIC,
|
||||
used_quota NUMERIC,
|
||||
soft_limit BOOLEAN,
|
||||
provider TEXT,
|
||||
max_batch_size NUMERIC
|
||||
);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info(
|
||||
username TEXT,
|
||||
orgname TEXT)
|
||||
@@ -88,6 +109,35 @@ RETURNS SETOF cdb_dataservices_server.service_quota_info AS $$
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_service_quota_info_batch(
|
||||
username TEXT,
|
||||
orgname TEXT)
|
||||
RETURNS SETOF cdb_dataservices_server.service_quota_info_batch AS $$
|
||||
from cartodb_services.bulk_geocoders import BATCH_GEOCODER_CLASS_BY_PROVIDER
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
sqi = plpy.execute("SELECT * from cdb_dataservices_server.cdb_service_quota_info({0},{1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
|
||||
ret = []
|
||||
for info in sqi:
|
||||
if info['service'] == 'hires_geocoder':
|
||||
provider = info['provider']
|
||||
batch_geocoder_class = BATCH_GEOCODER_CLASS_BY_PROVIDER.get(provider, None)
|
||||
if batch_geocoder_class and hasattr(batch_geocoder_class, 'MAX_BATCH_SIZE'):
|
||||
max_batch_size = batch_geocoder_class.MAX_BATCH_SIZE
|
||||
else:
|
||||
max_batch_size = 1
|
||||
|
||||
info['max_batch_size'] = max_batch_size
|
||||
else:
|
||||
info['max_batch_size'] = 1
|
||||
|
||||
ret += [[info['service'], info['monthly_quota'], info['used_quota'], info['soft_limit'], info['provider'], info['max_batch_size']]]
|
||||
|
||||
return ret
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_enough_quota(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
-- 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
|
||||
@@ -11,7 +12,9 @@ RETURNS Geometry AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger):
|
||||
params = {'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country}
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params):
|
||||
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']
|
||||
@@ -21,6 +24,12 @@ RETURNS Geometry AS $$
|
||||
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']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
@@ -70,16 +79,43 @@ RETURNS Geometry AS $$
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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 $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
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)]
|
||||
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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 $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_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.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import QuotaExceededException
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
@@ -90,6 +126,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -101,14 +140,14 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_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.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import LegacyServiceManager, QuotaExceededException
|
||||
from cartodb_services.google import GoogleMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
@@ -119,6 +158,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -130,18 +172,18 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.tools import ServiceManager
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
@@ -157,6 +199,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -165,3 +210,95 @@ RETURNS Geometry AS $$
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using Mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using Mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_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 iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.tomtom import TomTomGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.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:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using TomTom')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
97
server/extension/sql/21_bulk_geocode_street.sql
Normal file
97
server/extension/sql/21_bulk_geocode_street.sql
Normal file
@@ -0,0 +1,97 @@
|
||||
-- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset?
|
||||
CREATE TYPE cdb_dataservices_server.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding 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_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)
|
||||
|
||||
params = {'searches': searches}
|
||||
|
||||
with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params):
|
||||
if user_geocoder_config.google_geocoder:
|
||||
provider_function = "_cdb_bulk_google_geocode_street_point";
|
||||
elif user_geocoder_config.heremaps_geocoder:
|
||||
provider_function = "_cdb_bulk_heremaps_geocode_street_point";
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
provider_function = "_cdb_bulk_tomtom_geocode_street_point";
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
provider_function = "_cdb_bulk_mapbox_geocode_street_point";
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"])
|
||||
return plpy.execute(plan, [username, orgname, searches])
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_google_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.google import GoogleMapsBulkGeocoder
|
||||
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
geocoder = GoogleMapsBulkGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_heremaps_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.here import HereMapsBulkGeocoder
|
||||
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
geocoder = HereMapsBulkGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_tomtom_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
from cartodb_services.tomtom import TomTomBulkGeocoder
|
||||
from cartodb_services.tools import Logger
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
geocoder = TomTomBulkGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_mapbox_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
|
||||
from cartodb_services import run_street_point_geocoder
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
from cartodb_services.mapbox import MapboxBulkGeocoder
|
||||
from cartodb_services.tools import Logger
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
geocoder = MapboxBulkGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
return run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches)
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name])[0]['point']
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3) as point;", ["text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -14,10 +22,18 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name, country_name])[0]['point']
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, NULL, $4) as point;", ["text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -26,57 +42,20 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_namedplace_point(username text, orgname text, city_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
import spiexceptions
|
||||
try:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
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))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1}, {2})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname), plpy.quote_nullable('mapzen')))
|
||||
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)
|
||||
quota_service = QuotaService(user_geocoder_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
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()
|
||||
try:
|
||||
street_point = plpy.prepare("SELECT cdb_dataservices_server.cdb_geocode_street_point($1, $2, $3, NULL, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(street_point, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
except spiexceptions.ExternalRoutineException as e:
|
||||
import sys
|
||||
logger.error('Error geocoding namedplace using geocode street point, falling back to internal geocoder', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
internal_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_internal_geocode_namedplace($1, $2, $3, $4, $5) as point;", ["text", "text", "text", "text", "text"])
|
||||
return plpy.execute(internal_plan, [username, orgname, city_name, admin1_name, country_name])[0]['point']
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
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)
|
||||
|
||||
@@ -123,6 +123,134 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = tomtom_isolines.calculate_isodistance(origin, r, profile)
|
||||
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.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
|
||||
username TEXT,
|
||||
@@ -186,3 +314,124 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
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 = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -14,13 +14,21 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
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):
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isodistance', user_isolines_config, logger, params):
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -53,3 +61,31 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- mapbox isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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)]
|
||||
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- tomtom isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -14,13 +14,21 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
with metrics('cb_isochrone', user_isolines_config, logger):
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isochrone', user_isolines_config, logger, params):
|
||||
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])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -52,3 +60,29 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- mapbox isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_mapbox_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)]
|
||||
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- tomtom isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_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)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
@@ -31,6 +33,18 @@ SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
-- Check that the public function is callable, even with no data
|
||||
-- It should return NULL
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx', 'Valencia', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
@@ -32,36 +35,42 @@ INSERT INTO country_decoder (synonyms, iso2) VALUES (Array['spain', 'Spain'], 'E
|
||||
INSERT INTO admin1_decoder (admin1, synonyms, iso2) VALUES ('Valencia', Array['valencia', 'Valencia'], 'ES');
|
||||
-- This should return the point inserted above
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elche');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elche', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elx', 'Valencia', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point('test_user', 'test_orgname', 'Elche', 'valencia', 'Spain');
|
||||
WARNING: Error geocoding namedplace using geocode street point, falling back to internal geocoder. Exception: spiexceptions.ExternalRoutineException: cartodb_services.metrics.config.ConfigException: There is no user config available. Please check your configuration.'
|
||||
cdb_geocode_namedplace_point
|
||||
----------------------------------------------------
|
||||
0101000020E6100000637FD93D7958E63F2ECA6C9049A24340
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
@@ -13,6 +15,8 @@ SELECT cartodb.cdb_conf_setconf('redis_metrics_config', '{"redis_host": "localho
|
||||
SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 6379, "timeout": 0.1, "redis_db": 5}');
|
||||
SELECT cartodb.cdb_conf_setconf('heremaps_conf', '{"geocoder": {"app_id": "dummy_id", "app_code": "dummy_code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "dummy_id", "app_code": "dummy_code"}}');
|
||||
SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing_dummy_api_key", "monthly_quota": 1500000}, "geocoder": {"api_key": "geocoder_dummy_api_key", "monthly_quota": 1500000}, "matrix": {"api_key": "matrix_dummy_api_key", "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}');
|
||||
SELECT cartodb.cdb_conf_setconf('data_observatory_conf', '{"connection": {"whitelist": ["ethervoid"], "production": "host=localhost port=5432 dbname=contrib_regression user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}, "monthly_quota": 100000}');
|
||||
|
||||
|
||||
0
server/lib/__init__.py
Normal file
0
server/lib/__init__.py
Normal file
0
server/lib/python/__init__.py
Normal file
0
server/lib/python/__init__.py
Normal file
@@ -24,7 +24,7 @@ NOTE: a system installation is required at present because the library is meant
|
||||
|
||||
|
||||
## Running the unit tests
|
||||
Just run `nosetests test/`
|
||||
Just run `MAPBOX_API_KEY=xxx nosetests test/`
|
||||
```shell
|
||||
$ nosetests test/
|
||||
......................................................................................................
|
||||
|
||||
0
server/lib/python/cartodb_services/__init__.py
Normal file
0
server/lib/python/cartodb_services/__init__.py
Normal file
@@ -33,3 +33,5 @@ def _reset():
|
||||
|
||||
plpy = None
|
||||
GD = None
|
||||
|
||||
from geocoder import run_street_point_geocoder, StreetPointBulkGeocoder
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from google import GoogleMapsBulkGeocoder
|
||||
from here import HereMapsBulkGeocoder
|
||||
from tomtom import TomTomBulkGeocoder
|
||||
from mapbox import MapboxBulkGeocoder
|
||||
|
||||
BATCH_GEOCODER_CLASS_BY_PROVIDER = {
|
||||
'google': GoogleMapsBulkGeocoder,
|
||||
'heremaps': HereMapsBulkGeocoder,
|
||||
'tomtom': TomTomBulkGeocoder,
|
||||
'mapbox': MapboxBulkGeocoder
|
||||
}
|
||||
119
server/lib/python/cartodb_services/cartodb_services/geocoder.py
Normal file
119
server/lib/python/cartodb_services/cartodb_services/geocoder.py
Normal file
@@ -0,0 +1,119 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import QuotaExceededException, Logger
|
||||
from collections import namedtuple
|
||||
import json
|
||||
|
||||
|
||||
PRECISION_PRECISE = 'precise'
|
||||
PRECISION_INTERPOLATED = 'interpolated'
|
||||
|
||||
|
||||
def geocoder_metadata(relevance, precision, match_types):
|
||||
return {
|
||||
'relevance': round(relevance, 2),
|
||||
'precision': precision,
|
||||
'match_types': match_types
|
||||
}
|
||||
|
||||
|
||||
def compose_address(street, city=None, state=None, country=None):
|
||||
return ', '.join(filter(None, [street, city, state, country]))
|
||||
|
||||
|
||||
def run_street_point_geocoder(plpy, GD, geocoder, service_manager, username, orgname, searches):
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
|
||||
logger = Logger(logger_config)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
geocode_results = geocoder.bulk_geocode(searches=searches)
|
||||
if geocode_results:
|
||||
results = []
|
||||
for result in geocode_results:
|
||||
if len(result) > 2:
|
||||
metadata = json.dumps(result[2])
|
||||
else:
|
||||
logger.warning('Geocoding for {} without metadata'.format(username))
|
||||
metadata = '{}'
|
||||
|
||||
if result[1] and len(result[1]) == 2:
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326) as the_geom; ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, result[1], 1)[0]
|
||||
results.append([result[0], point['the_geom'], metadata])
|
||||
else:
|
||||
results.append([result[0], None, metadata])
|
||||
service_manager.quota_service.increment_success_service_use(len(results))
|
||||
return results
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use(len(searches))
|
||||
return []
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use(len(searches))
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to bulk geocode street point', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to bulk geocode street')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
|
||||
|
||||
StreetGeocoderSearch = namedtuple('StreetGeocoderSearch', 'id address city state country')
|
||||
|
||||
|
||||
class StreetPointBulkGeocoder:
|
||||
"""
|
||||
Classes extending StreetPointBulkGeocoder should implement:
|
||||
* _batch_geocode(street_geocoder_searches)
|
||||
* MAX_BATCH_SIZE
|
||||
|
||||
If they want to provide an alternative serial (for small batches):
|
||||
* _should_use_batch(street_geocoder_searches)
|
||||
* _serial_geocode(street_geocoder_searches)
|
||||
"""
|
||||
|
||||
SEARCH_KEYS = ['id', 'address', 'city', 'state', 'country']
|
||||
|
||||
def bulk_geocode(self, searches):
|
||||
"""
|
||||
:param searches: array of StreetGeocoderSearch
|
||||
:return: array of tuples with three elements:
|
||||
* id
|
||||
* latitude and longitude (array of two elements)
|
||||
* empty array (future use: metadata)
|
||||
"""
|
||||
try:
|
||||
decoded_searches = json.loads(searches)
|
||||
except Exception as e:
|
||||
self._logger.error('General error', exception=e)
|
||||
raise e
|
||||
|
||||
street_geocoder_searches = []
|
||||
for search in decoded_searches:
|
||||
search_id, address, city, state, country = \
|
||||
[search.get(k, None) for k in self.SEARCH_KEYS]
|
||||
street_geocoder_searches.append(
|
||||
StreetGeocoderSearch(search_id, address, city, state, country))
|
||||
|
||||
if len(street_geocoder_searches) > self.MAX_BATCH_SIZE:
|
||||
raise Exception("Batch size can't be larger than {}".format(self.MAX_BATCH_SIZE))
|
||||
if self._should_use_batch(street_geocoder_searches):
|
||||
return self._batch_geocode(street_geocoder_searches)
|
||||
else:
|
||||
return self._serial_geocode(street_geocoder_searches)
|
||||
|
||||
def _batch_geocode(self, street_geocoder_searches):
|
||||
raise NotImplementedError('Subclasses must implement _batch_geocode')
|
||||
|
||||
def _serial_geocode(self, street_geocoder_searches):
|
||||
raise NotImplementedError('Subclasses must implement _serial_geocode')
|
||||
|
||||
def _should_use_batch(self, street_geocoder_searches):
|
||||
return True
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
from geocoder import GoogleMapsGeocoder
|
||||
from bulk_geocoder import GoogleMapsBulkGeocoder
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
from multiprocessing import Pool
|
||||
from exceptions import MalformedResult
|
||||
from cartodb_services import StreetPointBulkGeocoder
|
||||
from cartodb_services.geocoder import compose_address
|
||||
from cartodb_services.google import GoogleMapsGeocoder
|
||||
|
||||
|
||||
def async_geocoder(geocoder, address, components):
|
||||
return geocoder.geocode(address=address, components=components)
|
||||
|
||||
|
||||
class GoogleMapsBulkGeocoder(GoogleMapsGeocoder, StreetPointBulkGeocoder):
|
||||
"""A Google Maps Geocoder wrapper for python"""
|
||||
MAX_BATCH_SIZE = 1000
|
||||
MIN_BATCHED_SEARCH = 2 # Batched is a parallelization
|
||||
PARALLEL_PROCESSES = 13
|
||||
|
||||
def __init__(self, client_id, client_secret, logger):
|
||||
GoogleMapsGeocoder.__init__(self, client_id, client_secret, logger)
|
||||
|
||||
def _should_use_batch(self, searches):
|
||||
return len(searches) >= self.MIN_BATCHED_SEARCH
|
||||
|
||||
def _serial_geocode(self, searches):
|
||||
results = []
|
||||
for search in searches:
|
||||
(cartodb_id, street, city, state, country) = search
|
||||
lng_lat, metadata = self.geocode_meta(street, city, state, country)
|
||||
results.append((cartodb_id, lng_lat, metadata))
|
||||
return results
|
||||
|
||||
def _batch_geocode(self, searches):
|
||||
bulk_results = {}
|
||||
pool = Pool(processes=self.PARALLEL_PROCESSES)
|
||||
for search in searches:
|
||||
(cartodb_id, street, city, state, country) = search
|
||||
address = compose_address(street, city, state, country)
|
||||
if address:
|
||||
components = self._build_optional_parameters(city, state, country)
|
||||
result = pool.apply_async(async_geocoder,
|
||||
(self.geocoder, address, components))
|
||||
bulk_results[cartodb_id] = result
|
||||
pool.close()
|
||||
pool.join()
|
||||
|
||||
try:
|
||||
results = []
|
||||
for cartodb_id, bulk_result in bulk_results.items():
|
||||
try:
|
||||
lng_lat, metadata = self._process_results(bulk_result.get())
|
||||
except Exception as e:
|
||||
self._logger.error('Error at Google async_geocoder', e)
|
||||
lng_lat, metadata = [[], {}]
|
||||
|
||||
results.append((cartodb_id, lng_lat, metadata))
|
||||
return results
|
||||
except KeyError as e:
|
||||
self._logger.error('KeyError error', exception=e)
|
||||
raise MalformedResult()
|
||||
except Exception as e:
|
||||
self._logger.error('General error', exception=e)
|
||||
raise e
|
||||
@@ -5,6 +5,7 @@ import googlemaps
|
||||
import base64
|
||||
from exceptions import InvalidGoogleCredentials
|
||||
|
||||
|
||||
class GoogleMapsClientFactory():
|
||||
clients = {}
|
||||
|
||||
@@ -13,11 +14,14 @@ class GoogleMapsClientFactory():
|
||||
cache_key = "{}:{}:{}".format(client_id, client_secret, channel)
|
||||
client = cls.clients.get(cache_key)
|
||||
if not client:
|
||||
cls.assert_valid_crendentials(client_secret)
|
||||
client = googlemaps.Client(
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
channel=channel)
|
||||
if client_id:
|
||||
cls.assert_valid_crendentials(client_secret)
|
||||
client = googlemaps.Client(
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
channel=channel)
|
||||
else:
|
||||
client = googlemaps.Client(key=client_secret)
|
||||
cls.clients[cache_key] = client
|
||||
return client
|
||||
|
||||
|
||||
@@ -1,16 +1,42 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import googlemaps
|
||||
from urlparse import parse_qs
|
||||
|
||||
from exceptions import MalformedResult
|
||||
from cartodb_services.geocoder import compose_address, geocoder_metadata, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
||||
from cartodb_services.google.exceptions import InvalidGoogleCredentials
|
||||
from client_factory import GoogleMapsClientFactory
|
||||
|
||||
EMPTY_RESPONSE = [[], {}]
|
||||
PARTIAL_FACTOR = 0.8
|
||||
RELEVANCE_BY_LOCATION_TYPE = {
|
||||
'ROOFTOP': 1,
|
||||
'GEOMETRIC_CENTER': 0.9,
|
||||
'RANGE_INTERPOLATED': 0.8,
|
||||
'APPROXIMATE': 0.7
|
||||
}
|
||||
PRECISION_BY_LOCATION_TYPE = {
|
||||
'ROOFTOP': PRECISION_PRECISE,
|
||||
'GEOMETRIC_CENTER': PRECISION_PRECISE,
|
||||
'RANGE_INTERPOLATED': PRECISION_INTERPOLATED,
|
||||
'APPROXIMATE': PRECISION_INTERPOLATED
|
||||
}
|
||||
MATCH_TYPE_BY_MATCH_LEVEL = {
|
||||
'point_of_interest': 'point_of_interest',
|
||||
'country': 'country',
|
||||
'administrative_area_level_1': 'state',
|
||||
'administrative_area_level_2': 'county',
|
||||
'locality': 'locality',
|
||||
'sublocality': 'district',
|
||||
'street_address': 'street',
|
||||
'intersection': 'intersection',
|
||||
'street_number': 'street_number',
|
||||
'postal_code': 'postal_code'
|
||||
}
|
||||
|
||||
class GoogleMapsGeocoder:
|
||||
"""A Google Maps Geocoder wrapper for python"""
|
||||
|
||||
class GoogleMapsGeocoder():
|
||||
|
||||
def __init__(self, client_id, client_secret, logger):
|
||||
if client_id is None:
|
||||
@@ -20,25 +46,49 @@ class GoogleMapsGeocoder:
|
||||
self.geocoder = GoogleMapsClientFactory.get(self.client_id, self.client_secret, self.channel)
|
||||
self._logger = logger
|
||||
|
||||
def geocode(self, searchtext, city=None, state=None,
|
||||
country=None):
|
||||
def geocode(self, searchtext, city=None, state=None, country=None):
|
||||
return self.geocode_meta(searchtext, city, state, country)[0]
|
||||
|
||||
def geocode_meta(self, searchtext, city=None, state=None, country=None):
|
||||
address = compose_address(searchtext, city, state, country)
|
||||
try:
|
||||
opt_params = self._build_optional_parameters(city, state, country)
|
||||
results = self.geocoder.geocode(address=searchtext,
|
||||
results = self.geocoder.geocode(address=address,
|
||||
components=opt_params)
|
||||
if results:
|
||||
return self._extract_lng_lat_from_result(results[0])
|
||||
else:
|
||||
return []
|
||||
except KeyError:
|
||||
return self._process_results(results)
|
||||
except KeyError as e:
|
||||
self._logger.error('address: {}'.format(address), e)
|
||||
raise MalformedResult()
|
||||
|
||||
def _process_results(self, results):
|
||||
if results:
|
||||
return [
|
||||
self._extract_lng_lat_from_result(results[0]),
|
||||
self._extract_metadata_from_result(results[0])
|
||||
]
|
||||
else:
|
||||
return EMPTY_RESPONSE
|
||||
|
||||
def _extract_lng_lat_from_result(self, result):
|
||||
location = result['geometry']['location']
|
||||
longitude = location['lng']
|
||||
latitude = location['lat']
|
||||
return [longitude, latitude]
|
||||
|
||||
def _extract_metadata_from_result(self, result):
|
||||
location_type = result['geometry']['location_type']
|
||||
base_relevance = RELEVANCE_BY_LOCATION_TYPE[location_type]
|
||||
partial_match = result.get('partial_match', False)
|
||||
partial_factor = PARTIAL_FACTOR if partial_match else 1
|
||||
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
||||
for match_level in result['types']]
|
||||
return geocoder_metadata(
|
||||
base_relevance * partial_factor,
|
||||
PRECISION_BY_LOCATION_TYPE[location_type],
|
||||
filter(None, match_types)
|
||||
)
|
||||
|
||||
|
||||
def _build_optional_parameters(self, city=None, state=None,
|
||||
country=None):
|
||||
optional_params = {}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from geocoder import HereMapsGeocoder
|
||||
from bulk_geocoder import HereMapsBulkGeocoder
|
||||
from routing import HereMapsRoutingIsoline
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import requests, time, zipfile, io, csv, cStringIO
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import namedtuple
|
||||
from requests.adapters import HTTPAdapter
|
||||
from cartodb_services import StreetPointBulkGeocoder
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
from cartodb_services.geocoder import geocoder_metadata
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
|
||||
|
||||
HereJobStatus = namedtuple('HereJobStatus', 'total_count processed_count status')
|
||||
|
||||
class HereMapsBulkGeocoder(HereMapsGeocoder, StreetPointBulkGeocoder):
|
||||
MAX_BATCH_SIZE = 1000000 # From the docs
|
||||
MIN_BATCHED_SEARCH = 100 # Under this, serial will be used
|
||||
BATCH_URL = 'https://batch.geocoder.cit.api.here.com/6.2/jobs'
|
||||
# https://developer.here.com/documentation/batch-geocoder/topics/read-batch-request-output.html
|
||||
META_COLS = ['relevance', 'matchType', 'matchCode', 'matchLevel', 'matchQualityStreet']
|
||||
MAX_STALLED_RETRIES = 100
|
||||
BATCH_RETRY_SLEEP_S = 5
|
||||
JOB_FINAL_STATES = ['completed', 'cancelled', 'deleted', 'failed']
|
||||
|
||||
def __init__(self, app_id, app_code, logger, service_params=None, maxresults=HereMapsGeocoder.DEFAULT_MAXRESULTS):
|
||||
HereMapsGeocoder.__init__(self, app_id, app_code, logger, service_params, maxresults)
|
||||
self.session = requests.Session()
|
||||
self.session.mount(self.BATCH_URL,
|
||||
HTTPAdapter(max_retries=self.max_retries))
|
||||
self.credentials_params = {
|
||||
'app_id': self.app_id,
|
||||
'app_code': self.app_code,
|
||||
}
|
||||
|
||||
def _should_use_batch(self, searches):
|
||||
return len(searches) >= self.MIN_BATCHED_SEARCH
|
||||
|
||||
def _serial_geocode(self, searches):
|
||||
results = []
|
||||
for search in searches:
|
||||
(search_id, address, city, state, country) = search
|
||||
result = self.geocode_meta(searchtext=address, city=city, state=state, country=country)
|
||||
results.append((search_id, result[0], result[1]))
|
||||
return results
|
||||
|
||||
def _batch_geocode(self, searches):
|
||||
request_id = self._send_batch(self._searches_to_csv(searches))
|
||||
|
||||
last_processed = 0
|
||||
stalled_retries = 0
|
||||
# https://developer.here.com/documentation/batch-geocoder/topics/job-status.html
|
||||
while True:
|
||||
job_info = self._job_status(request_id)
|
||||
if job_info.processed_count == last_processed:
|
||||
stalled_retries += 1
|
||||
if stalled_retries > self.MAX_STALLED_RETRIES:
|
||||
raise Exception('Too many retries for job {}'.format(request_id))
|
||||
else:
|
||||
stalled_retries = 0
|
||||
last_processed = job_info.processed_count
|
||||
|
||||
if job_info.status in self.JOB_FINAL_STATES:
|
||||
break
|
||||
else:
|
||||
time.sleep(self.BATCH_RETRY_SLEEP_S)
|
||||
|
||||
results = self._download_results(request_id)
|
||||
|
||||
return results
|
||||
|
||||
def _searches_to_csv(self, searches):
|
||||
queue = cStringIO.StringIO()
|
||||
writer = csv.writer(queue, delimiter='|')
|
||||
writer.writerow(['recId', 'searchText', 'country'])
|
||||
|
||||
for search in searches:
|
||||
fields = [search.address, search.city, search.state]
|
||||
search_text = ', '.join(filter(None, fields))
|
||||
row = [s.encode("utf-8") if s else ''
|
||||
for s in [str(search.id), search_text, search.country]]
|
||||
writer.writerow(row)
|
||||
|
||||
return queue.getvalue()
|
||||
|
||||
def _send_batch(self, data):
|
||||
cols = 'displayLatitude,displayLongitude,' + ','.join(self.META_COLS)
|
||||
request_params = self.credentials_params.copy()
|
||||
request_params.update({
|
||||
'gen': 8,
|
||||
'action': 'run',
|
||||
# 'mailto': 'juanignaciosl@carto.com',
|
||||
'header': 'true',
|
||||
'inDelim': '|',
|
||||
'outDelim': '|',
|
||||
'outCols': cols,
|
||||
'outputcombined': 'true'
|
||||
})
|
||||
|
||||
response = self.session.post(self.BATCH_URL, data=data,
|
||||
params=request_params,
|
||||
timeout=(self.connect_timeout, self.read_timeout))
|
||||
|
||||
if response.status_code == 200:
|
||||
root = ET.fromstring(response.text)
|
||||
return root.find('./Response/MetaInfo/RequestId').text
|
||||
else:
|
||||
raise ServiceException("Error sending HERE batch", response)
|
||||
|
||||
def _job_status(self, request_id):
|
||||
polling_params = self.credentials_params.copy()
|
||||
polling_params.update({'action': 'status'})
|
||||
polling_r = self.session.get("{}/{}".format(self.BATCH_URL, request_id),
|
||||
params=polling_params,
|
||||
timeout=(self.connect_timeout, self.read_timeout))
|
||||
polling_root = ET.fromstring(polling_r.text)
|
||||
return HereJobStatus(
|
||||
total_count=int(polling_root.find('./Response/TotalCount').text),
|
||||
processed_count=int(polling_root.find('./Response/ProcessedCount').text),
|
||||
status=polling_root.find('./Response/Status').text)
|
||||
|
||||
def _download_results(self, job_id):
|
||||
result_r = self.session.get("{}/{}/result".format(self.BATCH_URL, job_id),
|
||||
params=self.credentials_params,
|
||||
timeout=(self.connect_timeout, self.read_timeout))
|
||||
root_zip = zipfile.ZipFile(io.BytesIO(result_r.content))
|
||||
|
||||
results = []
|
||||
for name in root_zip.namelist():
|
||||
if name.endswith('_out.txt'):
|
||||
reader = csv.DictReader(root_zip.open(name), delimiter='|')
|
||||
for row in reader:
|
||||
if row['SeqNumber'] == '1': # First per requested data
|
||||
precision = self.PRECISION_BY_MATCH_TYPE[
|
||||
row.get('matchType', 'pointAddress')]
|
||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None)
|
||||
results.append((row['recId'],
|
||||
[row['displayLongitude'], row['displayLatitude']],
|
||||
geocoder_metadata(
|
||||
float(row['relevance']),
|
||||
precision,
|
||||
[match_type] if match_type else []
|
||||
)))
|
||||
|
||||
return results
|
||||
|
||||
@@ -6,9 +6,9 @@ import requests
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from exceptions import *
|
||||
from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
|
||||
from cartodb_services.metrics import Traceable
|
||||
|
||||
|
||||
class HereMapsGeocoder(Traceable):
|
||||
'A Here Maps Geocoder wrapper for python'
|
||||
|
||||
@@ -52,6 +52,23 @@ class HereMapsGeocoder(Traceable):
|
||||
'strictlanguagemode'
|
||||
] + ADDRESS_PARAMS
|
||||
|
||||
PRECISION_BY_MATCH_TYPE = {
|
||||
'pointAddress': PRECISION_PRECISE,
|
||||
'interpolated': PRECISION_INTERPOLATED
|
||||
}
|
||||
MATCH_TYPE_BY_MATCH_LEVEL = {
|
||||
'landmark': 'point_of_interest',
|
||||
'country': 'country',
|
||||
'state': 'state',
|
||||
'county': 'county',
|
||||
'city': 'locality',
|
||||
'district': 'district',
|
||||
'street': 'street',
|
||||
'intersection': 'intersection',
|
||||
'houseNumber': 'street_number',
|
||||
'postalCode': 'postal_code'
|
||||
}
|
||||
|
||||
def __init__(self, app_id, app_code, logger, service_params=None, maxresults=DEFAULT_MAXRESULTS):
|
||||
service_params = service_params or {}
|
||||
self.app_id = app_id
|
||||
@@ -65,12 +82,15 @@ class HereMapsGeocoder(Traceable):
|
||||
self.max_retries = service_params.get('max_retries', self.MAX_RETRIES)
|
||||
|
||||
def geocode(self, **kwargs):
|
||||
return self.geocode_meta(**kwargs)[0]
|
||||
|
||||
def geocode_meta(self, **kwargs):
|
||||
params = {}
|
||||
for key, value in kwargs.iteritems():
|
||||
if value:
|
||||
if value and value.strip():
|
||||
params[key] = value
|
||||
if not params:
|
||||
raise NoGeocodingParams()
|
||||
return [[], {}]
|
||||
return self._execute_geocode(params)
|
||||
|
||||
def _execute_geocode(self, params):
|
||||
@@ -78,11 +98,13 @@ class HereMapsGeocoder(Traceable):
|
||||
raise BadGeocodingParams(params)
|
||||
try:
|
||||
response = self._perform_request(params)
|
||||
results = response['Response']['View'][0]['Result'][0]
|
||||
return self._extract_lng_lat_from_result(results)
|
||||
result = response['Response']['View'][0]['Result'][0]
|
||||
return [self._extract_lng_lat_from_result(result),
|
||||
self._extract_metadata_from_result(result)]
|
||||
except IndexError:
|
||||
return []
|
||||
except KeyError:
|
||||
return [[], {}]
|
||||
except KeyError as e:
|
||||
self._logger.error('params: {}'.format(params), e)
|
||||
raise MalformedResult()
|
||||
|
||||
def _perform_request(self, params):
|
||||
@@ -118,3 +140,14 @@ class HereMapsGeocoder(Traceable):
|
||||
latitude = location['DisplayPosition']['Latitude']
|
||||
|
||||
return [longitude, latitude]
|
||||
|
||||
def _extract_metadata_from_result(self, result):
|
||||
# See https://stackoverflow.com/questions/51285622/missing-matchtype-at-here-geocoding-responses
|
||||
precision = self.PRECISION_BY_MATCH_TYPE[
|
||||
result.get('MatchType', 'pointAddress')]
|
||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None)
|
||||
return geocoder_metadata(
|
||||
result['Relevance'],
|
||||
precision,
|
||||
[match_type] if match_type else []
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from routing import MapboxRouting, MapboxRoutingResponse
|
||||
from geocoder import MapboxGeocoder
|
||||
from bulk_geocoder import MapboxBulkGeocoder
|
||||
from isolines import MapboxIsolines, MapboxIsochronesResponse
|
||||
from matrix_client import MapboxMatrixClient
|
||||
@@ -0,0 +1,67 @@
|
||||
import json, requests, time
|
||||
from requests.adapters import HTTPAdapter
|
||||
from cartodb_services import StreetPointBulkGeocoder
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
|
||||
|
||||
class MapboxBulkGeocoder(MapboxGeocoder, StreetPointBulkGeocoder):
|
||||
MAX_BATCH_SIZE = 50 # From the docs
|
||||
MIN_BATCHED_SEARCH = 0
|
||||
READ_TIMEOUT = 60
|
||||
CONNECT_TIMEOUT = 10
|
||||
MAX_RETRIES = 1
|
||||
|
||||
def __init__(self, token, logger, service_params=None):
|
||||
MapboxGeocoder.__init__(self, token, logger, service_params)
|
||||
self.connect_timeout = service_params.get('connect_timeout', self.CONNECT_TIMEOUT)
|
||||
self.read_timeout = service_params.get('read_timeout', self.READ_TIMEOUT)
|
||||
self.max_retries = service_params.get('max_retries', self.MAX_RETRIES)
|
||||
self.session = requests.Session()
|
||||
|
||||
def _should_use_batch(self, searches):
|
||||
return len(searches) >= self.MIN_BATCHED_SEARCH
|
||||
|
||||
def _serial_geocode(self, searches):
|
||||
results = []
|
||||
for search in searches:
|
||||
elements = self._encoded_elements(search)
|
||||
result = self.geocode_meta(*elements)
|
||||
|
||||
results.append((search[0], result[0], result[1]))
|
||||
return results
|
||||
|
||||
def _encoded_elements(self, search):
|
||||
(search_id, address, city, state, country) = search
|
||||
address = address.encode('utf-8') if address else None
|
||||
city = city.encode('utf-8') if city else None
|
||||
state = state.encode('utf-8') if state else None
|
||||
country = self._country_code(country) if country else None
|
||||
return address, city, state, country
|
||||
|
||||
def _batch_geocode(self, searches):
|
||||
if len(searches) == 1:
|
||||
return self._serial_geocode(searches)
|
||||
else:
|
||||
frees = []
|
||||
for search in searches:
|
||||
elements = self._encoded_elements(search)
|
||||
free = ', '.join([elem for elem in elements if elem])
|
||||
frees.append(free)
|
||||
|
||||
full_results = self.geocode_free_text_meta(frees)
|
||||
results = []
|
||||
for s, r in zip(searches, full_results):
|
||||
results.append((s[0], r[0], r[1]))
|
||||
return results
|
||||
|
||||
def _country_code(self, country):
|
||||
country_iso3166 = None
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
return country_iso3166
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
'''
|
||||
Python client for the Mapbox Geocoder service.
|
||||
'''
|
||||
|
||||
import json
|
||||
import requests
|
||||
from mapbox import Geocoder
|
||||
from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools.normalize import normalize
|
||||
|
||||
GEOCODER_NAME = 'geocoder_name'
|
||||
EPHEMERAL_GEOCODER = 'mapbox.places'
|
||||
PERMANENT_GEOCODER = 'mapbox.places-permanent'
|
||||
DEFAULT_GEOCODER = PERMANENT_GEOCODER
|
||||
|
||||
ENTRY_FEATURES = 'features'
|
||||
ENTRY_CENTER = 'center'
|
||||
ENTRY_GEOMETRY = 'geometry'
|
||||
ENTRY_COORDINATES = 'coordinates'
|
||||
ENTRY_TYPE = 'type'
|
||||
TYPE_POINT = 'Point'
|
||||
|
||||
EMPTY_RESPONSE = [[], {}]
|
||||
|
||||
MATCH_TYPE_BY_MATCH_LEVEL = {
|
||||
'poi': 'point_of_interest',
|
||||
'poi.landmark': 'point_of_interest',
|
||||
'place': 'point_of_interest',
|
||||
'country': 'country',
|
||||
'region': 'state',
|
||||
'locality': 'locality',
|
||||
'district': 'district',
|
||||
'address': 'street'
|
||||
}
|
||||
|
||||
|
||||
class MapboxGeocoder(Traceable):
|
||||
'''
|
||||
Python wrapper for the Mapbox Geocoder service.
|
||||
'''
|
||||
|
||||
def __init__(self, token, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._token = token
|
||||
self._logger = logger
|
||||
self._geocoder_name = service_params.get(GEOCODER_NAME,
|
||||
DEFAULT_GEOCODER)
|
||||
self._geocoder = Geocoder(access_token=self._token,
|
||||
name=self._geocoder_name)
|
||||
|
||||
def _parse_geocoder_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
if json_response:
|
||||
if type(json_response) != list:
|
||||
json_response = [json_response]
|
||||
|
||||
result = []
|
||||
for a_json_response in json_response:
|
||||
if a_json_response[ENTRY_FEATURES]:
|
||||
feature = a_json_response[ENTRY_FEATURES][0]
|
||||
result.append([
|
||||
self._extract_lng_lat_from_feature(feature),
|
||||
self._extract_metadata_from_result(feature)
|
||||
]
|
||||
)
|
||||
else:
|
||||
result.append(EMPTY_RESPONSE)
|
||||
return result
|
||||
else:
|
||||
return EMPTY_RESPONSE
|
||||
|
||||
def _extract_lng_lat_from_feature(self, feature):
|
||||
geometry = feature[ENTRY_GEOMETRY]
|
||||
if geometry[ENTRY_TYPE] == TYPE_POINT:
|
||||
location = geometry[ENTRY_COORDINATES]
|
||||
else:
|
||||
location = feature[ENTRY_CENTER]
|
||||
|
||||
longitude = location[0]
|
||||
latitude = location[1]
|
||||
return [longitude, latitude]
|
||||
|
||||
def _extract_metadata_from_result(self, result):
|
||||
if result[ENTRY_GEOMETRY].get('interpolated', False):
|
||||
precision = PRECISION_INTERPOLATED
|
||||
else:
|
||||
precision = PRECISION_PRECISE
|
||||
|
||||
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
||||
for match_level in result['place_type']]
|
||||
return geocoder_metadata(
|
||||
self._normalize_relevance(float(result['relevance'])),
|
||||
precision,
|
||||
filter(None, match_types)
|
||||
)
|
||||
|
||||
def _normalize_relevance(self, relevance):
|
||||
return 1 if relevance >= 0.99 else relevance
|
||||
|
||||
def _validate_input(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
if searchtext and searchtext.strip():
|
||||
return True
|
||||
elif city:
|
||||
return True
|
||||
elif state_province:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@qps_retry(qps=10)
|
||||
def geocode(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
"""
|
||||
:param searchtext:
|
||||
:param city:
|
||||
:param state_province:
|
||||
:param country: Country ISO 3166 code
|
||||
:return: [x, y] on success, [] on error
|
||||
"""
|
||||
return self.geocode_meta(searchtext, city, state_province, country)[0]
|
||||
|
||||
@qps_retry(qps=10)
|
||||
def geocode_meta(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
if not self._validate_input(searchtext, city, state_province, country):
|
||||
return EMPTY_RESPONSE
|
||||
|
||||
address = []
|
||||
if searchtext and searchtext.strip():
|
||||
address.append(normalize(searchtext))
|
||||
if city:
|
||||
address.append(normalize(city))
|
||||
if state_province:
|
||||
address.append(normalize(state_province))
|
||||
|
||||
free_search = ', '.join(address)
|
||||
|
||||
return self.geocode_free_text_meta([free_search], country)[0]
|
||||
|
||||
@qps_retry(qps=10)
|
||||
def geocode_free_text_meta(self, free_searches, country=None):
|
||||
"""
|
||||
:param free_searches: Free text searches
|
||||
:param country: Country ISO 3166 code
|
||||
:return: list of [x, y] on success, [] on error
|
||||
"""
|
||||
country = [country] if country else None
|
||||
|
||||
try:
|
||||
free_search = ';'.join([self._escape(fs) for fs in free_searches])
|
||||
response = self._geocoder.forward(address=free_search.decode('utf-8'),
|
||||
country=country)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self._parse_geocoder_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return EMPTY_RESPONSE
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return EMPTY_RESPONSE
|
||||
else:
|
||||
raise ServiceException(response.status_code, 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 Mapbox geocoding server',
|
||||
te)
|
||||
raise ServiceException('Error geocoding {0} using Mapbox'.format(
|
||||
free_search), None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to Mapbox geocoding server',
|
||||
exception=ce)
|
||||
return EMPTY_RESPONSE
|
||||
|
||||
def _escape(self, free_search):
|
||||
# Semicolon is used to separate batch geocoding; there's no documented
|
||||
# way to pass actual semicolons, and %3B or ; won't work (check
|
||||
# TestBulkStreetFunctions.test_semicolon and the docs,
|
||||
# https://www.mapbox.com/api-documentation/#batch-requests)
|
||||
return free_search.replace(';', ',')
|
||||
@@ -0,0 +1,183 @@
|
||||
'''
|
||||
Python implementation for Mapbox services based isolines.
|
||||
Uses the Mapbox Time Matrix service.
|
||||
'''
|
||||
|
||||
import json
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.spherical import (get_angles,
|
||||
calculate_dest_location)
|
||||
from cartodb_services.mapbox.matrix_client import (validate_profile,
|
||||
DEFAULT_PROFILE,
|
||||
PROFILE_WALKING,
|
||||
PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
ENTRY_DURATIONS,
|
||||
ENTRY_DESTINATIONS,
|
||||
ENTRY_LOCATION)
|
||||
|
||||
MAX_SPEEDS = {
|
||||
PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed
|
||||
PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed
|
||||
PROFILE_DRIVING: 41.67 # In m/s, assuming 140km/h max speed
|
||||
}
|
||||
|
||||
DEFAULT_NUM_ANGLES = 24
|
||||
DEFAULT_MAX_ITERS = 5
|
||||
DEFAULT_TOLERANCE = 0.1
|
||||
|
||||
MATRIX_NUM_ANGLES = DEFAULT_NUM_ANGLES
|
||||
MATRIX_MAX_ITERS = DEFAULT_MAX_ITERS
|
||||
MATRIX_TOLERANCE = DEFAULT_TOLERANCE
|
||||
|
||||
UNIT_FACTOR_ISOCHRONE = 1.0
|
||||
UNIT_FACTOR_ISODISTANCE = 1000.0
|
||||
DEFAULT_UNIT_FACTOR = UNIT_FACTOR_ISOCHRONE
|
||||
|
||||
|
||||
class MapboxIsolines():
|
||||
'''
|
||||
Python wrapper for Mapbox services based isolines.
|
||||
'''
|
||||
|
||||
def __init__(self, matrix_client, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._matrix_client = matrix_client
|
||||
self._logger = logger
|
||||
|
||||
def _calculate_matrix_cost(self, origin, targets, isorange,
|
||||
profile=DEFAULT_PROFILE,
|
||||
unit_factor=UNIT_FACTOR_ISOCHRONE,
|
||||
number_of_angles=MATRIX_NUM_ANGLES):
|
||||
response = self._matrix_client.matrix([origin] + targets,
|
||||
profile)
|
||||
json_response = json.loads(response)
|
||||
if not json_response:
|
||||
return []
|
||||
|
||||
costs = [None] * number_of_angles
|
||||
destinations = [None] * number_of_angles
|
||||
|
||||
for idx, cost in enumerate(json_response[ENTRY_DURATIONS][0][1:]):
|
||||
if cost:
|
||||
costs[idx] = cost * unit_factor
|
||||
else:
|
||||
costs[idx] = isorange
|
||||
|
||||
for idx, destination in enumerate(json_response[ENTRY_DESTINATIONS][1:]):
|
||||
destinations[idx] = Coordinate(destination[ENTRY_LOCATION][0],
|
||||
destination[ENTRY_LOCATION][1])
|
||||
|
||||
return costs, destinations
|
||||
|
||||
def calculate_isochrone(self, origin, time_ranges,
|
||||
profile=DEFAULT_PROFILE):
|
||||
validate_profile(profile)
|
||||
|
||||
max_speed = MAX_SPEEDS[profile]
|
||||
|
||||
isochrones = []
|
||||
for time_range in time_ranges:
|
||||
upper_rmax = max_speed * time_range # an upper bound for the radius
|
||||
|
||||
coordinates = self.calculate_isoline(origin=origin,
|
||||
isorange=time_range,
|
||||
upper_rmax=upper_rmax,
|
||||
cost_method=self._calculate_matrix_cost,
|
||||
profile=profile,
|
||||
unit_factor=UNIT_FACTOR_ISOCHRONE,
|
||||
number_of_angles=MATRIX_NUM_ANGLES,
|
||||
max_iterations=MATRIX_MAX_ITERS,
|
||||
tolerance=MATRIX_TOLERANCE)
|
||||
isochrones.append(MapboxIsochronesResponse(coordinates,
|
||||
time_range))
|
||||
return isochrones
|
||||
|
||||
def calculate_isodistance(self, origin, distance_range,
|
||||
profile=DEFAULT_PROFILE):
|
||||
validate_profile(profile)
|
||||
|
||||
max_speed = MAX_SPEEDS[profile]
|
||||
time_range = distance_range / max_speed
|
||||
|
||||
return self.calculate_isochrone(origin=origin,
|
||||
time_ranges=[time_range],
|
||||
profile=profile)[0].coordinates
|
||||
|
||||
def calculate_isoline(self, origin, isorange, upper_rmax,
|
||||
cost_method=_calculate_matrix_cost,
|
||||
profile=DEFAULT_PROFILE,
|
||||
unit_factor=DEFAULT_UNIT_FACTOR,
|
||||
number_of_angles=DEFAULT_NUM_ANGLES,
|
||||
max_iterations=DEFAULT_MAX_ITERS,
|
||||
tolerance=DEFAULT_TOLERANCE):
|
||||
# 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
|
||||
|
||||
# Initial setup
|
||||
angles = get_angles(number_of_angles)
|
||||
rmax = [upper_rmax] * number_of_angles
|
||||
rmin = [0.0] * number_of_angles
|
||||
location_estimates = [calculate_dest_location(origin, a,
|
||||
upper_rmax / 2.0)
|
||||
for a in angles]
|
||||
|
||||
# Iterate to refine the first solution
|
||||
for i in xrange(0, max_iterations):
|
||||
# Calculate the "actual" cost for each location estimate.
|
||||
# NOTE: sometimes it cannot calculate the cost and returns None.
|
||||
# Just assume isorange and stop the calculations there
|
||||
|
||||
costs, destinations = cost_method(origin=origin,
|
||||
targets=location_estimates,
|
||||
isorange=isorange,
|
||||
profile=profile,
|
||||
unit_factor=unit_factor,
|
||||
number_of_angles=number_of_angles)
|
||||
|
||||
if not costs:
|
||||
continue
|
||||
|
||||
errors = [(cost - isorange) / float(isorange) for cost in costs]
|
||||
max_abs_error = max([abs(e) for e in errors])
|
||||
if max_abs_error <= tolerance:
|
||||
# good enough, stop there
|
||||
break
|
||||
|
||||
# let's refine the solution, binary search
|
||||
for j in xrange(0, number_of_angles):
|
||||
|
||||
if abs(errors[j]) > tolerance:
|
||||
if errors[j] > 0:
|
||||
rmax[j] = (rmax[j] + rmin[j]) / 2.0
|
||||
else:
|
||||
rmin[j] = (rmax[j] + rmin[j]) / 2.0
|
||||
|
||||
location_estimates[j] = calculate_dest_location(origin,
|
||||
angles[j],
|
||||
(rmax[j] + rmin[j]) / 2.0)
|
||||
|
||||
# delete points that got None
|
||||
location_estimates_filtered = []
|
||||
for i, c in enumerate(costs):
|
||||
if c != isorange and c < isorange * (1 + tolerance):
|
||||
location_estimates_filtered.append(destinations[i])
|
||||
|
||||
return location_estimates_filtered
|
||||
|
||||
|
||||
class MapboxIsochronesResponse:
|
||||
|
||||
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
|
||||
@@ -0,0 +1,92 @@
|
||||
'''
|
||||
Python client for the Mapbox Time Matrix service.
|
||||
'''
|
||||
|
||||
import requests
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.coordinates import (validate_coordinates,
|
||||
marshall_coordinates)
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
|
||||
BASEURI = ('https://api.mapbox.com/directions-matrix/v1/mapbox/{profile}/'
|
||||
'{coordinates}'
|
||||
'?access_token={token}'
|
||||
'&sources=0' # Set the first coordinate as source...
|
||||
'&destinations=all') # ...and the rest as destinations
|
||||
|
||||
NUM_COORDINATES_MIN = 2 # https://www.mapbox.com/api-documentation/#matrix
|
||||
NUM_COORDINATES_MAX = 25 # https://www.mapbox.com/api-documentation/#matrix
|
||||
|
||||
PROFILE_DRIVING_TRAFFIC = 'driving-traffic'
|
||||
PROFILE_DRIVING = 'driving'
|
||||
PROFILE_CYCLING = 'cycling'
|
||||
PROFILE_WALKING = 'walking'
|
||||
DEFAULT_PROFILE = PROFILE_DRIVING
|
||||
|
||||
VALID_PROFILES = [PROFILE_DRIVING_TRAFFIC,
|
||||
PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
PROFILE_WALKING]
|
||||
|
||||
ENTRY_DURATIONS = 'durations'
|
||||
ENTRY_DESTINATIONS = 'destinations'
|
||||
ENTRY_LOCATION = 'location'
|
||||
|
||||
|
||||
def validate_profile(profile):
|
||||
if profile not in VALID_PROFILES:
|
||||
raise ValueError('{profile} is not a valid profile. '
|
||||
'Valid profiles are: {valid_profiles}'.format(
|
||||
profile=profile,
|
||||
valid_profiles=', '.join(
|
||||
[x for x in VALID_PROFILES])))
|
||||
|
||||
|
||||
class MapboxMatrixClient(Traceable):
|
||||
'''
|
||||
Python wrapper for the Mapbox Time Matrix service.
|
||||
'''
|
||||
|
||||
def __init__(self, token, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._token = token
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, coordinates, profile=DEFAULT_PROFILE):
|
||||
return BASEURI.format(profile=profile, coordinates=coordinates,
|
||||
token=self._token)
|
||||
|
||||
@qps_retry(qps=1)
|
||||
def matrix(self, coordinates, profile=DEFAULT_PROFILE):
|
||||
validate_profile(profile)
|
||||
validate_coordinates(coordinates,
|
||||
NUM_COORDINATES_MIN, NUM_COORDINATES_MAX)
|
||||
|
||||
coords = marshall_coordinates(coordinates)
|
||||
|
||||
uri = self._uri(coords, profile)
|
||||
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return response.text
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return '{}'
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return '{}'
|
||||
else:
|
||||
raise ServiceException(response.status_code, 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 Mapbox matrix service',
|
||||
te)
|
||||
raise ServiceException('Error getting matrix data from Mapbox',
|
||||
None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to Mapbox matrix service',
|
||||
exception=ce)
|
||||
return '{}'
|
||||
@@ -0,0 +1,129 @@
|
||||
'''
|
||||
Python client for the Mapbox Routing service.
|
||||
'''
|
||||
|
||||
import json
|
||||
import requests
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools import PolyLine
|
||||
from cartodb_services.tools.coordinates import (validate_coordinates,
|
||||
marshall_coordinates)
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
|
||||
BASEURI = ('https://api.mapbox.com/directions/v5/mapbox/{profile}/'
|
||||
'{coordinates}'
|
||||
'?access_token={token}'
|
||||
'&overview={overview}')
|
||||
|
||||
NUM_WAYPOINTS_MIN = 2 # https://www.mapbox.com/api-documentation/#directions
|
||||
NUM_WAYPOINTS_MAX = 25 # https://www.mapbox.com/api-documentation/#directions
|
||||
|
||||
PROFILE_DRIVING_TRAFFIC = 'driving-traffic'
|
||||
PROFILE_DRIVING = 'driving'
|
||||
PROFILE_CYCLING = 'cycling'
|
||||
PROFILE_WALKING = 'walking'
|
||||
DEFAULT_PROFILE = PROFILE_DRIVING
|
||||
|
||||
DEFAULT_OVERVIEW = 'full'
|
||||
|
||||
VALID_PROFILES = [PROFILE_DRIVING_TRAFFIC,
|
||||
PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
PROFILE_WALKING]
|
||||
|
||||
ENTRY_ROUTES = 'routes'
|
||||
ENTRY_GEOMETRY = 'geometry'
|
||||
ENTRY_DURATION = 'duration'
|
||||
ENTRY_DISTANCE = 'distance'
|
||||
|
||||
|
||||
class MapboxRouting(Traceable):
|
||||
'''
|
||||
Python wrapper for the Mapbox Routing service.
|
||||
'''
|
||||
|
||||
def __init__(self, token, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._token = token
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, coordinates, profile=DEFAULT_PROFILE,
|
||||
overview=DEFAULT_OVERVIEW):
|
||||
return BASEURI.format(profile=profile, coordinates=coordinates,
|
||||
token=self._token, overview=overview)
|
||||
|
||||
def _validate_profile(self, profile):
|
||||
if profile not in VALID_PROFILES:
|
||||
raise ValueError('{profile} is not a valid profile. '
|
||||
'Valid profiles are: {valid_profiles}'.format(
|
||||
profile=profile,
|
||||
valid_profiles=', '.join(
|
||||
[x for x in VALID_PROFILES])))
|
||||
|
||||
def _parse_routing_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
if json_response:
|
||||
route = json_response[ENTRY_ROUTES][0] # Force the first route
|
||||
|
||||
geometry = PolyLine().decode(route[ENTRY_GEOMETRY])
|
||||
distance = route[ENTRY_DISTANCE]
|
||||
duration = route[ENTRY_DURATION]
|
||||
|
||||
return MapboxRoutingResponse(geometry, distance, duration)
|
||||
else:
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
|
||||
@qps_retry(qps=1)
|
||||
def directions(self, waypoints, profile=DEFAULT_PROFILE):
|
||||
self._validate_profile(profile)
|
||||
validate_coordinates(waypoints, NUM_WAYPOINTS_MIN, NUM_WAYPOINTS_MAX)
|
||||
|
||||
coordinates = marshall_coordinates(waypoints)
|
||||
|
||||
uri = self._uri(coordinates, profile)
|
||||
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self._parse_routing_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
else:
|
||||
raise ServiceException(response.status_code, 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 Mapbox routing service',
|
||||
te)
|
||||
raise ServiceException('Error getting routing data from Mapbox',
|
||||
None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to Mapbox routing service',
|
||||
exception=ce)
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
|
||||
|
||||
class MapboxRoutingResponse:
|
||||
|
||||
def __init__(self, shape, length, duration):
|
||||
self._shape = shape
|
||||
self._length = length
|
||||
self._duration = duration
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self._shape
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
return self._length
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
return self._duration
|
||||
@@ -0,0 +1,9 @@
|
||||
MAPBOX_ROUTING_APIKEY_ROUNDROBIN = 'mapbox_routing_apikey_roundrobin'
|
||||
MAPBOX_GEOCODER_APIKEY_ROUNDROBIN = 'mapbox_geocoder_apikey_roundrobin'
|
||||
MAPBOX_ISOLINES_APIKEY_ROUNDROBIN = 'mapbox_isolines_apikey_roundrobin'
|
||||
|
||||
TRANSPORT_MODE_TO_MAPBOX = {
|
||||
'car': 'driving',
|
||||
'walk': 'walking',
|
||||
'bicycle': 'cycling',
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
|
||||
|
||||
class WrongParams(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr('Wrong parameters passed: ' + json.dumps(self.value))
|
||||
|
||||
|
||||
class MalformedResult(Exception):
|
||||
def __str__(self):
|
||||
return repr('Result structure is malformed')
|
||||
|
||||
|
||||
class TimeoutException(Exception):
|
||||
def __str__(self):
|
||||
return repr('Timeout requesting to mapzen server')
|
||||
|
||||
|
||||
class ServiceException(Exception):
|
||||
def __init__(self, message, response):
|
||||
self.message = message
|
||||
self.response = response
|
||||
|
||||
def response(self):
|
||||
return self.response
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
@@ -3,8 +3,10 @@ import json
|
||||
import re
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from exceptions import WrongParams, MalformedResult, ServiceException
|
||||
from qps import qps_retry
|
||||
from cartodb_services.tools.exceptions import (WrongParams,
|
||||
MalformedResult,
|
||||
ServiceException)
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools import Coordinate, PolyLine
|
||||
from cartodb_services.metrics import Traceable
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ import json
|
||||
import re
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from exceptions import WrongParams, MalformedResult, ServiceException
|
||||
from qps import qps_retry
|
||||
from cartodb_services.tools.exceptions import (WrongParams,
|
||||
MalformedResult,
|
||||
ServiceException)
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
|
||||
|
||||
class MapzenIsochrones:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import requests
|
||||
import json
|
||||
from qps import qps_retry
|
||||
from exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.metrics import Traceable
|
||||
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ import json
|
||||
import re
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from exceptions import WrongParams, MalformedResult, ServiceException
|
||||
from qps import qps_retry
|
||||
from cartodb_services.tools.exceptions import (WrongParams,
|
||||
MalformedResult,
|
||||
ServiceException)
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools import Coordinate, PolyLine
|
||||
from cartodb_services.metrics import MetricsDataGatherer, Traceable
|
||||
|
||||
|
||||
@@ -28,25 +28,10 @@ def coordinates_to_polygon(coordinates):
|
||||
wkt_coordinates = ','.join(result_coordinates)
|
||||
|
||||
try:
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3) as geom".format(wkt_coordinates)
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3)) 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:
|
||||
country_plan = plpy.prepare("SELECT adm0_a3 as iso3 FROM admin0_synonyms WHERE lower(regexp_replace($1, " \
|
||||
"'[^a-zA-Z\u00C0-\u00ff]+', '', 'g'))::text = name_; ", ['text'])
|
||||
country_result = plpy.execute(country_plan, [country], 1)
|
||||
if country_result:
|
||||
return country_result[0]['iso3']
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
plpy.warning("Can't get the iso3 code from {0}: {1}".format(country, e))
|
||||
return None
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user