Compare commits
36 Commits
0.34.2-ser
...
python-0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
885c7c50fb | ||
|
|
a38c5b275d | ||
|
|
45542b2f28 | ||
|
|
f0a9779a8d | ||
|
|
dd1df8695f | ||
|
|
8507067901 | ||
|
|
00f77cca8a | ||
|
|
dfaf0d5245 | ||
|
|
f63d73b9d7 | ||
|
|
29e636f115 | ||
|
|
f082c918f0 | ||
|
|
246ec135db | ||
|
|
4f5745988f | ||
|
|
f996cb35db | ||
|
|
bbfa03749a | ||
|
|
ab13f3a803 | ||
|
|
ac991a05ab | ||
|
|
0dfd1a9caa | ||
|
|
370272f6c4 | ||
|
|
e2c0a63803 | ||
|
|
84276b4cd3 | ||
|
|
b608830bce | ||
|
|
a8140e53c3 | ||
|
|
c28ca4861a | ||
|
|
b269c46724 | ||
|
|
6b6fbef586 | ||
|
|
eb4638a326 | ||
|
|
a919b87664 | ||
|
|
98a4ed81c5 | ||
|
|
0ec1e051be | ||
|
|
850497ef79 | ||
|
|
8d2d0ececd | ||
|
|
90fd8587e2 | ||
|
|
64a0616c97 | ||
|
|
b1bdf2460e | ||
|
|
04bbb32849 |
19
NEWS.md
19
NEWS.md
@@ -1,3 +1,22 @@
|
||||
Mar 4th, 2019
|
||||
==============
|
||||
* Version `0.21.2` of the python library
|
||||
* Fixed TomTom Qps respondes (#546)
|
||||
|
||||
Feb 25th, 2019
|
||||
==============
|
||||
* Version `0.26.2` of the client extension
|
||||
* Fixed bulk geocoding soft limit (#543)
|
||||
|
||||
Dec 31st, 2018
|
||||
==============
|
||||
* Version `0.35.1` of the server extension and `0.26.1` of the client
|
||||
* Now the bulk geocoder returns `Point` geometries instead of MultiPolygons (#538)
|
||||
|
||||
Nov 30th, 2018
|
||||
==============
|
||||
* Version `0.35.0` of the server extension
|
||||
* Now the `mode_type` is working the providers that support it (#536)
|
||||
|
||||
Nov 27th, 2018
|
||||
==============
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"carto_postgresql_ext": "^0.23.0"
|
||||
},
|
||||
"works_with": {
|
||||
"dataservices-api-server-extension": "^0.32.0"
|
||||
"dataservices-api-server-extension": "^0.35.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
client/cdb_dataservices_client--0.26.1--0.26.2.sql
Normal file
96
client/cdb_dataservices_client--0.26.1--0.26.2.sql
Normal file
@@ -0,0 +1,96 @@
|
||||
--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.26.2'" 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;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
username text;
|
||||
orgname text;
|
||||
apikey_permissions json;
|
||||
BEGIN
|
||||
SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json);
|
||||
IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN
|
||||
RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007';
|
||||
END IF;
|
||||
|
||||
-- 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 csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF enough_quota IS NULL OR NOT enough_quota THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Point,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
96
client/cdb_dataservices_client--0.26.2--0.26.1.sql
Normal file
96
client/cdb_dataservices_client--0.26.2--0.26.1.sql
Normal file
@@ -0,0 +1,96 @@
|
||||
--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.26.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;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
username text;
|
||||
orgname text;
|
||||
apikey_permissions json;
|
||||
BEGIN
|
||||
SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json);
|
||||
IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN
|
||||
RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007';
|
||||
END IF;
|
||||
|
||||
-- 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 csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Point,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
5606
client/cdb_dataservices_client--0.26.2.sql
Normal file
5606
client/cdb_dataservices_client--0.26.2.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.26.0'
|
||||
default_version = '0.26.2'
|
||||
requires = 'plproxy, cartodb'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_client
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
--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.26.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
|
||||
ALTER TYPE cdb_dataservices_client.geocoding ALTER ATTRIBUTE the_geom TYPE geometry(Point,4326);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
username text;
|
||||
orgname text;
|
||||
apikey_permissions json;
|
||||
BEGIN
|
||||
SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json);
|
||||
IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN
|
||||
RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007';
|
||||
END IF;
|
||||
|
||||
-- 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 csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Point,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
@@ -0,0 +1,99 @@
|
||||
--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.26.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
|
||||
ALTER TYPE cdb_dataservices_client.geocoding ALTER ATTRIBUTE the_geom TYPE geometry(MultiPolygon,4326);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_bulk_geocode_street_point (query text,
|
||||
street_column text, city_column text default null, state_column text default null, country_column text default null, batch_size integer DEFAULT NULL)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
DECLARE
|
||||
query_row_count integer;
|
||||
enough_quota boolean;
|
||||
remaining_quota integer;
|
||||
max_batch_size integer;
|
||||
|
||||
cartodb_id_batch integer;
|
||||
batches_n integer;
|
||||
DEFAULT_BATCH_SIZE CONSTANT numeric := 100;
|
||||
MAX_SAFE_BATCH_SIZE CONSTANT numeric := 5000;
|
||||
|
||||
temp_table_name text;
|
||||
username text;
|
||||
orgname text;
|
||||
apikey_permissions json;
|
||||
BEGIN
|
||||
SELECT u, o, p INTO username, orgname, apikey_permissions FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text, p json);
|
||||
IF apikey_permissions IS NULL OR NOT apikey_permissions::jsonb ? 'geocoding' THEN
|
||||
RAISE EXCEPTION 'Geocoding permission denied' USING ERRCODE = '01007';
|
||||
END IF;
|
||||
|
||||
-- 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 csqi.monthly_quota - csqi.used_quota AS remaining_quota, csqi.max_batch_size
|
||||
INTO remaining_quota, max_batch_size
|
||||
FROM cdb_dataservices_client.cdb_service_quota_info_batch() csqi
|
||||
WHERE service = 'hires_geocoder';
|
||||
RAISE DEBUG 'remaining_quota: %; max_batch_size: %', remaining_quota, max_batch_size;
|
||||
|
||||
IF batch_size IS NULL THEN
|
||||
batch_size := max_batch_size;
|
||||
ELSIF batch_size > max_batch_size THEN
|
||||
RAISE EXCEPTION 'batch_size must be lower than %', max_batch_size + 1;
|
||||
END IF;
|
||||
|
||||
IF batch_size > MAX_SAFE_BATCH_SIZE THEN
|
||||
batch_size := MAX_SAFE_BATCH_SIZE;
|
||||
END IF;
|
||||
|
||||
EXECUTE format('SELECT count(1), ceil(count(1)::float/%s) FROM (%s) _x', batch_size, query)
|
||||
INTO query_row_count, batches_n;
|
||||
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
RAISE DEBUG 'batches_n: %', batches_n;
|
||||
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Multipolygon,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
coalesce(street_column, ''''''), coalesce(city_column, ''''''),
|
||||
coalesce(state_column, ''''''), coalesce(country_column, '''''')
|
||||
into street_column, city_column, state_column, country_column;
|
||||
|
||||
IF batches_n > 0 THEN
|
||||
FOR cartodb_id_batch in 0..(batches_n - 1)
|
||||
LOOP
|
||||
EXECUTE format(
|
||||
'WITH geocoding_data as (' ||
|
||||
' SELECT ' ||
|
||||
' json_build_object(''id'', cartodb_id, ''address'', %s, ''city'', %s, ''state'', %s, ''country'', %s) as data , ' ||
|
||||
' floor((row_number() over () - 1)::float/$1) as batch' ||
|
||||
' FROM (%s) _x' ||
|
||||
') ' ||
|
||||
'INSERT INTO %s SELECT (cdb_dataservices_client._cdb_bulk_geocode_street_point(jsonb_agg(data))).* ' ||
|
||||
'FROM geocoding_data ' ||
|
||||
'WHERE batch = $2', street_column, city_column, state_column, country_column, query, temp_table_name)
|
||||
USING batch_size, cartodb_id_batch;
|
||||
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY EXECUTE 'SELECT * FROM ' || quote_ident(temp_table_name);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER VOLATILE PARALLEL UNSAFE;
|
||||
5606
client/old_versions/cdb_dataservices_client--0.26.1.sql
Normal file
5606
client/old_versions/cdb_dataservices_client--0.26.1.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ CREATE TYPE cdb_dataservices_client.isoline AS (
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
the_geom geometry(Point,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ BEGIN
|
||||
RAISE DEBUG 'cdb_bulk_geocode_street_point --> query_row_count: %; query: %; country: %; state: %; city: %; street: %',
|
||||
query_row_count, query, country_column, state_column, city_column, street_column;
|
||||
SELECT cdb_dataservices_client.cdb_enough_quota('hires_geocoder', query_row_count) INTO enough_quota;
|
||||
IF remaining_quota < query_row_count THEN
|
||||
IF enough_quota IS NULL OR NOT enough_quota THEN
|
||||
RAISE EXCEPTION 'Remaining quota: %. Estimated cost: %', remaining_quota, query_row_count;
|
||||
END IF;
|
||||
|
||||
@@ -58,7 +58,7 @@ BEGIN
|
||||
temp_table_name := 'bulk_geocode_street_' || md5(random()::text);
|
||||
|
||||
EXECUTE format('CREATE TEMPORARY TABLE %s ' ||
|
||||
'(cartodb_id integer, the_geom geometry(Multipolygon,4326), metadata jsonb)',
|
||||
'(cartodb_id integer, the_geom geometry(Point,4326), metadata jsonb)',
|
||||
temp_table_name);
|
||||
|
||||
select
|
||||
|
||||
@@ -9,6 +9,13 @@ CREATE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_si
|
||||
RETURNS BOOLEAN as $$
|
||||
SELECT FALSE;
|
||||
$$ LANGUAGE SQL;
|
||||
ALTER FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb) RENAME TO _cdb_bulk_geocode_street_point_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'called with this searches: %', searches;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
-- No permissions granted
|
||||
-- Test bulk size not mandatory (it will get the optimal)
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''', null, null, null, null);
|
||||
@@ -42,6 +49,18 @@ ERROR: Remaining quota: 0. Estimated cost: 1
|
||||
-- Test quota check by mocking quota 0
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
ERROR: Remaining quota: 0. Estimated cost: 1
|
||||
-- Check that when cdb_enough_quota returns true (ie. when soft_limit is set to true, even if not enough quota)
|
||||
-- it is able to proceed with the bulk geocode
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
|
||||
RETURNS BOOLEAN as $$
|
||||
SELECT TRUE;
|
||||
$$ LANGUAGE SQL;
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
NOTICE: called with this searches: [{"id": 1, "city": "", "state": "", "address": "Valladolid, Spain", "country": ""}]
|
||||
cdb_bulk_geocode_street_point
|
||||
-------------------------------
|
||||
(0 rows)
|
||||
|
||||
-- Remove permissions
|
||||
SELECT CDB_Conf_RemoveConf('api_keys_postgres');
|
||||
cdb_conf_removeconf
|
||||
@@ -51,5 +70,7 @@ SELECT CDB_Conf_RemoveConf('api_keys_postgres');
|
||||
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch;
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_enough_quota;
|
||||
DROP FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota_mocked (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch_mocked() RENAME TO cdb_service_quota_info_batch;
|
||||
ALTER FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point_mocked(searches jsonb) RENAME TO _cdb_bulk_geocode_street_point;
|
||||
|
||||
@@ -12,6 +12,14 @@ RETURNS BOOLEAN as $$
|
||||
SELECT FALSE;
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb) RENAME TO _cdb_bulk_geocode_street_point_mocked;
|
||||
CREATE FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point(searches jsonb)
|
||||
RETURNS SETOF cdb_dataservices_client.geocoding AS $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'called with this searches: %', searches;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
-- No permissions granted
|
||||
-- Test bulk size not mandatory (it will get the optimal)
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''', null, null, null, null);
|
||||
@@ -32,12 +40,21 @@ SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartod
|
||||
-- Test quota check by mocking quota 0
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
|
||||
-- Check that when cdb_enough_quota returns true (ie. when soft_limit is set to true, even if not enough quota)
|
||||
-- it is able to proceed with the bulk geocode
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_enough_quota (service TEXT ,input_size NUMERIC)
|
||||
RETURNS BOOLEAN as $$
|
||||
SELECT TRUE;
|
||||
$$ LANGUAGE SQL;
|
||||
SELECT cdb_dataservices_client.cdb_bulk_geocode_street_point('select 1 as cartodb_id', '''Valladolid, Spain''');
|
||||
|
||||
-- Remove permissions
|
||||
SELECT CDB_Conf_RemoveConf('api_keys_postgres');
|
||||
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch;
|
||||
DROP FUNCTION cdb_dataservices_client.cdb_enough_quota;
|
||||
DROP FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point;
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_enough_quota_mocked (service TEXT ,input_size NUMERIC) RENAME TO cdb_enough_quota;
|
||||
ALTER FUNCTION cdb_dataservices_client.cdb_service_quota_info_batch_mocked() RENAME TO cdb_service_quota_info_batch;
|
||||
|
||||
ALTER FUNCTION cdb_dataservices_client._cdb_bulk_geocode_street_point_mocked(searches jsonb) RENAME TO _cdb_bulk_geocode_street_point;
|
||||
|
||||
@@ -81,4 +81,4 @@ The optional value parameters must be passed using the format: `option=value`. N
|
||||
|
||||
Name | Type | Description | Accepted values
|
||||
--- | --- | --- | ---
|
||||
`mode_type` | `text` | Type of route calculation | `shortest` (this option only applies to the car transport mode)
|
||||
`mode_type` | `text` | Type of route calculation | `shortest` or `fastest` (this option only applies to the car transport mode)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.35.1'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
ALTER TYPE cdb_dataservices_server.geocoding ALTER ATTRIBUTE the_geom TYPE geometry(Point,4326);
|
||||
@@ -0,0 +1,6 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.35.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
ALTER TYPE cdb_dataservices_server.geocoding ALTER ATTRIBUTE the_geom TYPE geometry(MultiPolygon,4326);
|
||||
3808
server/extension/cdb_dataservices_server--0.35.1.sql
Normal file
3808
server/extension/cdb_dataservices_server--0.35.1.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.34.2'
|
||||
default_version = '0.35.1'
|
||||
requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_server
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
--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.35.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_route_with_waypoints(text, text, geometry(Point, 4326)[], text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_route_with_waypoints(text, text, geometry(Point, 4326)[], text);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.tools.normalize import options_to_dict
|
||||
from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
options_dict = options_to_dict(options)
|
||||
if 'mode_type' in options_dict:
|
||||
plpy.warning('Mapbox provider doesnt support route type parameter')
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate Mapbox routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM, DEFAULT_ROUTE_TYPE, MODE_TYPE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.tools.normalize import options_to_dict
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
route_type = DEFAULT_ROUTE_TYPE
|
||||
options_dict = options_to_dict(options)
|
||||
if 'mode_type' in options_dict:
|
||||
route_type = MODE_TYPE_TO_TOMTOM.get(options_dict['mode_type'])
|
||||
|
||||
resp = client.directions(waypoint_coords, profile=profile, route_type=route_type)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
origin geometry(Point, 4326),
|
||||
destination geometry(Point, 4326),
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'username': username, 'orgname': orgname, 'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'username': username, 'orgname': orgname, 'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,209 @@
|
||||
--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.34.2'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapbox_route_with_waypoints(text, text, geometry(Point, 4326)[], text, text[], text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_route_with_waypoints(text, text, geometry(Point, 4326)[], text, text[], text);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', MapboxRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxRouting(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate Mapbox routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate Mapbox routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
origin geometry(Point, 4326),
|
||||
destination geometry(Point, 4326),
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'username': username, 'orgname': orgname, 'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'username': username, 'orgname': orgname, 'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
3808
server/extension/old_versions/cdb_dataservices_server--0.35.0.sql
Normal file
3808
server/extension/old_versions/cdb_dataservices_server--0.35.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,16 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_route_with_waypoi
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.tools.normalize import options_to_dict
|
||||
from cartodb_services.refactor.service.mapbox_routing_config import MapboxRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
@@ -43,6 +46,9 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
options_dict = options_to_dict(options)
|
||||
if 'mode_type' in options_dict:
|
||||
plpy.warning('Mapbox provider doesnt support route type parameter')
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
@@ -69,13 +75,16 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoi
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM, DEFAULT_ROUTE_TYPE, MODE_TYPE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.tools.normalize import options_to_dict
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
@@ -104,8 +113,12 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
route_type = DEFAULT_ROUTE_TYPE
|
||||
options_dict = options_to_dict(options)
|
||||
if 'mode_type' in options_dict:
|
||||
route_type = MODE_TYPE_TO_TOMTOM.get(options_dict['mode_type'])
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
resp = client.directions(waypoint_coords, profile=profile, route_type=route_type)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
|
||||
@@ -24,16 +24,16 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
@@ -63,16 +63,16 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4, $5, $6) as route;", ["text", "text", "geometry(Point, 4326)[]", "text", "text[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- TODO: could cartodb_id be replaced by rowid, maybe needing extra care for offset?
|
||||
CREATE TYPE cdb_dataservices_server.geocoding AS (
|
||||
cartodb_id integer,
|
||||
the_geom geometry(Multipolygon,4326),
|
||||
the_geom geometry(Point,4326),
|
||||
metadata jsonb
|
||||
);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from collections import namedtuple
|
||||
from requests.adapters import HTTPAdapter
|
||||
from cartodb_services import StreetPointBulkGeocoder
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
from cartodb_services.geocoder import geocoder_metadata, geocoder_error_response
|
||||
from cartodb_services.geocoder import geocoder_metadata, geocoder_error_response, PRECISION_INTERPOLATED
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
|
||||
@@ -137,8 +137,8 @@ class HereMapsBulkGeocoder(HereMapsGeocoder, StreetPointBulkGeocoder):
|
||||
reader = csv.DictReader(root_zip.open(name), delimiter='|')
|
||||
for row in reader:
|
||||
if row['SeqNumber'] == '1': # First per requested data
|
||||
precision = self.PRECISION_BY_MATCH_TYPE[
|
||||
row.get('matchType', 'pointAddress')]
|
||||
precision = self.PRECISION_BY_MATCH_TYPE.get(
|
||||
row.get('matchType'), PRECISION_INTERPOLATED)
|
||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None)
|
||||
results.append((row['recId'],
|
||||
[row['displayLongitude'], row['displayLatitude']],
|
||||
|
||||
@@ -143,8 +143,8 @@ class HereMapsGeocoder(Traceable):
|
||||
|
||||
def _extract_metadata_from_result(self, result):
|
||||
# See https://stackoverflow.com/questions/51285622/missing-matchtype-at-here-geocoding-responses
|
||||
precision = self.PRECISION_BY_MATCH_TYPE[
|
||||
result.get('MatchType', 'pointAddress')]
|
||||
precision = self.PRECISION_BY_MATCH_TYPE.get(
|
||||
result.get('MatchType'), PRECISION_INTERPOLATED)
|
||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None)
|
||||
return geocoder_metadata(
|
||||
result['Relevance'],
|
||||
|
||||
@@ -11,13 +11,14 @@ from cartodb_services.tools.coordinates import (validate_coordinates,
|
||||
marshall_coordinates)
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from types import (DEFAULT_PROFILE, VALID_PROFILES, DEFAULT_DEPARTAT)
|
||||
from types import (DEFAULT_PROFILE, DEFAULT_ROUTE_TYPE, VALID_PROFILES, VALID_ROUTE_TYPE, DEFAULT_DEPARTAT)
|
||||
|
||||
BASEURI = ('https://api.tomtom.com/routing/1/calculateRoute/'
|
||||
'{coordinates}'
|
||||
'/json'
|
||||
'?key={apikey}'
|
||||
'&travelMode={travelmode}'
|
||||
'&routeType={route_type}'
|
||||
'&departAt={departat}'
|
||||
'&computeBestOrder=true')
|
||||
|
||||
@@ -45,10 +46,11 @@ class TomTomRouting(Traceable):
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, coordinates, profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
date_time=DEFAULT_DEPARTAT, route_type=DEFAULT_ROUTE_TYPE):
|
||||
uri = URITemplate(BASEURI).expand(apikey=self._apikey,
|
||||
coordinates=coordinates,
|
||||
travelmode=profile,
|
||||
route_type=route_type,
|
||||
departat=date_time)
|
||||
return uri
|
||||
|
||||
@@ -60,6 +62,14 @@ class TomTomRouting(Traceable):
|
||||
valid_profiles=', '.join(
|
||||
[x for x in VALID_PROFILES])))
|
||||
|
||||
def _validate_route_type(self, route_type):
|
||||
if route_type not in VALID_ROUTE_TYPE:
|
||||
raise ValueError('{route_type} is not a valid route type. '
|
||||
'Valid route types are: {valid_route_types}'.format(
|
||||
route_type=route_type,
|
||||
valid_route_types=', '.join(
|
||||
[x for x in VALID_ROUTE_TYPE])))
|
||||
|
||||
def _marshall_coordinates(self, coordinates):
|
||||
return ':'.join(['{lat},{lon}'.format(lat=coordinate.latitude,
|
||||
lon=coordinate.longitude)
|
||||
@@ -91,13 +101,14 @@ class TomTomRouting(Traceable):
|
||||
|
||||
@qps_retry(qps=5, provider='tomtom')
|
||||
def directions(self, waypoints, profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
date_time=DEFAULT_DEPARTAT, route_type=DEFAULT_ROUTE_TYPE):
|
||||
self._validate_profile(profile)
|
||||
self._validate_route_type(route_type)
|
||||
validate_coordinates(waypoints, NUM_WAYPOINTS_MIN, NUM_WAYPOINTS_MAX)
|
||||
|
||||
coordinates = self._marshall_coordinates(waypoints)
|
||||
|
||||
uri = self._uri(coordinates, profile, date_time)
|
||||
uri = self._uri(coordinates, profile, date_time, route_type)
|
||||
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
@@ -6,12 +6,16 @@ PROFILE_DRIVING = 'car'
|
||||
PROFILE_CYCLING = 'bicycle'
|
||||
PROFILE_WALKING = 'pedestrian'
|
||||
DEFAULT_PROFILE = PROFILE_DRIVING
|
||||
ROUTE_TYPE_FAST = 'fastest'
|
||||
ROUTE_TYPE_SHORT = 'shortest'
|
||||
|
||||
DEFAULT_DEPARTAT = 'now'
|
||||
|
||||
VALID_PROFILES = [PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
PROFILE_WALKING]
|
||||
VALID_ROUTE_TYPE = [ROUTE_TYPE_SHORT,
|
||||
ROUTE_TYPE_FAST]
|
||||
|
||||
MAX_SPEEDS = {
|
||||
PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed
|
||||
@@ -20,7 +24,13 @@ MAX_SPEEDS = {
|
||||
}
|
||||
|
||||
TRANSPORT_MODE_TO_TOMTOM = {
|
||||
'car': 'car',
|
||||
'walk': 'pedestrian',
|
||||
'bicycle': 'bicycle',
|
||||
'car': PROFILE_DRIVING,
|
||||
'walk': PROFILE_WALKING,
|
||||
'bicycle': PROFILE_CYCLING,
|
||||
}
|
||||
|
||||
DEFAULT_ROUTE_TYPE = ROUTE_TYPE_SHORT
|
||||
MODE_TYPE_TO_TOMTOM = {
|
||||
'shortest': ROUTE_TYPE_SHORT,
|
||||
'fastest': ROUTE_TYPE_FAST
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
def normalize(str_input):
|
||||
return str_input.replace('"', '"') \
|
||||
.replace(';', ',')
|
||||
|
||||
def options_to_dict(options):
|
||||
return dict(option.split("=") for option in options)
|
||||
|
||||
@@ -2,13 +2,17 @@ import time
|
||||
import random
|
||||
from datetime import datetime
|
||||
from exceptions import TimeoutException
|
||||
import re
|
||||
|
||||
DEFAULT_RETRY_TIMEOUT = 60
|
||||
DEFAULT_QUERIES_PER_SECOND = 10
|
||||
|
||||
TOMTOM_403_RATE_LIMIT_HEADER = 'Account Over Queries Per Second Limit'
|
||||
TOMTOM_403_RATE_LIMIT_HEADERS = [
|
||||
'Account Over Queries Per Second Limit',
|
||||
'Developer Over Qps'
|
||||
]
|
||||
TOMTOM_DETAIL_HEADER = 'X-Error-Detail-Header'
|
||||
|
||||
TOMTOM_403_RATE_LIMIT_HEADER_PATTERN = re.compile('|'.join(TOMTOM_403_RATE_LIMIT_HEADERS), re.IGNORECASE)
|
||||
|
||||
def qps_retry(original_function=None, **options):
|
||||
""" Query Per Second retry decorator
|
||||
@@ -49,9 +53,11 @@ class QPSService:
|
||||
response = getattr(e, 'response', None)
|
||||
if response is not None:
|
||||
if self._provider is not None and self._provider == 'tomtom' and (response.status_code == 403):
|
||||
if response.headers.get(TOMTOM_DETAIL_HEADER) != TOMTOM_403_RATE_LIMIT_HEADER:
|
||||
detail_header = response.headers.get(TOMTOM_DETAIL_HEADER)
|
||||
if detail_header and TOMTOM_403_RATE_LIMIT_HEADER_PATTERN.search(detail_header):
|
||||
self.retry(start_time, attempt_number)
|
||||
else:
|
||||
raise e
|
||||
self.retry(start_time, attempt_number)
|
||||
elif response.status_code == 429:
|
||||
self.retry(start_time, attempt_number)
|
||||
else:
|
||||
|
||||
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
||||
setup(
|
||||
name='cartodb_services',
|
||||
|
||||
version='0.20.2',
|
||||
version='0.21.2',
|
||||
|
||||
description='CartoDB Services API Python Library',
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ INVALID_WAYPOINTS_MIN = [Coordinate(13.42936, 52.50931)]
|
||||
INVALID_WAYPOINTS_MAX = [Coordinate(13.42936, 52.50931)
|
||||
for x in range(0, NUM_WAYPOINTS_MAX + 2)]
|
||||
VALID_PROFILE = DEFAULT_PROFILE
|
||||
VALID_ROUTE_TYPE = 'fastest'
|
||||
INVALID_PROFILE = 'invalid_profile'
|
||||
INVALID_ROUTE_TYPE = 'invalid_route_type'
|
||||
|
||||
|
||||
class TomTomRoutingTestCase(unittest.TestCase):
|
||||
@@ -43,6 +45,9 @@ class TomTomRoutingTestCase(unittest.TestCase):
|
||||
with self.assertRaises(ServiceException):
|
||||
invalid_routing.directions(VALID_WAYPOINTS,
|
||||
VALID_PROFILE)
|
||||
def test_invalid_route_type(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.routing.directions(VALID_WAYPOINTS, VALID_PROFILE, route_type=INVALID_ROUTE_TYPE)
|
||||
|
||||
def test_valid_request(self):
|
||||
route = self.routing.directions(VALID_WAYPOINTS, VALID_PROFILE)
|
||||
@@ -50,3 +55,9 @@ class TomTomRoutingTestCase(unittest.TestCase):
|
||||
assert route.shape
|
||||
assert route.length
|
||||
assert route.duration
|
||||
|
||||
route = self.routing.directions(VALID_WAYPOINTS, VALID_PROFILE, route_type=VALID_ROUTE_TYPE)
|
||||
|
||||
assert route.shape
|
||||
assert route.length
|
||||
assert route.duration
|
||||
|
||||
Reference in New Issue
Block a user