Compare commits
54 Commits
python-0.1
...
python-0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc13a35a58 | ||
|
|
ce62b647f8 | ||
|
|
c6c4255242 | ||
|
|
87a2e02721 | ||
|
|
fc1e05658e | ||
|
|
b8ec3dc306 | ||
|
|
4822739fee | ||
|
|
ffdb6524da | ||
|
|
82a7477d37 | ||
|
|
5098b5e9e1 | ||
|
|
41c16d8a54 | ||
|
|
049c8e8657 | ||
|
|
6dca3f4e58 | ||
|
|
d01170471e | ||
|
|
89762c1a7f | ||
|
|
1081e81047 | ||
|
|
29cdd8099a | ||
|
|
c0374f5800 | ||
|
|
677d2acead | ||
|
|
457858a490 | ||
|
|
dde86e985c | ||
|
|
be39f6e9ef | ||
|
|
64c24628a0 | ||
|
|
eb5c7ec5c3 | ||
|
|
435a84f294 | ||
|
|
a9e942a48b | ||
|
|
061956f250 | ||
|
|
2621573d71 | ||
|
|
d7bb31be9a | ||
|
|
3d94d1dfaf | ||
|
|
c364c7f5ed | ||
|
|
b2f9a10035 | ||
|
|
c550a5d4e9 | ||
|
|
b4fa0dd4fc | ||
|
|
f0d96541b6 | ||
|
|
8094e79d0b | ||
|
|
bfd7df8c8a | ||
|
|
1f225e0978 | ||
|
|
e81f005ce9 | ||
|
|
8204bb3451 | ||
|
|
56de523498 | ||
|
|
7fe8b6cccc | ||
|
|
ec3b99f258 | ||
|
|
1a7e99b2fd | ||
|
|
2ad9e508f5 | ||
|
|
a0dd7c7497 | ||
|
|
9cbde7d319 | ||
|
|
f7ecb30384 | ||
|
|
6ca9e87035 | ||
|
|
caa00c63fa | ||
|
|
dae8021efe | ||
|
|
07616c468a | ||
|
|
9abb81d0e7 | ||
|
|
96a147a242 |
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Contributing
|
||||
---
|
||||
|
||||
The issue tracker is at [github.com/CartoDB/dataservices-api](https://github.com/CartoDB/dataservices-api).
|
||||
|
||||
We love pull requests from everyone, see [Contributing to Open Source on GitHub](https://guides.github.com/activities/contributing-to-open-source/#contributing).
|
||||
|
||||
|
||||
## Submitting Contributions
|
||||
|
||||
* You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here](https://carto.com/contributions).
|
||||
19
NEWS.md
19
NEWS.md
@@ -1,3 +1,22 @@
|
||||
March 8th, 2017
|
||||
===============
|
||||
* Version 0.22.0 of the server and version 0.14.0 of the python library
|
||||
* New optional configuration parameters for external services can be provided through `cdb_conf`:
|
||||
- In `heremaps_conf`, under `geocoder.service`: `json_url`, `connect_timeout`, `read_timeout`, `max_retries`, `gen`
|
||||
- In `heremaps_conf`, under `isolines.service`: `base_url`, `connect_timeout`, `read_timeout`, `max_retries`, `isoline_path`
|
||||
- In `mapzen_conf`, under `geocoder.service`: `base_url`, `connect_timeout`, `read_timeout`, `max_retries`
|
||||
- In `mapzen_conf`, under `routing.service`: `base_url`, `connect_timeout`, `read_timeout`
|
||||
- In `mapzen_conf`, under `matrix.service`: `one_to_many_url`, `connect_timeout`, `read_timeout`
|
||||
- In `mapzen_conf`, under `isochrones.service`: `base_url`, `connect_timeout`, `read_timeout`, `max_retries`
|
||||
* Strictly speaking, version 0.14.0 of the python library is not compatible with 0.13.0, but the changes are made on method signatures with default values that were not used from the PG extension.
|
||||
* Improvements to the Mapzen geocoder client, that should yield better results overall. See #342
|
||||
|
||||
February 2st, 2017
|
||||
===================
|
||||
* Version 0.21.0 of the server and version 0.15.0 of the client
|
||||
* Added functions `OBS_GetData` and `OBS_GetMeta`
|
||||
* Default isolines provider changed to `mapzen` instead of `heremaps`
|
||||
|
||||
November 29st, 2016
|
||||
===================
|
||||
* Version 0.20.0 of the server and version 0.12.0 of the python library
|
||||
|
||||
217
README.md
217
README.md
@@ -23,25 +23,26 @@ Steps to deploy a new Data Services API version :
|
||||
|
||||
### Local install instructions
|
||||
|
||||
- install data services geocoder extension
|
||||
- install data services geocoder extension
|
||||
|
||||
```
|
||||
git clone git@github.com:CartoDB/data-services.git
|
||||
git clone https://github.com/CartoDB/data-services.git
|
||||
cd data-services/geocoder/extension
|
||||
sudo make install
|
||||
```
|
||||
|
||||
- install observatory extension
|
||||
|
||||
- install observatory extension
|
||||
|
||||
```
|
||||
git clone git@github.com:CartoDB/observatory-extension.git
|
||||
git clone https://github.com/CartoDB/observatory-extension.git
|
||||
cd observatory
|
||||
sudo make install
|
||||
```
|
||||
|
||||
- install server and client extensions
|
||||
|
||||
|
||||
```
|
||||
# in data-services repo root path:
|
||||
cd client && sudo make install
|
||||
cd server/extension && sudo make install
|
||||
```
|
||||
@@ -49,7 +50,8 @@ Steps to deploy a new Data Services API version :
|
||||
- install python library
|
||||
|
||||
```
|
||||
cd server/lib/python/cartodb_services && sudo pip install --upgrade .
|
||||
# in data-services repo root path:
|
||||
cd server/lib/python/cartodb_services && sudo pip install . --upgrade
|
||||
```
|
||||
|
||||
- install extensions in user database
|
||||
@@ -62,39 +64,184 @@ Steps to deploy a new Data Services API version :
|
||||
create extension cdb_dataservices_client;
|
||||
```
|
||||
|
||||
- add configuration for different services in server database
|
||||
|
||||
### Server configuration
|
||||
|
||||
```
|
||||
# If sentinel is used:
|
||||
SELECT CDB_Conf_SetConf('redis_metadata_config', '{"sentinel_host": "localhost", "sentinel_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
SELECT CDB_Conf_SetConf('redis_metrics_config', '{"sentinel_host": "localhost", "sentinel_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
|
||||
# If sentinel is not used
|
||||
SELECT CDB_Conf_SetConf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 6379, "sentinel_master_id": "", "timeout": 0.1, "redis_db": 5}');
|
||||
SELECT CDB_Conf_SetConf('redis_metrics_config', '{"redis_host": "localhost", "redis_port": 6379, "sentinel_master_id": "", "timeout": 0.1, "redis_db": 5}');
|
||||
|
||||
SELECT CDB_Conf_SetConf('heremaps_conf', '{"geocoder": {"app_id": "here_geocoder_app_id", "app_code": "here_geocoder_app_code", "geocoder_cost_per_hit": "1"}, "isolines" : {"app_id": "here_isolines_app_id", "app_code": "here_geocoder_app_code"}}');
|
||||
SELECT CDB_Conf_SetConf('user_config', '{"is_organization": false, "entity_name": "<YOUR_USERNAME>"}')
|
||||
SELECT CDB_Conf_SetConf('mapzen_conf', '{"routing": {"api_key": "valhalla_app_key", "monthly_quota": 999999}, "geocoder": {"api_key": "search_app_key", "monthly_quota": 999999}, "matrix": {"api_key": "[your_matrix_key]", "monthly_quota": 1500000}}');
|
||||
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"]}');
|
||||
SELECT CDB_Conf_SetConf('data_observatory_conf', '{"connection": {"whitelist": [], "production": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}}');
|
||||
Configuration for the different services must be stored in the server database using `CDB_Conf_SetConf()`.
|
||||
|
||||
# Environment to decide: rollbar message, which servers for third party use, etc. If not setted uses production by default (current behavior)
|
||||
SELECT CDB_Conf_SetConf('server_conf', '{"environment": "[development|staging|production]"}')
|
||||
```
|
||||
#### Redis configuration
|
||||
|
||||
- configure the user DB:
|
||||
If sentinel is used:
|
||||
|
||||
```sql
|
||||
-- Point to the dataservices server DB (you can use a specific database for the server or your same user's):
|
||||
SELECT CDB_Conf_SetConf('geocoder_server_config', '{ "connection_str": "host=localhost port=5432 dbname=<SERVER_DB_NAME> user=postgres"}');
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'redis_metadata_config',
|
||||
'{"sentinel_host": "localhost", "sentinel_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}'
|
||||
);
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'redis_metrics_config',
|
||||
'{"sentinel_host": "localhost", "sentinel_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}'
|
||||
);
|
||||
```
|
||||
|
||||
SELECT CDB_Conf_SetConf('user_config', '{"is_organization": false, "entity_name": "<YOUR_USERNAME>"}');
|
||||
```
|
||||
If sentinel is not used:
|
||||
|
||||
- configure the search path in order to be able to execute the functions without using the schema:
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'redis_metadata_config',
|
||||
'{"redis_host": "localhost", "redis_port": 6379, "sentinel_master_id": "", "timeout": 0.1, "redis_db": 5}'
|
||||
);
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'redis_metrics_config',
|
||||
'{"redis_host": "localhost", "redis_port": 6379, "sentinel_master_id": "", "timeout": 0.1, "redis_db": 5}'
|
||||
);
|
||||
```
|
||||
|
||||
```
|
||||
ALTER ROLE "<USER_ROLE>" SET search_path="$user", public, cartodb, cdb_dataservices_client;
|
||||
```
|
||||
#### Users/Organizations
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'user_config',
|
||||
'{"is_organization": false, "entity_name": "<YOUR_USERNAME>"}'
|
||||
);
|
||||
```
|
||||
|
||||
#### HERE configuration
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'heremaps_conf',
|
||||
'{"geocoder": {"app_id": "here_geocoder_app_id", "app_code": "here_geocoder_app_code", "geocoder_cost_per_hit": "1"}, "isolines" : {"app_id": "here_isolines_app_id", "app_code": "here_geocoder_app_code"}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Mapzen configuration
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapzen_conf',
|
||||
'{"routing": {"api_key": "valhalla_app_key", "monthly_quota": 999999}, "geocoder": {"api_key": "search_app_key", "monthly_quota": 999999}, "matrix": {"api_key": "[your_matrix_key]", "monthly_quota": 1500000}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Data Observatory
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'data_observatory_conf',
|
||||
'{"connection": {"whitelist": [], "production": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Logger
|
||||
|
||||
```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"]}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Environment
|
||||
|
||||
The execution environment (development/staging/production) affects rollbar messages and other details.
|
||||
The production environment is used by default.
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'server_conf',
|
||||
'{"environment": "[development|staging|production]"}'
|
||||
);
|
||||
```
|
||||
### Server optional configuration
|
||||
|
||||
External services (Mapzen, Here) can have optional configuration, which is only needed for using non-standard services, such as on-premise installations. We can add the service parameters to an existing configuration like this:
|
||||
|
||||
```
|
||||
# Here geocoder
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'heremaps_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('heremaps_conf')),
|
||||
'{geocoder, service}',
|
||||
'{"json_url":"https://geocoder.api.here.com/6.2/geocode.json","gen":9,"read_timeout":60,"connect_timeout":10,"max_retries":1}'
|
||||
)::json
|
||||
);
|
||||
|
||||
# Here isolines
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'heremaps_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('heremaps_conf')),
|
||||
'{isolines, service}',
|
||||
'{"base_url":"https://isoline.route.api.here.com","isoline_path":"/routing/7.2/calculateisoline.json","read_timeout":60,"connect_timeout":10,"max_retries":1}'
|
||||
)::json
|
||||
);
|
||||
|
||||
# Mapzen geocoder
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapzen_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('mapzen_conf')),
|
||||
'{geocoder, service}',
|
||||
'{"base_url":"https://search.mapzen.com/v1/search","read_timeout":60,"connect_timeout":10,"max_retries":1}'
|
||||
)::json
|
||||
);
|
||||
|
||||
# Mapzen isochrones
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapzen_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('mapzen_conf')),
|
||||
'{isochrones, service}',
|
||||
'{"base_url":"https://matrix.mapzen.com/isochrone","read_timeout":60,"connect_timeout":10,"max_retries":1}'
|
||||
)::json
|
||||
);
|
||||
|
||||
# Mapzen isolines (matrix service)
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapzen_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('mapzen_conf')),
|
||||
'{matrix, service}',
|
||||
'{"base_url":"https://matrix.mapzen.com/one_to_many","read_timeout":60,"connect_timeout":10}'
|
||||
)::json
|
||||
);
|
||||
|
||||
# Mapzen routing
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'mapzen_conf',
|
||||
jsonb_set(
|
||||
to_jsonb(CDB_Conf_GetConf('mapzen_conf')),
|
||||
'{routing, service}',
|
||||
'{"base_url":"https://valhalla.mapzen.com/route","read_timeout":60,"connect_timeout":10}'
|
||||
)::json
|
||||
);
|
||||
```
|
||||
### User database configuration
|
||||
|
||||
User (client) databases need also some configuration so that the client extension can access the server:
|
||||
#### Users/Organizations
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf('user_config', '{"is_organization": false, "entity_name": "<YOUR_USERNAME>"}');
|
||||
```
|
||||
|
||||
#### Dataservices server
|
||||
|
||||
The `geocoder_server_config` (the name is not accurate for historical reasons) entry points
|
||||
to the dataservices server DB (you can use a specific database for the server or your same user's):
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'geocoder_server_config',
|
||||
'{ "connection_str": "host=localhost port=5432 dbname=<SERVER_DB_NAME> user=postgres"}'
|
||||
);
|
||||
```
|
||||
#### Search path
|
||||
|
||||
The search path must be configured in order to be able to execute the functions without using the schema:
|
||||
|
||||
```sql
|
||||
ALTER ROLE "<USER_ROLE>" SET search_path="$user", public, cartodb, cdb_dataservices_client;
|
||||
```
|
||||
|
||||
204
client/cdb_dataservices_client--0.14.1--0.15.0.sql
Normal file
204
client/cdb_dataservices_client--0.14.1--0.15.0.sql
Normal file
@@ -0,0 +1,204 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.15.0'" to load this file. \quit
|
||||
|
||||
-- Make sure we have a sane search path to create/update the extension
|
||||
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomvals geomval[] ,params json ,merge boolean DEFAULT true)
|
||||
RETURNS TABLE(id int, data json) AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getdata (geomrefs text[] ,params json)
|
||||
RETURNS TABLE(id text, data json) AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.obs_getmeta (geom_ref Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL)
|
||||
RETURNS json AS $$
|
||||
DECLARE
|
||||
ret json;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomvals geomval[] ,params json ,merge boolean DEFAULT true)
|
||||
RETURNS TABLE(id int, data json) AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomvals, params, merge);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
END;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
--
|
||||
-- Exception-safe private DataServices API function
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata_exception_safe (geomrefs text[] ,params json)
|
||||
RETURNS TABLE(id text, data json) AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._obs_getdata(username, orgname, geomrefs, params);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
END;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
--
|
||||
-- Exception-safe private DataServices API function
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta_exception_safe (geom_ref Geometry(Geometry, 4326) ,params json ,max_timespan_rank integer DEFAULT NULL ,max_score_rank integer DEFAULT NULL ,target_geoms integer DEFAULT NULL)
|
||||
RETURNS json AS $$
|
||||
DECLARE
|
||||
ret json;
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms) INTO ret;
|
||||
RETURN ret;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
RETURN ret;
|
||||
END;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, organization_name text, geomvals geomval[], params json, merge boolean DEFAULT true)
|
||||
RETURNS TABLE(id int, data json) AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.obs_getdata (username, organization_name, geomvals, params, merge);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getdata (username text, organization_name text, geomrefs text[], params json)
|
||||
RETURNS TABLE(id text, data json) AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.obs_getdata (username, organization_name, geomrefs, params);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._obs_getmeta (username text, organization_name text, geom_ref Geometry(Geometry, 4326), params json, max_timespan_rank integer DEFAULT NULL, max_score_rank integer DEFAULT NULL, target_geoms integer DEFAULT NULL)
|
||||
RETURNS json AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.obs_getmeta (username, organization_name, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
17
client/cdb_dataservices_client--0.15.0--0.14.1.sql
Normal file
17
client/cdb_dataservices_client--0.15.0--0.14.1.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.14.1'" to load this file. \quit
|
||||
|
||||
-- Make sure we have a sane search path to create/update the extension
|
||||
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (text, text, geomval[], json, boolean);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata (text, text, text[], json);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta (text, text, Geometry(Geometry, 4326), json, integer, integer, integer);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata_exception_safe (geomval[], json, boolean);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getdata_exception_safe (text[], json);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._obs_getmeta_exception_safe (Geometry(Geometry, 4326), json , integer, integer, integer);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getdata (geomval[], json, boolean);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getdata (text[], json);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.obs_getmeta (Geometry(Geometry, 4326), json, integer, integer, integer);
|
||||
3985
client/cdb_dataservices_client--0.15.0.sql
Normal file
3985
client/cdb_dataservices_client--0.15.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.14.1'
|
||||
default_version = '0.15.0'
|
||||
requires = 'plproxy, cartodb'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_client
|
||||
|
||||
@@ -261,6 +261,38 @@
|
||||
- { name: boundary_id, type: text}
|
||||
- { name: time_span, type: text, default: 'NULL'}
|
||||
|
||||
- name: obs_getdata
|
||||
return_type: TABLE(id int, data json)
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
table_fields:
|
||||
- { name: id, type: integer }
|
||||
- { name: data, type: json }
|
||||
params:
|
||||
- { name: geomvals, type: "geomval[]" }
|
||||
- { name: params, type: json }
|
||||
- { name: merge, type: boolean, default: true }
|
||||
|
||||
- name: obs_getdata
|
||||
return_type: TABLE(id text, data json)
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
table_fields:
|
||||
- { name: id, type: text }
|
||||
- { name: data, type: json }
|
||||
params:
|
||||
- { name: geomrefs, type: "text[]" }
|
||||
- { name: params, type: json }
|
||||
|
||||
- name: obs_getmeta
|
||||
return_type: json
|
||||
params:
|
||||
- { name: geom_ref, type: "Geometry(Geometry, 4326)" }
|
||||
- { name: params, type: json }
|
||||
- { name: max_timespan_rank, type: integer, default: 'NULL' }
|
||||
- { name: max_score_rank, type: integer, default: 'NULL' }
|
||||
- { name: target_geoms, type: integer, default: 'NULL' }
|
||||
|
||||
- name: obs_getcategory
|
||||
return_type: text
|
||||
params:
|
||||
@@ -388,4 +420,4 @@
|
||||
return_type: BOOLEAN
|
||||
params:
|
||||
- { name: service, type: TEXT }
|
||||
- { name: input_size, type: NUMERIC }
|
||||
- { name: input_size, type: NUMERIC }
|
||||
|
||||
@@ -173,6 +173,27 @@ BEGIN
|
||||
RETURN QUERY SELECT '0106000020E61000000100000001030000000100000019000000DD96C805677C52C0CBD8D0CDFE5A44407A19C5724B7C52C033BF9A03045B4440FF59F3E32F7C52C0CB290131095B4440247EC51A2E7C52C0548B8862F25A44401FF5D72B2C7C52C0CB811E6ADB5A444049F086342A7C52C09CC3B5DAC35A444044679945287C52C01F680586AC5A444012D90759167C52C09430D3F6AF5A44405698BED7107C52C04759BF99985A4440DEE522BE137C52C00664AF777F5A4440F92EA52E197C52C09BA73AE4665A4440C558A65F227C52C0D80DDB16655A4440373465A71F7C52C065A71FD4455A44404AED45B41D7C52C0785DBF60375A444083A3E4D5397C52C09946938B315A4440F2B4FCC0557C52C01FF5D72B2C5A444026C286A7577C52C02BDD5D67435A44405BCF108E597C52C0C651B9895A5A444030D461855B7C52C0D1393FC5715A444065E1EB6B5D7C52C078280AF4895A44403AE63C635F7C52C07D1F0E12A25A44403F6F2A52617C52C05983F755B95A44405C3AE63C637C52C04852D2C3D05A444049810530657C52C0FAEE5696E85A4440DD96C805677C52C0CBD8D0CDFE5A4440'::geometry as the_geom, '36047049300'::text as geom_refs;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getmeta(username text, orgname text, geom geometry(Geometry, 4326), params JSON, max_timespan_rank INTEGER DEFAULT NULL, max_score_rank INTEGER DEFAULT NULL, target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getmeta invoked with params (%, %, %, %, %, %, %)', username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms;
|
||||
RETURN '[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]'::JSON;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomrefs text[], params json)
|
||||
RETURNS TABLE (id TEXT, data JSON) AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %)', username, orgname, geomrefs, params;
|
||||
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomvals geomval[], params json, merge boolean default true)
|
||||
RETURNS TABLE (id TEXT, data JSON) AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %, %)', username, orgname, geomvals, params, merge;
|
||||
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
-- Exercise the public and the proxied function
|
||||
SELECT obs_get_demographic_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '2009 - 2013'::text, '"us.census.tiger".block_group'::text);
|
||||
NOTICE: cdb_dataservices_client._obs_get_demographic_snapshot(5): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_get_demographic_snapshot invoked with params (test_user, <NULL>, 0101000020E6100000548B8862F27B52C0DDD1FF722D5A4440, 2009 - 2013, "us.census.tiger".block_group)
|
||||
@@ -337,3 +358,34 @@ CONTEXT: PL/pgSQL function obs_getavailableboundaries(geometry,text) line 16 at
|
||||
(us.census.tiger.place,"Incorporated places are those reported to the Census Bureau as legally in existence as of January 1, 2010, as reported in the latest Boundary and Annexation Survey (BAS), under the laws of their respective states.",2014,obs_7c9493c41fa8f4bd178ab993ea3d5891c1977667)
|
||||
(1 row)
|
||||
|
||||
SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]', 1, 1, 1000);
|
||||
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001"}], 1, 1, 1000)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
|
||||
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
|
||||
obs_getmeta
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]
|
||||
(1 row)
|
||||
|
||||
SELECT obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}]', 1, 1, 1000));
|
||||
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}], 1, 1, 1000)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
|
||||
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
|
||||
NOTICE: cdb_dataservices_client._obs_getdata(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getdata invoked with params (test_user, <NULL>, {36047}, [{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}])
|
||||
CONTEXT: PL/pgSQL function obs_getdata(text[],json) line 16 at RETURN QUERY
|
||||
obs_getdata
|
||||
--------------------------------------------
|
||||
(36047,"[{""value"" : 10349.1547875017}]")
|
||||
(1 row)
|
||||
|
||||
SELECT obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]'));
|
||||
NOTICE: cdb_dataservices_client._obs_getmeta(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getmeta invoked with params (test_user, <NULL>, 0101000020E61000009A999999997952C09A99999999594440, [{"numer_id": "us.census.acs.B01003001"}], <NULL>, <NULL>, <NULL>)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._obs_getmeta(username, orgname, geom_ref, params, max_timespan_rank, max_score_rank, target_geoms)"
|
||||
PL/pgSQL function obs_getmeta(geometry,json,integer,integer,integer) line 16 at SQL statement
|
||||
NOTICE: cdb_dataservices_client._obs_getdata(5): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.obs_getdata invoked with params (test_user, <NULL>, {"(0101000020E61000009A999999997952C09A99999999594440,1)"}, [{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}], t)
|
||||
CONTEXT: PL/pgSQL function obs_getdata(geomval[],json,boolean) line 16 at RETURN QUERY
|
||||
obs_getdata
|
||||
--------------------------------------------
|
||||
(36047,"[{""value"" : 10349.1547875017}]")
|
||||
(1 row)
|
||||
|
||||
|
||||
@@ -194,6 +194,30 @@ BEGIN
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getmeta(username text, orgname text, geom geometry(Geometry, 4326), params JSON, max_timespan_rank INTEGER DEFAULT NULL, max_score_rank INTEGER DEFAULT NULL, target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getmeta invoked with params (%, %, %, %, %, %, %)', username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms;
|
||||
RETURN '[{"id" : 1, "numer_id" : "us.census.acs.B01003001", "timespan_rank" : 1, "score_rank" : 1, "score" : 19.9580760018781868330120152747832081562684, "numer_aggregate" : "sum", "numer_colname" : "total_pop", "numer_geomref_colname" : "geoid", "numer_tablename" : "obs_209d3476ef8eaaa18e597cabcf1bdb627f37aa5e", "numer_type" : "Numeric", "denom_aggregate" : null, "denom_colname" : null, "denom_geomref_colname" : null, "denom_tablename" : null, "denom_type" : null, "geom_colname" : "the_geom", "geom_geomref_colname" : "geoid", "geom_tablename" : "obs_78fb6c1d6ff6505225175922c2c389ce48d7632c", "geom_type" : "Geometry", "geom_timespan" : "2015", "numer_timespan" : "2011 - 2015", "numer_name" : "Total Population", "denom_name" : null, "geom_name" : "US Census Block Groups", "normalization" : null, "denom_id" : null, "geom_id" : "us.census.tiger.block_group"}]'::JSON;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomrefs text[], params json)
|
||||
RETURNS TABLE (id TEXT, data JSON) AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %)', username, orgname, geomrefs, params;
|
||||
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.obs_getdata(username text, orgname text, geomvals geomval[], params json, merge boolean default true)
|
||||
RETURNS TABLE (id TEXT, data JSON) AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.obs_getdata invoked with params (%, %, %, %, %)', username, orgname, geomvals, params, merge;
|
||||
RETURN QUERY SELECT '36047'::TEXT AS id, '[{"value" : 10349.1547875017}]'::JSON AS data;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
-- Exercise the public and the proxied function
|
||||
SELECT obs_get_demographic_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '2009 - 2013'::text, '"us.census.tiger".block_group'::text);
|
||||
SELECT obs_get_segment_snapshot(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326), '"us.census.tiger".block_group'::text);
|
||||
@@ -214,3 +238,7 @@ SELECT obs_getuscensuscategory(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326
|
||||
SELECT obs_getpopulation(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326));
|
||||
SELECT obs_search('total_pop'::text);
|
||||
SELECT obs_getavailableboundaries(ST_SetSRID(ST_Point(-73.936669 , 40.704512), 4326));
|
||||
SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]', 1, 1, 1000);
|
||||
SELECT obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001", "geom_id": "us.census.tiger.county"}]', 1, 1, 1000));
|
||||
SELECT obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), '[{"numer_id": "us.census.acs.B01003001"}]'));
|
||||
|
||||
|
||||
@@ -12,3 +12,124 @@ Quota consumption is calculated based on the number of request made for each fun
|
||||
**Note:** Queries to the Data Services API, and any of its functions in your maps, may be forbidden in the future
|
||||
|
||||
* It is advised to store results of these queries into your datasets, and refresh them as needed. This ensure more control of quota credits for your account
|
||||
|
||||
|
||||
## Quota Information Functions
|
||||
|
||||
There are several SQL functions that you can run to obtain quota information about your services.
|
||||
|
||||
## cdb_service_quota_info()
|
||||
|
||||
Returns information about per-service quotas (available and used) for the account.
|
||||
|
||||
#### Returns
|
||||
|
||||
This function returns a set of service quota information records, one per service.
|
||||
|
||||
Name | Type | Description
|
||||
--------------- | --------- | ------------
|
||||
`service` | `text` | Type of service.
|
||||
`monthly_quota` | `numeric` | Quota available to the user (number of calls) per monthly period.
|
||||
`used_quota` | `numeric` | Quota used by the user in the present period.
|
||||
`soft_limit` | `boolean` | Set to `True`, if the user has *soft-limit* quota.
|
||||
`provider` | `text` | Service provider for this type of service.
|
||||
|
||||
Service Types:
|
||||
|
||||
* `'isolines'` [Isoline/Isochrones (isochrone/isodistance lines) service](https://carto.com/docs/carto-engine/dataservices-api/isoline_functions/)
|
||||
* `'hires_geocoder'` [Street level geocoding](https://carto.com/docs/carto-engine/dataservices-api/geocoding-functions#street-level-geocoder)
|
||||
* `'routing'` [Routing functions](https://carto.com/docs/carto-engine/dataservices-api/routing_functions/)
|
||||
* `'observatory'` Data Observatory services ([demographic](https://carto.com/docs/carto-engine/dataservices-api/demographic_functions/) and [segmentation](https://carto.com/docs/carto-engine/dataservices-api/segmentation_functions/) functions)
|
||||
|
||||
**Notes**
|
||||
|
||||
Users who have *soft-quota* activated never run out of quota, but they may incur extra
|
||||
expenses when the regular quota is exceeded.
|
||||
|
||||
A zero value of `monthly_quota` indicates that the service has not been activated for the user.
|
||||
|
||||
#### Example
|
||||
|
||||
```sql
|
||||
SELECT * FROM cdb_service_quota_info();
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```sql
|
||||
service | monthly_quota | used_quota | soft_limit | provider
|
||||
----------------+---------------+------------+------------+------------------
|
||||
isolines | 100 | 0 | f | mapzen
|
||||
hires_geocoder | 100 | 0 | f | mapzen
|
||||
routing | 50 | 0 | f | mapzen
|
||||
observatory | 0 | 0 | f | data observatory
|
||||
(4 rows)
|
||||
|
||||
```
|
||||
|
||||
In this case, notice that the user has no access to the observatory services. All quotas are *hard-limited* (no soft limits), and no quota has been used in the present period.
|
||||
|
||||
## cdb_enough_quota(service text ,input_size numeric)
|
||||
|
||||
This function is useful to check if enough quota is available for completing a job.
|
||||
|
||||
This is specifically relevant if a number of service calls are to be performed inside a transaction. If any of the calls fails (due to exceeded quota), the transaction will be rolled back; resulting in partial quota consumption, but no saved results from the services consumed.
|
||||
|
||||
**Tip:** If you are requesting repeating quota-consuming functions (e.g. to geocode a whole table), it is extremely important to check if enough quota is available to complete the job _before_ applying this function.
|
||||
|
||||
Note that some services consume more than one credit per row/call. For example, isolines (with more than one range/track) consume (N rows x M ranges) credits; indicating that the input size should be N x M.
|
||||
|
||||
#### Arguments
|
||||
|
||||
Name | Type | Description
|
||||
------------ | --------- | -----------
|
||||
`service` | `text` | Service to check; see the list of valid services above.
|
||||
`input_size` | `numeric` | Number of service calls required, i.e. size of the input to be processed.
|
||||
|
||||
#### Returns
|
||||
|
||||
The result is a *boolean* value. A *true* value (`'t'`) indicates that the available quota
|
||||
for the service is enough for the input size requested. A *false* value (`'f'`) indicates
|
||||
insufficient quota.
|
||||
|
||||
#### Example
|
||||
|
||||
Suppose you want to geocode a whole table. In order to check that you have enough quota, and avoid a "quota exhausted" exception, first find out how many records you need to geocode:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM {tablename} WHERE {street_name_column} IS NOT NULL;
|
||||
```
|
||||
|
||||
Result: here's a sample result of 10000 records:
|
||||
|
||||
```sql
|
||||
count
|
||||
-------
|
||||
10000
|
||||
(1 row)
|
||||
```
|
||||
|
||||
The result shows how much quota is needed to complete this job. In this case,
|
||||
each call to `cdb_geocode_street_point` consumes one quota credit. This indicates that we need one credit per row to geocode the whole table.
|
||||
|
||||
```sql
|
||||
SELECT cdb_enough_quota('hires_geocoder', {number_of_records});
|
||||
```
|
||||
|
||||
The result is similar to the following:
|
||||
|
||||
```sql
|
||||
cdb_enough_quota
|
||||
------------------
|
||||
t
|
||||
```
|
||||
|
||||
If the result of this query is *true* (`'t'`), you can safely proceed. If a *false* value (`'f'`) is returned, you should avoid processing any more requests that consume quota. Apply the `cdb_service_quota_info` function to get more information about your services.
|
||||
|
||||
**Note:** Remember to apply any filtering conditions that you used to count the records (in this case, `{street_name_column} IS NOT NULL`):
|
||||
|
||||
|
||||
```sql
|
||||
UPDATE {tablename} SET the_geom = cdb_geocode_street_point({street_name_column})
|
||||
WHERE {street_name_column} IS NOT NULL;
|
||||
```
|
||||
|
||||
@@ -38,7 +38,7 @@ all: $(DATA)
|
||||
.PHONY: release
|
||||
release: $(EXTENSION).control $(SOURCES_DATA)
|
||||
test -n "$(NEW_VERSION)" # $$NEW_VERSION VARIABLE MISSING. Eg. make release NEW_VERSION=0.x.0
|
||||
mv *.sql old_versions
|
||||
git mv *.sql old_versions
|
||||
$(SED) $(REPLACEMENTS) $(EXTENSION).control
|
||||
cat $(SOURCES_DATA_DIR)/*.sql > $(EXTENSION)--$(NEW_VERSION).sql
|
||||
$(ERB) version=$(NEW_VERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(EXTVERSION)--$(NEW_VERSION).sql
|
||||
|
||||
292
server/extension/cdb_dataservices_server--0.21.0--0.22.0.sql
Normal file
292
server/extension/cdb_dataservices_server--0.21.0--0.22.0.sql
Normal file
@@ -0,0 +1,292 @@
|
||||
--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.22.0'" to load this file. \quit
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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 $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse
|
||||
from cartodb_services.mapzen.types import polyline_to_linestring
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
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)
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MapzenRouting(user_routing_config.mapzen_api_key, logger, user_routing_config.mapzen_service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
logger.info("Empty origin or destination")
|
||||
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))
|
||||
|
||||
resp = client.calculate_route_point_to_point(waypoint_coords, mode, options, units)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, resp.duration]
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to calculate mapzen routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate mapzen routing')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
|
||||
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.here import HereMapsGeocoder
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_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)
|
||||
# -- Check the quota
|
||||
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')
|
||||
|
||||
try:
|
||||
geocoder = HereMapsGeocoder(user_geocoder_config.heremaps_app_id, user_geocoder_config.heremaps_app_code, logger, user_geocoder_config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
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 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:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
|
||||
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 $$
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger
|
||||
from cartodb_services.refactor.tools.logger import LoggerConfigBuilder
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
from cartodb_services.refactor.core.environment import ServerEnvironmentBuilder
|
||||
from cartodb_services.refactor.backend.server_config import ServerConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.user_config import UserConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.org_config import OrgConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.redis_metrics_connection import RedisMetricsConnectionFactory
|
||||
|
||||
server_config_backend = ServerConfigBackendFactory().get()
|
||||
environment = ServerEnvironmentBuilder(server_config_backend).get()
|
||||
user_config_backend = UserConfigBackendFactory(username, environment, server_config_backend).get()
|
||||
org_config_backend = OrgConfigBackendFactory(orgname, environment, server_config_backend).get()
|
||||
|
||||
logger_config = LoggerConfigBuilder(environment, server_config_backend).get()
|
||||
logger = Logger(logger_config)
|
||||
|
||||
mapzen_geocoder_config = MapzenGeocoderConfigBuilder(server_config_backend, user_config_backend, org_config_backend, username, orgname).get()
|
||||
|
||||
redis_metrics_connection = RedisMetricsConnectionFactory(environment, server_config_backend).get()
|
||||
|
||||
quota_service = QuotaService(mapzen_geocoder_config, redis_metrics_connection)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(mapzen_geocoder_config.mapzen_api_key, logger, mapzen_geocoder_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:
|
||||
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 street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MatrixClient, MapzenIsolines
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger, user_isolines_routing_config.mapzen_matrix_service_params)
|
||||
mapzen_isolines = MapzenIsolines(client, logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = {'lat': lat, 'lon': lon}
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations])
|
||||
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
quota_service.increment_success_service_use()
|
||||
quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get mapzen isolines')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
from cartodb_services.mapzen.types import coordinates_to_polygon
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
# -- Check the quota
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
|
||||
logger, user_isolines_routing_config.mapzen_isochrones_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 = {'lat': lat, 'lon': lon}
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
quota_service.increment_success_service_use()
|
||||
quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get mapzen isochrones')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
292
server/extension/cdb_dataservices_server--0.22.0--0.21.0.sql
Normal file
292
server/extension/cdb_dataservices_server--0.22.0--0.21.0.sql
Normal file
@@ -0,0 +1,292 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.21.0'" to load this file. \quit
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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 $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse
|
||||
from cartodb_services.mapzen.types import polyline_to_linestring
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
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)
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MapzenRouting(user_routing_config.mapzen_api_key, logger)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
logger.info("Empty origin or destination")
|
||||
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))
|
||||
|
||||
resp = client.calculate_route_point_to_point(waypoint_coords, mode, options, units)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, resp.duration]
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to calculate mapzen routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate mapzen routing')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
|
||||
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.here import HereMapsGeocoder
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_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)
|
||||
# -- Check the quota
|
||||
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')
|
||||
|
||||
try:
|
||||
geocoder = HereMapsGeocoder(user_geocoder_config.heremaps_app_id, user_geocoder_config.heremaps_app_code, logger)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
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 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:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
|
||||
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 $$
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.mapzen.types import country_to_iso3
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger
|
||||
from cartodb_services.refactor.tools.logger import LoggerConfigBuilder
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
from cartodb_services.refactor.core.environment import ServerEnvironmentBuilder
|
||||
from cartodb_services.refactor.backend.server_config import ServerConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.user_config import UserConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.org_config import OrgConfigBackendFactory
|
||||
from cartodb_services.refactor.backend.redis_metrics_connection import RedisMetricsConnectionFactory
|
||||
|
||||
server_config_backend = ServerConfigBackendFactory().get()
|
||||
environment = ServerEnvironmentBuilder(server_config_backend).get()
|
||||
user_config_backend = UserConfigBackendFactory(username, environment, server_config_backend).get()
|
||||
org_config_backend = OrgConfigBackendFactory(orgname, environment, server_config_backend).get()
|
||||
|
||||
logger_config = LoggerConfigBuilder(environment, server_config_backend).get()
|
||||
logger = Logger(logger_config)
|
||||
|
||||
mapzen_geocoder_config = MapzenGeocoderConfigBuilder(server_config_backend, user_config_backend, org_config_backend, username, orgname).get()
|
||||
|
||||
redis_metrics_connection = RedisMetricsConnectionFactory(environment, server_config_backend).get()
|
||||
|
||||
quota_service = QuotaService(mapzen_geocoder_config, redis_metrics_connection)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(mapzen_geocoder_config.mapzen_api_key, logger)
|
||||
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:
|
||||
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 street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MatrixClient, MapzenIsolines
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger)
|
||||
mapzen_isolines = MapzenIsolines(client, logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = {'lat': lat, 'lon': lon}
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapzen_isolines.calculate_isodistance(origin, mode, r)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l['lon'], l['lat']) for l in locations])
|
||||
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
quota_service.increment_success_service_use()
|
||||
quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to get mapzen isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get mapzen isolines')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
import json
|
||||
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
from cartodb_services.mapzen.types import coordinates_to_polygon
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
# -- Check the quota
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
|
||||
logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = {'lat': lat, 'lon': lon}
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
quota_service.increment_success_service_use()
|
||||
quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use()
|
||||
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get mapzen isochrones')
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
2900
server/extension/cdb_dataservices_server--0.22.0.sql
Normal file
2900
server/extension/cdb_dataservices_server--0.22.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.20.0'
|
||||
default_version = '0.22.0'
|
||||
requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_server
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.21.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomvals geomval[],
|
||||
params JSON,
|
||||
merge BOOLEAN DEFAULT True)
|
||||
RETURNS TABLE (
|
||||
id INT,
|
||||
data JSON
|
||||
) AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomvals geomval[],
|
||||
params JSON,
|
||||
merge BOOLEAN DEFAULT True)
|
||||
RETURNS TABLE (
|
||||
id INT,
|
||||
data JSON
|
||||
) AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_obs_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
with metrics('obs_getdata', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge])
|
||||
empty_results = len(geomvals) - len(result)
|
||||
if empty_results > 0:
|
||||
quota_service.increment_empty_service_use(empty_results)
|
||||
if result:
|
||||
quota_service.increment_success_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use(len(geomvals))
|
||||
logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetData')
|
||||
finally:
|
||||
quota_service.increment_total_service_use(len(geomvals))
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomrefs TEXT[],
|
||||
params JSON)
|
||||
RETURNS TABLE (
|
||||
id TEXT,
|
||||
data JSON
|
||||
) AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomrefs TEXT[],
|
||||
params JSON)
|
||||
RETURNS TABLE (
|
||||
id TEXT,
|
||||
data JSON
|
||||
) AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_obs_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
with metrics('obs_getdata', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geomrefs, params])
|
||||
empty_results = len(geomrefs) - len(result)
|
||||
if empty_results > 0:
|
||||
quota_service.increment_empty_service_use(empty_results)
|
||||
if result:
|
||||
quota_service.increment_success_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use(len(geomrefs))
|
||||
exc_info = sys.exc_info()
|
||||
logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2]))
|
||||
logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetData')
|
||||
finally:
|
||||
quota_service.increment_total_service_use(len(geomrefs))
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geom Geometry(Geometry, 4326),
|
||||
params JSON,
|
||||
max_timespan_rank INTEGER DEFAULT NULL,
|
||||
max_score_rank INTEGER DEFAULT NULL,
|
||||
target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geom Geometry(Geometry, 4326),
|
||||
params JSON,
|
||||
max_timespan_rank INTEGER DEFAULT NULL,
|
||||
max_score_rank INTEGER DEFAULT NULL,
|
||||
target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('obs_getmeta', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms])
|
||||
if result:
|
||||
return result[0]['meta']
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetMeta')
|
||||
$$ LANGUAGE plpythonu;
|
||||
@@ -0,0 +1,11 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.20.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetData(TEXT, TEXT, geomval[], JSON, BOOLEAN);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetData(TEXT, TEXT, geomval[], JSON, BOOLEAN);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetData(TEXT, TEXT, TEXT[], JSON);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetData(TEXT, TEXT, TEXT[], JSON);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.OBS_GetMeta(TEXT, TEXT, Geometry(Geometry, 4326), JSON, INTEGER, INTEGER, INTEGER);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._OBS_GetMeta(TEXT, TEXT, Geometry(Geometry, 4326), JSON, INTEGER, INTEGER, INTEGER);
|
||||
2900
server/extension/old_versions/cdb_dataservices_server--0.21.0.sql
Normal file
2900
server/extension/old_versions/cdb_dataservices_server--0.21.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MapzenRouting(user_routing_config.mapzen_api_key, logger)
|
||||
client = MapzenRouting(user_routing_config.mapzen_api_key, logger, user_routing_config.mapzen_service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
logger.info("Empty origin or destination")
|
||||
|
||||
@@ -567,3 +567,173 @@ RETURNS NUMERIC AS $$
|
||||
finally:
|
||||
quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomvals geomval[],
|
||||
params JSON,
|
||||
merge BOOLEAN DEFAULT True)
|
||||
RETURNS TABLE (
|
||||
id INT,
|
||||
data JSON
|
||||
) AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT * FROM cdb_observatory.OBS_GetData(geomvals, params, merge);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomvals geomval[],
|
||||
params JSON,
|
||||
merge BOOLEAN DEFAULT True)
|
||||
RETURNS TABLE (
|
||||
id INT,
|
||||
data JSON
|
||||
) AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_obs_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
with metrics('obs_getdata', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4, $5);", ["text", "text", "geomval[]", "json", "boolean"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geomvals, params, merge])
|
||||
empty_results = len(geomvals) - len(result)
|
||||
if empty_results > 0:
|
||||
quota_service.increment_empty_service_use(empty_results)
|
||||
if result:
|
||||
quota_service.increment_success_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use(len(geomvals))
|
||||
logger.error('Error trying to OBS_GetData', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetData')
|
||||
finally:
|
||||
quota_service.increment_total_service_use(len(geomvals))
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomrefs TEXT[],
|
||||
params JSON)
|
||||
RETURNS TABLE (
|
||||
id TEXT,
|
||||
data JSON
|
||||
) AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT * FROM cdb_observatory.OBS_GetData(geomrefs, params);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetData(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geomrefs TEXT[],
|
||||
params JSON)
|
||||
RETURNS TABLE (
|
||||
id TEXT,
|
||||
data JSON
|
||||
) AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
quota_service = QuotaService(user_obs_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
with metrics('obs_getdata', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._OBS_GetData($1, $2, $3, $4);", ["text", "text", "text[]", "json"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geomrefs, params])
|
||||
empty_results = len(geomrefs) - len(result)
|
||||
if empty_results > 0:
|
||||
quota_service.increment_empty_service_use(empty_results)
|
||||
if result:
|
||||
quota_service.increment_success_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
quota_service.increment_failed_service_use(len(geomrefs))
|
||||
exc_info = sys.exc_info()
|
||||
logger.error('%s, %s, %s' % (exc_info[0], exc_info[1], exc_info[2]))
|
||||
logger.error('Error trying to OBS_GetData', exc_info, data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetData')
|
||||
finally:
|
||||
quota_service.increment_total_service_use(len(geomrefs))
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._OBS_GetMeta(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geom Geometry(Geometry, 4326),
|
||||
params JSON,
|
||||
max_timespan_rank INTEGER DEFAULT NULL,
|
||||
max_score_rank INTEGER DEFAULT NULL,
|
||||
target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
CONNECT cdb_dataservices_server._obs_server_conn_str(username, orgname);
|
||||
SELECT cdb_observatory.OBS_GetMeta(geom, params, max_timespan_rank, max_score_rank, target_geoms);
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.OBS_GetMeta(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
geom Geometry(Geometry, 4326),
|
||||
params JSON,
|
||||
max_timespan_rank INTEGER DEFAULT NULL,
|
||||
max_score_rank INTEGER DEFAULT NULL,
|
||||
target_geoms INTEGER DEFAULT NULL)
|
||||
RETURNS JSON AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_obs_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_obs_config = GD["user_obs_config_{0}".format(username)]
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('obs_getmeta', user_obs_config, logger):
|
||||
try:
|
||||
obs_plan = plpy.prepare("SELECT cdb_dataservices_server._OBS_GetMeta($1, $2, $3, $4, $5, $6, $7) as meta;", ["text", "text", "Geometry (Geometry, 4326)", "json", "integer", "integer", "integer"])
|
||||
result = plpy.execute(obs_plan, [username, orgname, geom, params, max_timespan_rank, max_score_rank, target_geoms])
|
||||
if result:
|
||||
return result[0]['meta']
|
||||
else:
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
logger.error('Error trying to OBS_GetMeta', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to OBS_GetMeta')
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
@@ -88,7 +88,7 @@ RETURNS Geometry AS $$
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
geocoder = HereMapsGeocoder(user_geocoder_config.heremaps_app_id, user_geocoder_config.heremaps_app_code, logger)
|
||||
geocoder = HereMapsGeocoder(user_geocoder_config.heremaps_app_id, user_geocoder_config.heremaps_app_code, logger, user_geocoder_config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
quota_service.increment_success_service_use()
|
||||
@@ -115,7 +115,7 @@ RETURNS Geometry AS $$
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
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)
|
||||
@@ -174,7 +174,7 @@ RETURNS Geometry AS $$
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(mapzen_geocoder_config.mapzen_api_key, logger)
|
||||
geocoder = MapzenGeocoder(mapzen_geocoder_config.mapzen_api_key, logger, mapzen_geocoder_config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
|
||||
@@ -20,7 +20,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id,
|
||||
client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id,
|
||||
user_isolines_routing_config.heremaps_app_code, logger)
|
||||
|
||||
if source:
|
||||
@@ -81,7 +81,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
|
||||
try:
|
||||
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger)
|
||||
client = MatrixClient(user_isolines_routing_config.mapzen_matrix_api_key, logger, user_isolines_routing_config.mapzen_matrix_service_params)
|
||||
mapzen_isolines = MapzenIsolines(client, logger)
|
||||
|
||||
if source:
|
||||
@@ -151,7 +151,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
|
||||
try:
|
||||
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
|
||||
logger)
|
||||
logger, user_isolines_routing_config.mapzen_isochrones_service_params)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
|
||||
@@ -141,6 +141,39 @@ SELECT exists(SELECT *
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getmeta'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, json, integer, integer, integer');
|
||||
exists
|
||||
--------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getdata'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geomval[], json, boolean');
|
||||
exists
|
||||
--------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getdata'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, text[], json');
|
||||
exists
|
||||
--------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
|
||||
@@ -89,6 +89,27 @@ SELECT exists(SELECT *
|
||||
AND proname = 'obs_getboundarybyid'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, text, text, text');
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getmeta'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, json, integer, integer, integer');
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getdata'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geomval[], json, boolean');
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
WHERE ns.nspname = 'cdb_dataservices_server'
|
||||
AND proname = 'obs_getdata'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, text[], json');
|
||||
|
||||
SELECT exists(SELECT *
|
||||
FROM pg_proc p
|
||||
INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
|
||||
|
||||
@@ -52,14 +52,17 @@ class HereMapsGeocoder(Traceable):
|
||||
'strictlanguagemode'
|
||||
] + ADDRESS_PARAMS
|
||||
|
||||
def __init__(self, app_id, app_code, logger, maxresults=DEFAULT_MAXRESULTS,
|
||||
gen=DEFAULT_GEN, host=PRODUCTION_GEOCODE_JSON_URL):
|
||||
def __init__(self, app_id, app_code, logger, service_params=None, maxresults=DEFAULT_MAXRESULTS):
|
||||
service_params = service_params or {}
|
||||
self.app_id = app_id
|
||||
self.app_code = app_code
|
||||
self._logger = logger
|
||||
self.maxresults = maxresults
|
||||
self.gen = gen
|
||||
self.host = host
|
||||
self.gen = service_params.get('gen', self.DEFAULT_GEN)
|
||||
self.host = service_params.get('json_url', self.PRODUCTION_GEOCODE_JSON_URL)
|
||||
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)
|
||||
|
||||
def geocode(self, **kwargs):
|
||||
params = {}
|
||||
@@ -92,9 +95,9 @@ class HereMapsGeocoder(Traceable):
|
||||
request_params.update(params)
|
||||
# TODO Extract HTTP client wrapper
|
||||
session = requests.Session()
|
||||
session.mount(self.host, HTTPAdapter(max_retries=self.MAX_RETRIES))
|
||||
session.mount(self.host, HTTPAdapter(max_retries=self.max_retries))
|
||||
response = session.get(self.host, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
|
||||
timeout=(self.connect_timeout, self.read_timeout))
|
||||
self.add_response_data(response, self._logger)
|
||||
if response.status_code == requests.codes.ok:
|
||||
return json.loads(response.text)
|
||||
|
||||
@@ -30,12 +30,17 @@ class HereMapsRoutingIsoline(Traceable):
|
||||
'quality'
|
||||
]
|
||||
|
||||
def __init__(self, app_id, app_code, logger,
|
||||
base_url=PRODUCTION_ROUTING_BASE_URL):
|
||||
def __init__(self, app_id, app_code, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._app_id = app_id
|
||||
self._app_code = app_code
|
||||
self._logger = logger
|
||||
self._url = "{0}{1}".format(base_url, self.ISOLINE_PATH)
|
||||
base_url = service_params.get('base_url', self.PRODUCTION_ROUTING_BASE_URL)
|
||||
isoline_path = service_params.get('isoline_path', self.ISOLINE_PATH)
|
||||
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._url = "{0}{1}".format(base_url, isoline_path)
|
||||
|
||||
def calculate_isodistance(self, source, mode, data_range, options=[]):
|
||||
return self.__calculate_isolines(source, mode, data_range, 'distance',
|
||||
@@ -57,9 +62,9 @@ class HereMapsRoutingIsoline(Traceable):
|
||||
parsed_options)
|
||||
# TODO Extract HTTP client wrapper
|
||||
session = requests.Session()
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self.max_retries))
|
||||
response = requests.get(self._url, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
|
||||
timeout=(self.connect_timeout, self.read_timeout))
|
||||
self.add_response_data(response, self._logger)
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self.__parse_isolines_response(response.text)
|
||||
|
||||
@@ -17,23 +17,32 @@ class MapzenGeocoder(Traceable):
|
||||
CONNECT_TIMEOUT = 10
|
||||
MAX_RETRIES = 1
|
||||
|
||||
def __init__(self, app_key, logger, base_url=BASE_URL):
|
||||
def __init__(self, app_key, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._app_key = app_key
|
||||
self._url = base_url
|
||||
self._url = service_params.get('base_url', self.BASE_URL)
|
||||
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._logger = logger
|
||||
|
||||
@qps_retry(qps=20)
|
||||
def geocode(self, searchtext, city=None, state_province=None,
|
||||
country=None, search_type=None):
|
||||
|
||||
# Remove the search_type if its address from the params sent to mapzen
|
||||
if search_type and search_type.lower() == 'address':
|
||||
search_type = None
|
||||
|
||||
request_params = self._build_requests_parameters(searchtext, city,
|
||||
state_province,
|
||||
country, search_type)
|
||||
try:
|
||||
# TODO Extract HTTP client wrapper
|
||||
session = requests.Session()
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self._max_retries))
|
||||
response = session.get(self._url, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
|
||||
timeout=(self._connect_timeout, self._read_timeout))
|
||||
self.add_response_data(response, self._logger)
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self.__parse_response(response.text)
|
||||
|
||||
@@ -20,10 +20,15 @@ class MapzenIsochrones:
|
||||
"car": "auto"
|
||||
}
|
||||
|
||||
def __init__(self, app_key, logger, base_url=BASE_URL):
|
||||
def __init__(self, app_key, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._app_key = app_key
|
||||
self._url = base_url
|
||||
self._logger = logger
|
||||
self._url = service_params.get('base_url', self.BASE_URL)
|
||||
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)
|
||||
|
||||
|
||||
@qps_retry(qps=7)
|
||||
def isochrone(self, locations, costing, ranges):
|
||||
@@ -32,10 +37,10 @@ class MapzenIsochrones:
|
||||
try:
|
||||
# TODO Extract HTTP client wrapper
|
||||
session = requests.Session()
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self._max_retries))
|
||||
response = session.get(self._url, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT,
|
||||
self.READ_TIMEOUT))
|
||||
timeout=(self._connect_timeout,
|
||||
self._read_timeout))
|
||||
|
||||
if response.status_code is requests.codes.ok:
|
||||
return self._parse_response(response)
|
||||
|
||||
@@ -23,9 +23,14 @@ class MatrixClient(Traceable):
|
||||
READ_TIMEOUT = 60
|
||||
CONNECT_TIMEOUT = 10
|
||||
|
||||
def __init__(self, matrix_key, logger):
|
||||
def __init__(self, matrix_key, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._matrix_key = matrix_key
|
||||
self._logger = logger
|
||||
self._url = service_params.get('one_to_many_url', self.ONE_TO_MANY_URL)
|
||||
self._connect_timeout = service_params.get('connect_timeout', self.CONNECT_TIMEOUT)
|
||||
self._read_timeout = service_params.get('read_timeout', self.READ_TIMEOUT)
|
||||
|
||||
|
||||
"""Get distances and times to a set of locations.
|
||||
See https://mapzen.com/documentation/matrix/api-reference/
|
||||
@@ -44,8 +49,8 @@ class MatrixClient(Traceable):
|
||||
'costing': costing,
|
||||
'api_key': self._matrix_key
|
||||
}
|
||||
response = requests.get(self.ONE_TO_MANY_URL, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
|
||||
response = requests.get(self._url, params=request_params,
|
||||
timeout=(self._connect_timeout, self._read_timeout))
|
||||
self.add_response_data(response, self._logger)
|
||||
|
||||
if response.status_code != requests.codes.ok:
|
||||
|
||||
@@ -33,10 +33,14 @@ class MapzenRouting(Traceable):
|
||||
METRICS_UNITS = 'kilometers'
|
||||
IMPERIAL_UNITS = 'miles'
|
||||
|
||||
def __init__(self, app_key, logger, base_url=PRODUCTION_ROUTING_BASE_URL):
|
||||
def __init__(self, app_key, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._app_key = app_key
|
||||
self._url = base_url
|
||||
self._logger = logger
|
||||
self._url = service_params.get('base_url', self.PRODUCTION_ROUTING_BASE_URL)
|
||||
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)
|
||||
|
||||
@qps_retry
|
||||
def calculate_route_point_to_point(self, waypoints, mode,
|
||||
@@ -50,9 +54,9 @@ class MapzenRouting(Traceable):
|
||||
request_params = self.__parse_request_parameters(json_request_params)
|
||||
# TODO Extract HTTP client wrapper
|
||||
session = requests.Session()
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self.MAX_RETRIES))
|
||||
session.mount(self._url, HTTPAdapter(max_retries=self._max_retries))
|
||||
response = session.get(self._url, params=request_params,
|
||||
timeout=(self.CONNECT_TIMEOUT, self.READ_TIMEOUT))
|
||||
timeout=(self._connect_timeout, self._read_timeout))
|
||||
self.add_response_data(response, self._logger)
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self.__parse_routing_response(response.text)
|
||||
|
||||
@@ -147,6 +147,7 @@ class RoutingConfig(ServiceConfig):
|
||||
if not self._routing_provider:
|
||||
self._routing_provider = self.DEFAULT_PROVIDER
|
||||
self._mapzen_api_key = self._db_config.mapzen_routing_api_key
|
||||
self._mapzen_service_params = self._db_config.mapzen_routing_service_params
|
||||
self._set_monthly_quota()
|
||||
self._set_soft_limit()
|
||||
self._period_end_date = date_parse(self._redis_config[self.PERIOD_END_DATE])
|
||||
@@ -164,6 +165,10 @@ class RoutingConfig(ServiceConfig):
|
||||
def mapzen_api_key(self):
|
||||
return self._mapzen_api_key
|
||||
|
||||
@property
|
||||
def mapzen_service_params(self):
|
||||
return self._mapzen_service_params
|
||||
|
||||
@property
|
||||
def monthly_quota(self):
|
||||
return self._monthly_quota
|
||||
@@ -199,7 +204,7 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
GEOCODER_PROVIDER_KEY = 'geocoder_provider'
|
||||
MAPZEN_PROVIDER = 'mapzen'
|
||||
HEREMAPS_PROVIDER = 'heremaps'
|
||||
DEFAULT_PROVIDER = 'heremaps'
|
||||
DEFAULT_PROVIDER = 'mapzen'
|
||||
METRICS_LOG_KEY = 'isolines_log_path'
|
||||
|
||||
def __init__(self, redis_connection, db_conn, username, orgname=None):
|
||||
@@ -222,8 +227,11 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
if self._isolines_provider == self.HEREMAPS_PROVIDER:
|
||||
self._heremaps_app_id = db_config.heremaps_isolines_app_id
|
||||
self._heremaps_app_code = db_config.heremaps_isolines_app_code
|
||||
self._heremaps_service_params = db_config.heremaps_isolines_service_params
|
||||
elif self._isolines_provider == self.MAPZEN_PROVIDER:
|
||||
self._mapzen_matrix_api_key = self._db_config.mapzen_matrix_api_key
|
||||
self._mapzen_matrix_service_params = db_config.mapzen_matrix_service_params
|
||||
self._mapzen_isochrones_service_params = db_config.mapzen_isochrones_service_params
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
@@ -256,10 +264,22 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
def heremaps_app_code(self):
|
||||
return self._heremaps_app_code
|
||||
|
||||
@property
|
||||
def heremaps_service_params(self):
|
||||
return self._heremaps_service_params
|
||||
|
||||
@property
|
||||
def mapzen_matrix_api_key(self):
|
||||
return self._mapzen_matrix_api_key
|
||||
|
||||
@property
|
||||
def mapzen_matrix_service_params(self):
|
||||
return self._mapzen_matrix_service_params
|
||||
|
||||
@property
|
||||
def mapzen_isochrones_service_params(self):
|
||||
return self._mapzen_isochrones_service_params
|
||||
|
||||
@property
|
||||
def mapzen_provider(self):
|
||||
return self._isolines_provider == self.MAPZEN_PROVIDER
|
||||
@@ -368,6 +388,7 @@ class GeocoderConfig(ServiceConfig):
|
||||
self._heremaps_app_id = db_config.heremaps_geocoder_app_id
|
||||
self._heremaps_app_code = db_config.heremaps_geocoder_app_code
|
||||
self._cost_per_hit = db_config.heremaps_geocoder_cost_per_hit
|
||||
self._heremaps_service_params = db_config.heremaps_geocoder_service_params
|
||||
elif self._geocoder_provider == self.GOOGLE_GEOCODER:
|
||||
self._google_maps_api_key = filtered_config[self.GOOGLE_GEOCODER_API_KEY]
|
||||
self._google_maps_client_id = filtered_config[self.GOOGLE_GEOCODER_CLIENT_ID]
|
||||
@@ -375,6 +396,7 @@ class GeocoderConfig(ServiceConfig):
|
||||
elif self._geocoder_provider == self.MAPZEN_GEOCODER:
|
||||
self._mapzen_api_key = db_config.mapzen_geocoder_api_key
|
||||
self._cost_per_hit = 0
|
||||
self._mapzen_service_params = db_config.mapzen_geocoder_service_params
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
@@ -428,10 +450,18 @@ class GeocoderConfig(ServiceConfig):
|
||||
def heremaps_app_code(self):
|
||||
return self._heremaps_app_code
|
||||
|
||||
@property
|
||||
def heremaps_service_params(self):
|
||||
return self._heremaps_service_params
|
||||
|
||||
@property
|
||||
def mapzen_api_key(self):
|
||||
return self._mapzen_api_key
|
||||
|
||||
@property
|
||||
def mapzen_service_params(self):
|
||||
return self._mapzen_service_params
|
||||
|
||||
@property
|
||||
def is_high_resolution(self):
|
||||
return True
|
||||
@@ -444,6 +474,9 @@ class GeocoderConfig(ServiceConfig):
|
||||
def provider(self):
|
||||
return self._geocoder_provider
|
||||
|
||||
@property
|
||||
def service(self):
|
||||
return self._service
|
||||
|
||||
class ServicesDBConfig:
|
||||
|
||||
@@ -480,8 +513,10 @@ class ServicesDBConfig:
|
||||
self._heremaps_geocoder_app_code = heremaps_conf['geocoder']['app_code']
|
||||
self._heremaps_geocoder_cost_per_hit = heremaps_conf['geocoder'][
|
||||
'geocoder_cost_per_hit']
|
||||
self._heremaps_geocoder_service_params = heremaps_conf['geocoder'].get('service', {})
|
||||
self._heremaps_isolines_app_id = heremaps_conf['isolines']['app_id']
|
||||
self._heremaps_isolines_app_code = heremaps_conf['isolines']['app_code']
|
||||
self._heremaps_isolines_service_params = heremaps_conf['isolines'].get('service', {})
|
||||
|
||||
def _get_mapzen_config(self):
|
||||
mapzen_conf_json = self._get_conf('mapzen_conf')
|
||||
@@ -491,10 +526,14 @@ class ServicesDBConfig:
|
||||
mapzen_conf = json.loads(mapzen_conf_json)
|
||||
self._mapzen_matrix_api_key = mapzen_conf['matrix']['api_key']
|
||||
self._mapzen_matrix_quota = mapzen_conf['matrix']['monthly_quota']
|
||||
self._mapzen_matrix_service_params = mapzen_conf['matrix'].get('service', {})
|
||||
self._mapzen_isochrones_service_params = mapzen_conf.get('isochrones', {}).get('service', {})
|
||||
self._mapzen_routing_api_key = mapzen_conf['routing']['api_key']
|
||||
self._mapzen_routing_quota = mapzen_conf['routing']['monthly_quota']
|
||||
self._mapzen_routing_service_params = mapzen_conf['routing'].get('service', {})
|
||||
self._mapzen_geocoder_api_key = mapzen_conf['geocoder']['api_key']
|
||||
self._mapzen_geocoder_quota = mapzen_conf['geocoder']['monthly_quota']
|
||||
self._mapzen_geocoder_service_params = mapzen_conf['geocoder'].get('service', {})
|
||||
|
||||
def _get_data_observatory_config(self):
|
||||
do_conf_json = self._get_conf('data_observatory_conf')
|
||||
@@ -530,6 +569,10 @@ class ServicesDBConfig:
|
||||
def heremaps_isolines_app_code(self):
|
||||
return self._heremaps_isolines_app_code
|
||||
|
||||
@property
|
||||
def heremaps_isolines_service_params(self):
|
||||
return self._heremaps_isolines_service_params
|
||||
|
||||
@property
|
||||
def heremaps_geocoder_app_id(self):
|
||||
return self._heremaps_geocoder_app_id
|
||||
@@ -542,6 +585,10 @@ class ServicesDBConfig:
|
||||
def heremaps_geocoder_cost_per_hit(self):
|
||||
return self._heremaps_geocoder_cost_per_hit
|
||||
|
||||
@property
|
||||
def heremaps_geocoder_service_params(self):
|
||||
return self._heremaps_geocoder_service_params
|
||||
|
||||
@property
|
||||
def mapzen_matrix_api_key(self):
|
||||
return self._mapzen_matrix_api_key
|
||||
@@ -550,6 +597,14 @@ class ServicesDBConfig:
|
||||
def mapzen_matrix_monthly_quota(self):
|
||||
return self._mapzen_matrix_quota
|
||||
|
||||
@property
|
||||
def mapzen_matrix_service_params(self):
|
||||
return self._mapzen_matrix_service_params
|
||||
|
||||
@property
|
||||
def mapzen_isochrones_service_params(self):
|
||||
return self._mapzen_isochrones_service_params
|
||||
|
||||
@property
|
||||
def mapzen_routing_api_key(self):
|
||||
return self._mapzen_routing_api_key
|
||||
@@ -558,6 +613,10 @@ class ServicesDBConfig:
|
||||
def mapzen_routing_monthly_quota(self):
|
||||
return self._mapzen_routing_quota
|
||||
|
||||
@property
|
||||
def mapzen_routing_service_params(self):
|
||||
return self._mapzen_routing_service_params
|
||||
|
||||
@property
|
||||
def mapzen_geocoder_api_key(self):
|
||||
return self._mapzen_geocoder_api_key
|
||||
@@ -566,6 +625,10 @@ class ServicesDBConfig:
|
||||
def mapzen_geocoder_monthly_quota(self):
|
||||
return self._mapzen_geocoder_quota
|
||||
|
||||
@property
|
||||
def mapzen_geocoder_service_params(self):
|
||||
return self._mapzen_geocoder_service_params
|
||||
|
||||
@property
|
||||
def data_observatory_connection_str(self):
|
||||
return self._data_observatory_connection_str
|
||||
|
||||
@@ -13,7 +13,8 @@ class MapzenGeocoderConfig(object):
|
||||
log_path,
|
||||
mapzen_api_key,
|
||||
username,
|
||||
organization):
|
||||
organization,
|
||||
service_params):
|
||||
self._geocoding_quota = geocoding_quota
|
||||
self._soft_geocoding_limit = soft_geocoding_limit
|
||||
self._period_end_date = period_end_date
|
||||
@@ -22,6 +23,7 @@ class MapzenGeocoderConfig(object):
|
||||
self._mapzen_api_key = mapzen_api_key
|
||||
self._username = username
|
||||
self._organization = organization
|
||||
self._service_params = service_params
|
||||
|
||||
# Kind of generic properties. Note which ones are for actually running the
|
||||
# service and which ones are needed for quota stuff.
|
||||
@@ -72,6 +74,10 @@ class MapzenGeocoderConfig(object):
|
||||
def organization(self):
|
||||
return self._organization
|
||||
|
||||
@property
|
||||
def service_params(self):
|
||||
return self._service_params
|
||||
|
||||
# TODO: for BW compat, remove
|
||||
@property
|
||||
def google_geocoder(self):
|
||||
@@ -90,6 +96,7 @@ class MapzenGeocoderConfigBuilder(object):
|
||||
def get(self):
|
||||
mapzen_server_conf = self._server_conf.get('mapzen_conf')
|
||||
mapzen_api_key = mapzen_server_conf['geocoder']['api_key']
|
||||
mapzen_service_params = mapzen_server_conf['geocoder'].get('service', {})
|
||||
|
||||
geocoding_quota = self._get_quota(mapzen_server_conf)
|
||||
soft_geocoding_limit = self._user_conf.get('soft_geocoding_limit').lower() == 'true'
|
||||
@@ -107,7 +114,8 @@ class MapzenGeocoderConfigBuilder(object):
|
||||
log_path,
|
||||
mapzen_api_key,
|
||||
self._username,
|
||||
self._orgname)
|
||||
self._orgname,
|
||||
mapzen_service_params)
|
||||
|
||||
def _get_quota(self, mapzen_server_conf):
|
||||
geocoding_quota = self._org_conf.get('geocoding_quota') or self._user_conf.get('geocoding_quota')
|
||||
|
||||
@@ -41,7 +41,7 @@ class RedisDBConfig:
|
||||
key)
|
||||
conf = self._db_conn.execute(conf_query)[0]['conf']
|
||||
if conf is None:
|
||||
raise "There is no redis configuration defined"
|
||||
raise Exception("There is no redis configuration defined")
|
||||
else:
|
||||
params = json.loads(conf)
|
||||
self._host = params['redis_host']
|
||||
|
||||
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
||||
setup(
|
||||
name='cartodb_services',
|
||||
|
||||
version='0.13.0',
|
||||
version='0.14.0',
|
||||
|
||||
description='CartoDB Services API Python Library',
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class TestQuotaChecker(TestCase):
|
||||
self.username,
|
||||
self.service_type,
|
||||
self.period_end_date.year,
|
||||
self.period_end_date.month
|
||||
self.period_end_date.strftime('%m')
|
||||
)
|
||||
|
||||
def test_routing_quota_check_passes_when_enough_quota(self):
|
||||
|
||||
@@ -13,7 +13,7 @@ class TestMapzenGeocoderUserConfig(TestCase):
|
||||
self._server_config = InMemoryConfigStorage({"server_conf": {"environment": "testing"},
|
||||
"mapzen_conf":
|
||||
{"geocoder":
|
||||
{"api_key": "search-xxxxxxx", "monthly_quota": 1500000}
|
||||
{"api_key": "search-xxxxxxx", "monthly_quota": 1500000, "service":{"base_url":"http://base"}}
|
||||
}, "logger_conf": {}})
|
||||
self._username = 'test_user'
|
||||
self._user_key = "rails:users:{0}".format(self._username)
|
||||
@@ -81,6 +81,14 @@ class TestMapzenGeocoderUserConfig(TestCase):
|
||||
self._redis_connection.hset(self._user_key, 'soft_geocoding_limit', 'false')
|
||||
self._redis_connection.hset(self._user_key, 'period_end_date', '2016-12-31 00:00:00')
|
||||
|
||||
def test_config_service_values(self):
|
||||
config = MapzenGeocoderConfigBuilder(self._server_config,
|
||||
self._user_config,
|
||||
self._org_config,
|
||||
self._username,
|
||||
None).get()
|
||||
assert config.service_params == {"base_url":"http://base"}
|
||||
|
||||
class TestMapzenGeocoderOrgConfig(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@@ -151,4 +159,12 @@ class TestMapzenGeocoderOrgConfig(TestCase):
|
||||
self._redis_connection.hset(self._user_key, 'soft_geocoding_limit', 'false')
|
||||
self._redis_connection.hset(self._user_key, 'period_end_date', '2016-12-15 00:00:00')
|
||||
self._redis_connection.hset(self._org_key, 'geocoding_quota', '200')
|
||||
self._redis_connection.hset(self._org_key, 'period_end_date', '2016-12-31 00:00:00')
|
||||
self._redis_connection.hset(self._org_key, 'period_end_date', '2016-12-31 00:00:00')
|
||||
|
||||
def test_config_default_service_values(self):
|
||||
config = MapzenGeocoderConfigBuilder(self._server_config,
|
||||
self._user_config,
|
||||
self._org_config,
|
||||
self._username,
|
||||
self._organization).get()
|
||||
assert config.service_params == {}
|
||||
|
||||
@@ -145,3 +145,17 @@ class HereMapsGeocoderTestCase(unittest.TestCase):
|
||||
searchtext='Calle amor de dios',
|
||||
city='Cordoba',
|
||||
country='España')
|
||||
|
||||
def test_geocode_with_nonstandard_url(self, req_mock):
|
||||
geocoder = HereMapsGeocoder(None, None, Mock(), { 'json_url': 'http://nonstandard_here_url' })
|
||||
req_mock.register_uri('GET', 'http://nonstandard_here_url', text=self.GOOD_RESPONSE)
|
||||
response = geocoder.geocode(
|
||||
searchtext='Calle amor de dios',
|
||||
city='Cordoba',
|
||||
country='España')
|
||||
|
||||
self.assertEqual(response[0], -5.2794)
|
||||
self.assertEqual(response[1], 37.70246)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -212,3 +212,20 @@ class HereMapsRoutingIsolineTestCase(unittest.TestCase):
|
||||
parsed_url = urlparse(req_mock.request_history[0].url)
|
||||
url_params = parse_qs(parsed_url.query)
|
||||
self.assertEqual(url_params['destination'][0], 'geo!33.0,1.0')
|
||||
|
||||
def test_isodistance_with_nonstandard_url(self, req_mock):
|
||||
base_url = 'http://nonstandard_base'
|
||||
url = "{0}{1}".format(base_url, HereMapsRoutingIsoline.ISOLINE_PATH)
|
||||
routing = HereMapsRoutingIsoline(None, None, Mock(), { 'base_url': base_url })
|
||||
req_mock.register_uri('GET', url, text=self.GOOD_RESPONSE)
|
||||
response = routing.calculate_isodistance('geo!33.0,1.0', 'car',
|
||||
['1000', '2000'])
|
||||
self.assertEqual(len(response), 2)
|
||||
self.assertEqual(response[0]['range'], 1000)
|
||||
self.assertEqual(response[1]['range'], 2000)
|
||||
self.assertEqual(response[0]['geom'], [u'32.9699707,0.9462833',
|
||||
u'32.9699707,0.9458542',
|
||||
u'32.9699707,0.9462833'])
|
||||
self.assertEqual(response[1]['geom'], [u'32.9699707,0.9462833',
|
||||
u'32.9699707,0.9750366',
|
||||
u'32.9699707,0.9462833'])
|
||||
|
||||
@@ -109,3 +109,14 @@ class MapzenGeocoderTestCase(unittest.TestCase):
|
||||
self.geocoder.geocode(
|
||||
searchtext='Calle Siempreviva 3, Valladolid',
|
||||
country='ESP')
|
||||
|
||||
def test_geocode_address_with_nonstandard_url(self, req_mock):
|
||||
nonstandard_url = 'http://nonstandardmapzen'
|
||||
req_mock.register_uri('GET', nonstandard_url, text=self.GOOD_RESPONSE)
|
||||
geocoder = MapzenGeocoder('search-XXXXXXX', Mock(), { 'base_url': nonstandard_url })
|
||||
response = geocoder.geocode(
|
||||
searchtext='Calle Siempreviva 3, Valldolid',
|
||||
country='ESP')
|
||||
|
||||
self.assertEqual(response[0], -4.730928)
|
||||
self.assertEqual(response[1], 41.669034)
|
||||
|
||||
@@ -52,3 +52,16 @@ class MapzenIsochronesTestCase(unittest.TestCase):
|
||||
with self.assertRaises(ServiceException):
|
||||
self.mapzen_isochrones.isochrone([-41.484375, 28.993727],
|
||||
'walk', [300, 900])
|
||||
|
||||
def test_nonstandard_url(self, req_mock):
|
||||
url = 'http://serviceurl.com'
|
||||
req_mock.register_uri('GET', url, text=self.GOOD_RESPONSE)
|
||||
mapzen_isochrones = MapzenIsochrones('matrix-xxxxx', Mock(), {'base_url': url})
|
||||
|
||||
response = mapzen_isochrones.isochrone([-41.484375, 28.993727],
|
||||
'walk', [300, 900])
|
||||
self.assertEqual(len(response), 2)
|
||||
self.assertEqual(response[0].coordinates, [[-3.702579,40.430893],[-3.702193,40.430122],[-3.702579,40.430893]])
|
||||
self.assertEqual(response[0].duration, 15)
|
||||
self.assertEqual(response[1].coordinates, [[-3.703050,40.424995],[-3.702546,40.424694],[-3.703050,40.424995]])
|
||||
self.assertEqual(response[1].duration, 5)
|
||||
|
||||
@@ -142,3 +142,17 @@ class MapzenRoutingTestCase(unittest.TestCase):
|
||||
self.assertEqual(response.length, 1.261)
|
||||
self.assertEqual(response.duration, 913)
|
||||
self.assertEqual(response.shape, self.GOOD_SHAPE_MULTI)
|
||||
|
||||
def test_nonstandard_url(self, req_mock):
|
||||
url = 'http://serviceurl.com'
|
||||
routing = MapzenRouting('api_key', Mock(), {'base_url': url})
|
||||
req_mock.register_uri('GET', url, text=self.GOOD_RESPONSE_SIMPLE)
|
||||
origin = Coordinate('-120.2', '38.5')
|
||||
destination = Coordinate('-126.4', '43.2')
|
||||
waypoints = [origin, destination]
|
||||
response = routing.calculate_route_point_to_point(waypoints,
|
||||
'car')
|
||||
|
||||
self.assertEqual(response.shape, self.GOOD_SHAPE_SIMPLE)
|
||||
self.assertEqual(response.length, 444.59)
|
||||
self.assertEqual(response.duration, 16969)
|
||||
|
||||
@@ -160,12 +160,12 @@ class TestDataObservatoryFunctions(TestCase):
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
|
||||
def test_if_obs_get_boundary_id_is_ok(self):
|
||||
query = "SELECT OBS_GetBoundaryId(CDB_LatLng(40.704512, -73.936669), 'us.census.tiger.census_tract', '2014') as boundary_id;&api_key={0}".format(self.env_variables['api_key'])
|
||||
query = "SELECT OBS_GetBoundaryId(CDB_LatLng(40.704512, -73.936669), 'us.census.tiger.census_tract', '2015') as boundary_id;&api_key={0}".format(self.env_variables['api_key'])
|
||||
result = IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
assert_not_equal(result['boundary_id'], None)
|
||||
|
||||
def test_if_obs_get_boundary_id_without_api_key_raise_error(self):
|
||||
query = "SELECT OBS_GetBoundaryId(CDB_LatLng(40.704512, -73.936669), 'us.census.tiger.census_tract', '2014') as boundary_id;"
|
||||
query = "SELECT OBS_GetBoundaryId(CDB_LatLng(40.704512, -73.936669), 'us.census.tiger.census_tract', '2015') as boundary_id;"
|
||||
try:
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
except Exception as e:
|
||||
@@ -290,3 +290,41 @@ class TestDataObservatoryFunctions(TestCase):
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
except Exception as e:
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
|
||||
def test_if_obs_get_meta_is_ok(self):
|
||||
params = '\'[{\"numer_id\": \"us.census.acs.B01003001\"}]\''
|
||||
query = "SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), {0}, 1, 1, 1000) as metadata LIMIT 1;&api_key={1}".format(params, self.env_variables['api_key'])
|
||||
result = IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
assert_not_equal(result['metadata'], None)
|
||||
|
||||
def test_if_obs_get_meta_without_api_key_raise_error(self):
|
||||
params = '\'[{\"numer_id\": \"us.census.acs.B01003001\"}]\''
|
||||
query = "SELECT obs_getmeta(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), {0}, 1, 1, 1000) LIMIT 1;".format(params)
|
||||
try:
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
except Exception as e:
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
|
||||
def test_if_obs_get_data_is_ok(self):
|
||||
params_1 = '\'[{\"numer_id\": \"us.census.acs.B01003001\", \"geom_id\": \"us.census.tiger.county\"}]\''
|
||||
params_2 = '\'[{\"numer_id\": \"us.census.acs.B01003001\"}]\''
|
||||
query_1 = "SELECT id as data_id FROM obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), {0}, 1, 1, 1000)) LIMIT 1;&api_key={1}".format(params_1, self.env_variables['api_key'])
|
||||
query_2 = "SELECT id as data_id FROM obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), {0})) LIMIT 1;&api_key={1}".format(params_2,self.env_variables['api_key'])
|
||||
result_1 = IntegrationTestHelper.execute_query(self.sql_api_url, query_1)
|
||||
assert_not_equal(result_1['data_id'], None)
|
||||
result_2 = IntegrationTestHelper.execute_query(self.sql_api_url, query_2)
|
||||
assert_not_equal(result_2['data_id'], None)
|
||||
|
||||
def test_if_obs_get_data_without_api_key_raise_error(self):
|
||||
params_1 = '\'[{\"numer_id\": \"us.census.acs.B01003001\", \"geom_id\": \"us.census.tiger.county\"}]\'';
|
||||
params_2 = '\'[{\"numer_id\": \"us.census.acs.B01003001\"}]\''
|
||||
query_1 = "SELECT id as data_id FROM obs_getdata(ARRAY['36047'], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), {0}, 1, 1, 1000)) LIMIT 1;".format(params_1)
|
||||
query_2 = "SELECT id as data_id FROM obs_getdata(ARRAY[(ST_SetSRID(ST_Point(-73.9, 40.7), 4326), 1)::geomval], obs_getmeta(st_setsrid(st_point(-73.9, 40.7), 4326), {0})) LIMIT 1;".format(params_2)
|
||||
try:
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query_1)
|
||||
except Exception as e:
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
try:
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query_2)
|
||||
except Exception as e:
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
|
||||
Reference in New Issue
Block a user