Compare commits
19 Commits
0.2.0-clie
...
0.3.0-clie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f85c4f1bbf | ||
|
|
60f17fdb09 | ||
|
|
3bf81b426b | ||
|
|
f4082b3a00 | ||
|
|
df08b27068 | ||
|
|
4d04882c18 | ||
|
|
2b084ee2ab | ||
|
|
7ddd2dfc8a | ||
|
|
d99a0c80d3 | ||
|
|
9a36445661 | ||
|
|
df195a9539 | ||
|
|
e6b0e3794b | ||
|
|
d2e73a69fa | ||
|
|
2a807af6df | ||
|
|
6c5b1b4e99 | ||
|
|
472d8c2360 | ||
|
|
ab32065e1d | ||
|
|
04617332a2 | ||
|
|
93463b3032 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
||||
.DS_Store
|
||||
*.pyc
|
||||
cartodb_services.egg-info/
|
||||
build/
|
||||
dist/
|
||||
|
||||
@@ -13,10 +13,13 @@ NEW_EXTENSION_ARTIFACT = $(EXTENSION)--$(EXTVERSION).sql
|
||||
DATA = $(NEW_EXTENSION_ARTIFACT) \
|
||||
cdb_dataservices_client--0.0.1.sql \
|
||||
cdb_dataservices_client--0.1.0.sql \
|
||||
cdb_dataservices_client--0.2.0.sql \
|
||||
cdb_dataservices_client--0.1.0--0.0.1.sql \
|
||||
cdb_dataservices_client--0.0.1--0.1.0.sql \
|
||||
cdb_dataservices_client--0.2.0--0.1.0.sql \
|
||||
cdb_dataservices_client--0.1.0--0.2.0.sql
|
||||
cdb_dataservices_client--0.1.0--0.2.0.sql \
|
||||
cdb_dataservices_client--0.2.0--0.3.0.sql \
|
||||
cdb_dataservices_client--0.3.0--0.2.0.sql
|
||||
|
||||
|
||||
REGRESS = $(notdir $(basename $(wildcard test/$(EXTVERSION)/sql/*test.sql)))
|
||||
|
||||
38
client/cdb_dataservices_client--0.2.0--0.3.0.sql
Normal file
38
client/cdb_dataservices_client--0.2.0--0.3.0.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
CREATE TYPE cdb_dataservices_client.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
duration integer
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_point_to_point (origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
DECLARE
|
||||
ret cdb_dataservices_client.simple_route;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point (username text, organization_name text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_route_point_to_point (username, organization_name, origin, destination, mode, options, units);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_point_to_point(origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[], units text) TO publicuser;
|
||||
3
client/cdb_dataservices_client--0.3.0--0.2.0.sql
Normal file
3
client/cdb_dataservices_client--0.3.0--0.2.0.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_route_point_to_point (geometry(Point, 4326), geometry(Point, 4326), text, text[], text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_route_point_to_point (text, text, geometry(Point, 4326), geometry(Point, 4326), text, text[], text);
|
||||
DROP TYPE IF EXISTS cdb_dataservices_client.simple_route;
|
||||
556
client/cdb_dataservices_client--0.3.0.sql
Normal file
556
client/cdb_dataservices_client--0.3.0.sql
Normal file
@@ -0,0 +1,556 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION cdb_dataservices_client" to load this file. \quit
|
||||
--
|
||||
-- Geocoder server connection config
|
||||
--
|
||||
-- The purpose of this function is provide to the PL/Proxy functions
|
||||
-- the connection string needed to connect with the server
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._server_conn_str()
|
||||
RETURNS text AS $$
|
||||
DECLARE
|
||||
db_connection_str text;
|
||||
BEGIN
|
||||
SELECT cartodb.cdb_conf_getconf('geocoder_server_config')->'connection_str' INTO db_connection_str;
|
||||
SELECT trim(both '"' FROM db_connection_str) INTO db_connection_str;
|
||||
RETURN db_connection_str;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
CREATE TYPE cdb_dataservices_client._entity_config AS (
|
||||
username text,
|
||||
organization_name text
|
||||
);
|
||||
|
||||
--
|
||||
-- Get entity config function
|
||||
--
|
||||
-- The purpose of this function is to retrieve the username and organization name from
|
||||
-- a) schema where he/her is the owner in case is an organization user
|
||||
-- b) entity_name from the cdb_conf database in case is a non organization user
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_entity_config()
|
||||
RETURNS record AS $$
|
||||
DECLARE
|
||||
result cdb_dataservices_client._entity_config;
|
||||
is_organization boolean;
|
||||
username text;
|
||||
organization_name text;
|
||||
BEGIN
|
||||
SELECT cartodb.cdb_conf_getconf('user_config')->'is_organization' INTO is_organization;
|
||||
IF is_organization IS NULL THEN
|
||||
RAISE EXCEPTION 'User must have user configuration in the config table';
|
||||
ELSIF is_organization = TRUE THEN
|
||||
SELECT nspname
|
||||
FROM pg_namespace s
|
||||
LEFT JOIN pg_roles r ON s.nspowner = r.oid
|
||||
WHERE r.rolname = session_user INTO username;
|
||||
SELECT cartodb.cdb_conf_getconf('user_config')->>'entity_name' INTO organization_name;
|
||||
ELSE
|
||||
SELECT cartodb.cdb_conf_getconf('user_config')->>'entity_name' INTO username;
|
||||
organization_name = NULL;
|
||||
END IF;
|
||||
result.username = username;
|
||||
result.organization_name = organization_name;
|
||||
RETURN result;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
CREATE TYPE cdb_dataservices_client.isoline AS (
|
||||
center geometry(Geometry,4326),
|
||||
data_range integer,
|
||||
the_geom geometry(Multipolygon,4326)
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
duration integer
|
||||
);--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin0_polygon (country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon (admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point (city_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon (postal_code text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point (postal_code text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_ipaddress_point (ip_address text)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_geocode_street_point (searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isodistance (source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._cdb_isodistance(username, orgname, source, mode, range, options);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_isochrone (source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT * FROM cdb_dataservices_client._cdb_isochrone(username, orgname, source, mode, range, options);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
--
|
||||
-- Public geocoder API function
|
||||
--
|
||||
-- These are the only ones with permissions to publicuser role
|
||||
-- and should also be the only ones with SECURITY DEFINER
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_route_point_to_point (origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
DECLARE
|
||||
ret cdb_dataservices_client.simple_route;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin0_polygon (username text, organization_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_admin0_polygon (username, organization_name, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, organization_name text, admin1_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, organization_name, admin1_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_admin1_polygon (username text, organization_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_admin1_polygon (username, organization_name, admin1_name, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, organization_name text, city_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, organization_name, city_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, organization_name text, city_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, organization_name, city_name, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_namedplace_point (username text, organization_name text, city_name text, admin1_name text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_namedplace_point (username, organization_name, city_name, admin1_name, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_polygon (username text, organization_name text, postal_code text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_postalcode_polygon (username, organization_name, postal_code, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_postalcode_point (username text, organization_name text, postal_code text, country_name text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_postalcode_point (username, organization_name, postal_code, country_name);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_ipaddress_point (username text, organization_name text, ip_address text)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_ipaddress_point (username, organization_name, ip_address);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_geocode_street_point (username text, organization_name text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_geocode_street_point (username, organization_name, searchtext, city, state_province, country);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isodistance (username text, organization_name text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_isodistance (username, organization_name, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_isochrone (username text, organization_name text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_isochrone (username, organization_name, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_route_point_to_point (username text, organization_name text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_route_point_to_point (username, organization_name, origin, destination, mode, options, units);
|
||||
|
||||
$$ LANGUAGE plproxy;
|
||||
|
||||
-- Make sure by default there are no permissions for publicuser
|
||||
-- NOTE: this happens at extension creation time, as part of an implicit transaction.
|
||||
REVOKE ALL PRIVILEGES ON SCHEMA cdb_dataservices_client FROM PUBLIC, publicuser CASCADE;
|
||||
|
||||
-- Grant permissions on the schema to publicuser (but just the schema)
|
||||
GRANT USAGE ON SCHEMA cdb_dataservices_client TO publicuser;
|
||||
|
||||
-- Revoke execute permissions on all functions in the schema by default
|
||||
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_dataservices_client FROM PUBLIC, publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_admin0_polygon(country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon(admin1_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_admin1_polygon(admin1_name text, country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point(city_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point(city_name text, country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_namedplace_point(city_name text, admin1_name text, country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_polygon(postal_code text, country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_postalcode_point(postal_code text, country_name text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_ipaddress_point(ip_address text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isodistance(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_isochrone(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_route_point_to_point(origin geometry(Point, 4326), destination geometry(Point, 4326), mode text, options text[], units text) TO publicuser;
|
||||
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB dataservices client API extension'
|
||||
default_version = '0.2.0'
|
||||
default_version = '0.3.0'
|
||||
requires = 'plproxy, cartodb'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_client
|
||||
|
||||
91
client/renderer/interfaces/interface_0.3.0.yaml
Normal file
91
client/renderer/interfaces/interface_0.3.0.yaml
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
- name: cdb_geocode_admin0_polygon
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: country_name, type: text }
|
||||
|
||||
- name: cdb_geocode_admin1_polygon
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: admin1_name, type: text }
|
||||
|
||||
- name: cdb_geocode_admin1_polygon
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: admin1_name, type: text }
|
||||
- { name: country_name, type: text }
|
||||
|
||||
- name: cdb_geocode_namedplace_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: city_name, type: text}
|
||||
|
||||
- name: cdb_geocode_namedplace_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: city_name, type: text}
|
||||
- { name: country_name, type: text}
|
||||
|
||||
- name: cdb_geocode_namedplace_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: city_name, type: text}
|
||||
- { name: admin1_name, type: text}
|
||||
- { name: country_name, type: text}
|
||||
|
||||
|
||||
- name: cdb_geocode_postalcode_polygon
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: postal_code, type: text}
|
||||
- { name: country_name, type: text}
|
||||
|
||||
- name: cdb_geocode_postalcode_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: postal_code, type: text}
|
||||
- { name: country_name, type: text}
|
||||
|
||||
- name: cdb_geocode_ipaddress_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: ip_address, type: text}
|
||||
|
||||
- name: cdb_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: searchtext, type: text}
|
||||
- { name: city, type: text, default: 'NULL'}
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_route_point_to_point
|
||||
return_type: cdb_dataservices_client.simple_route
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: origin, type: "geometry(Point, 4326)" }
|
||||
- { name: destination, type: "geometry(Point, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
- { name: units, type: "text", default: "'kilometers'"}
|
||||
|
||||
@@ -28,6 +28,10 @@ class SqlTemplateRenderer
|
||||
@function_signature['return_type']
|
||||
end
|
||||
|
||||
def multi_field
|
||||
@function_signature['multi_field']
|
||||
end
|
||||
|
||||
def multi_row
|
||||
@function_signature['multi_row']
|
||||
end
|
||||
|
||||
@@ -22,6 +22,9 @@ BEGIN
|
||||
<% if multi_row %>
|
||||
RETURN QUERY
|
||||
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>);
|
||||
<% elsif multi_field %>
|
||||
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
|
||||
RETURN ret;
|
||||
<% else %>
|
||||
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
|
||||
RETURN ret;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (username text, organization_name text, <%= params_with_type_and_default %>)
|
||||
RETURNS <%= return_type %> AS $$
|
||||
CONNECT <%= DATASERVICES_CLIENT_SCHEMA %>._server_conn_str();
|
||||
<% if multi_row %>
|
||||
<% if multi_field %>
|
||||
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
|
||||
<% else %>
|
||||
SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
|
||||
|
||||
1
client/sql/0.3.0/00_header.sql
Symbolic link
1
client/sql/0.3.0/00_header.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.2.0/00_header.sql
|
||||
1
client/sql/0.3.0/10_geocoder_server_conn.sql
Symbolic link
1
client/sql/0.3.0/10_geocoder_server_conn.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.2.0/10_geocoder_server_conn.sql
|
||||
1
client/sql/0.3.0/15_config_management.sql
Symbolic link
1
client/sql/0.3.0/15_config_management.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.2.0/15_config_management.sql
|
||||
11
client/sql/0.3.0/16_custom_types.sql
Normal file
11
client/sql/0.3.0/16_custom_types.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE TYPE cdb_dataservices_client.isoline AS (
|
||||
center geometry(Geometry,4326),
|
||||
data_range integer,
|
||||
the_geom geometry(Multipolygon,4326)
|
||||
);
|
||||
|
||||
CREATE TYPE cdb_dataservices_client.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
duration integer
|
||||
);
|
||||
1
client/sql/0.3.0/80_permissions.sql
Symbolic link
1
client/sql/0.3.0/80_permissions.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.2.0/80_permissions.sql
|
||||
1
client/test/0.3.0/expected/00_installation_test.out
Symbolic link
1
client/test/0.3.0/expected/00_installation_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/00_installation_test.out
|
||||
1
client/test/0.3.0/expected/10_admin0_test.out
Symbolic link
1
client/test/0.3.0/expected/10_admin0_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/10_admin0_test.out
|
||||
1
client/test/0.3.0/expected/20_admin1_test.out
Symbolic link
1
client/test/0.3.0/expected/20_admin1_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/20_admin1_test.out
|
||||
1
client/test/0.3.0/expected/30_namedplaces_test.out
Symbolic link
1
client/test/0.3.0/expected/30_namedplaces_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/30_namedplaces_test.out
|
||||
1
client/test/0.3.0/expected/40_postalcodes_test.out
Symbolic link
1
client/test/0.3.0/expected/40_postalcodes_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/40_postalcodes_test.out
|
||||
1
client/test/0.3.0/expected/50_ipaddresses_test.out
Symbolic link
1
client/test/0.3.0/expected/50_ipaddresses_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/50_ipaddresses_test.out
|
||||
1
client/test/0.3.0/expected/60_street_test.out
Symbolic link
1
client/test/0.3.0/expected/60_street_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/expected/60_street_test.out
|
||||
41
client/test/0.3.0/expected/80_route_point_to_point_test.out
Normal file
41
client/test/0.3.0/expected/80_route_point_to_point_test.out
Normal file
@@ -0,0 +1,41 @@
|
||||
-- Add to the search path the schema
|
||||
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||
-- Mock the server functions
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
DECLARE
|
||||
ret cdb_dataservices_client.simple_route;
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.cdb_route_point_to_point invoked with params (%, %, %, %, %, %, %)', username, orgname, origin, destination, mode, options, units;
|
||||
SELECT NULL, 5.33, 100 INTO ret;
|
||||
RETURN ret;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
-- Exercise the public and the proxied function
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
NOTICE: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_route_point_to_point invoked with params (test_user, <NULL>, 0101000000D53E1D8F19F455C0185B087250F24440, 0101000000465F419AB1F255C0D8B628B341EE4440, car, {}, kilometers)
|
||||
CONTEXT: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
|
||||
PL/pgSQL function cdb_route_point_to_point(geometry,geometry,text,text[],text) line 16 at SQL statement
|
||||
cdb_route_point_to_point
|
||||
--------------------------
|
||||
(,5.33,100)
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);
|
||||
NOTICE: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_route_point_to_point invoked with params (test_user, <NULL>, 0101000000D53E1D8F19F455C0185B087250F24440, 0101000000465F419AB1F255C0D8B628B341EE4440, car, {mode_type=shortest}, kilometers)
|
||||
CONTEXT: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
|
||||
PL/pgSQL function cdb_route_point_to_point(geometry,geometry,text,text[],text) line 16 at SQL statement
|
||||
cdb_route_point_to_point
|
||||
--------------------------
|
||||
(,5.33,100)
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car', ARRAY[]::text[], 'miles');
|
||||
NOTICE: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_route_point_to_point invoked with params (test_user, <NULL>, 0101000000D53E1D8F19F455C0185B087250F24440, 0101000000465F419AB1F255C0D8B628B341EE4440, car, {}, miles)
|
||||
CONTEXT: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
|
||||
PL/pgSQL function cdb_route_point_to_point(geometry,geometry,text,text[],text) line 16 at SQL statement
|
||||
cdb_route_point_to_point
|
||||
--------------------------
|
||||
(,5.33,100)
|
||||
(1 row)
|
||||
|
||||
128
client/test/0.3.0/expected/90_permissions_test.out
Normal file
128
client/test/0.3.0/expected/90_permissions_test.out
Normal file
@@ -0,0 +1,128 @@
|
||||
-- Use regular user role
|
||||
SET ROLE test_regular_user;
|
||||
-- Add to the search path the schema
|
||||
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||
-- Exercise the public function
|
||||
-- it is public, it shall work
|
||||
SELECT cdb_geocode_admin0_polygon('Spain');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_admin0_polygon(3): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_admin0_polygon invoked with params (test_user, <NULL>, Spain)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_admin0_polygon(username, orgname, country_name)"
|
||||
PL/pgSQL function cdb_geocode_admin0_polygon(text) line 16 at SQL statement
|
||||
cdb_geocode_admin0_polygon
|
||||
----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_admin1_polygon('California');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_admin1_polygon(3): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_admin1_polygon invoked with params (test_user, <NULL>, California)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name)"
|
||||
PL/pgSQL function cdb_geocode_admin1_polygon(text) line 16 at SQL statement
|
||||
cdb_geocode_admin1_polygon
|
||||
----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_admin1_polygon('California', 'United States');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_admin1_polygon(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_admin1_polygon invoked with params (test_user, <NULL>, California, United States)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_admin1_polygon(username, orgname, admin1_name, country_name)"
|
||||
PL/pgSQL function cdb_geocode_admin1_polygon(text,text) line 16 at SQL statement
|
||||
cdb_geocode_admin1_polygon
|
||||
----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_namedplace_point('Elx');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_namedplace_point(3): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_namedplace_point invoked with params (test_user, <NULL>, Elx)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name)"
|
||||
PL/pgSQL function cdb_geocode_namedplace_point(text) line 16 at SQL statement
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_namedplace_point('Elx', 'Valencia');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_namedplace_point(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_namedplace_point invoked with params (test_user, <NULL>, Elx, Valencia)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, country_name)"
|
||||
PL/pgSQL function cdb_geocode_namedplace_point(text,text) line 16 at SQL statement
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_namedplace_point('Elx', 'Valencia', 'Spain');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_namedplace_point(5): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_namedplace_point invoked with params (test_user, <NULL>, Elx, Valencia, Spain)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_namedplace_point(username, orgname, city_name, admin1_name, country_name)"
|
||||
PL/pgSQL function cdb_geocode_namedplace_point(text,text,text) line 16 at SQL statement
|
||||
cdb_geocode_namedplace_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_postalcode_polygon('03204', 'Spain');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_postalcode_polygon(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_postalcode_polygon invoked with params (test_user, <NULL>, 03204, Spain)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_postalcode_polygon(username, orgname, postal_code, country_name)"
|
||||
PL/pgSQL function cdb_geocode_postalcode_polygon(text,text) line 16 at SQL statement
|
||||
cdb_geocode_postalcode_polygon
|
||||
--------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_postalcode_point('03204', 'Spain');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_postalcode_point(4): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_postalcode_point invoked with params (test_user, <NULL>, 03204, Spain)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_postalcode_point(username, orgname, postal_code, country_name)"
|
||||
PL/pgSQL function cdb_geocode_postalcode_point(text,text) line 16 at SQL statement
|
||||
cdb_geocode_postalcode_point
|
||||
------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_ipaddress_point('8.8.8.8');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_ipaddress_point(3): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_ipaddress_point invoked with params (test_user, <NULL>, 8.8.8.8)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_ipaddress_point(username, orgname, ip_address)"
|
||||
PL/pgSQL function cdb_geocode_ipaddress_point(text) line 16 at SQL statement
|
||||
cdb_geocode_ipaddress_point
|
||||
-----------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_geocode_street_point('one street, 1');
|
||||
NOTICE: cdb_dataservices_client._cdb_geocode_street_point(6): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_geocode_geocoder_street_point invoked with params (test_user, <NULL>, one street, 1, <NULL>, <NULL>, <NULL>)
|
||||
CONTEXT: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country)"
|
||||
PL/pgSQL function cdb_geocode_street_point(text,text,text,text) line 16 at SQL statement
|
||||
cdb_geocode_street_point
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
NOTICE: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE NOTICE: cdb_dataservices_server.cdb_route_point_to_point invoked with params (test_user, <NULL>, 0101000000D53E1D8F19F455C0185B087250F24440, 0101000000465F419AB1F255C0D8B628B341EE4440, car, {}, kilometers)
|
||||
CONTEXT: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
|
||||
PL/pgSQL function cdb_route_point_to_point(geometry,geometry,text,text[],text) line 16 at SQL statement
|
||||
cdb_route_point_to_point
|
||||
--------------------------
|
||||
(,5.33,100)
|
||||
(1 row)
|
||||
|
||||
-- Check the regular user has no permissions on private functions
|
||||
SELECT _cdb_geocode_admin0_polygon('evil_user', 'evil_orgname', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_admin0_polygon
|
||||
SELECT _cdb_geocode_admin1_polygon('evil_user', 'evil_orgname', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_admin1_polygon
|
||||
SELECT _cdb_geocode_admin1_polygon('evil_user', 'evil_orgname', 'Sheol', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_admin1_polygon
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol');
|
||||
ERROR: permission denied for function _cdb_geocode_namedplace_point
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_namedplace_point
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol', 'Hell', 'Ugly world');
|
||||
ERROR: permission denied for function _cdb_geocode_namedplace_point
|
||||
SELECT _cdb_geocode_postalcode_polygon('evil_user', 'evil_orgname', '66666', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_postalcode_polygon
|
||||
SELECT _cdb_geocode_postalcode_point('evil_user', 'evil_orgname', '66666', 'Hell');
|
||||
ERROR: permission denied for function _cdb_geocode_postalcode_point
|
||||
SELECT _cdb_geocode_ipaddress_point('evil_user', 'evil_orgname', '8.8.8.8');
|
||||
ERROR: permission denied for function _cdb_geocode_ipaddress_point
|
||||
SELECT _cdb_geocode_street_point('evil_user', 'evil_orgname', 'one street, 1');
|
||||
ERROR: permission denied for function _cdb_geocode_street_point
|
||||
SELECT _cdb_route_point_to_point('evil_user', 'evil_orgname', 'POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
ERROR: permission denied for function _cdb_route_point_to_point
|
||||
1
client/test/0.3.0/sql/00_installation_test.sql
Symbolic link
1
client/test/0.3.0/sql/00_installation_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/00_installation_test.sql
|
||||
1
client/test/0.3.0/sql/10_admin0_test.sql
Symbolic link
1
client/test/0.3.0/sql/10_admin0_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/10_admin0_test.sql
|
||||
1
client/test/0.3.0/sql/20_admin1_test.sql
Symbolic link
1
client/test/0.3.0/sql/20_admin1_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/20_admin1_test.sql
|
||||
1
client/test/0.3.0/sql/30_namedplaces_test.sql
Symbolic link
1
client/test/0.3.0/sql/30_namedplaces_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/30_namedplaces_test.sql
|
||||
1
client/test/0.3.0/sql/40_postalcodes_test.sql
Symbolic link
1
client/test/0.3.0/sql/40_postalcodes_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/40_postalcodes_test.sql
|
||||
1
client/test/0.3.0/sql/50_ipaddresses_test.sql
Symbolic link
1
client/test/0.3.0/sql/50_ipaddresses_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/50_ipaddresses_test.sql
|
||||
1
client/test/0.3.0/sql/60_street_test.sql
Symbolic link
1
client/test/0.3.0/sql/60_street_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.2.0/sql/60_street_test.sql
|
||||
21
client/test/0.3.0/sql/80_route_point_to_point_test.sql
Normal file
21
client/test/0.3.0/sql/80_route_point_to_point_test.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- Add to the search path the schema
|
||||
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||
|
||||
-- Mock the server functions
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||
DECLARE
|
||||
ret cdb_dataservices_client.simple_route;
|
||||
BEGIN
|
||||
RAISE NOTICE 'cdb_dataservices_server.cdb_route_point_to_point invoked with params (%, %, %, %, %, %, %)', username, orgname, origin, destination, mode, options, units;
|
||||
SELECT NULL, 5.33, 100 INTO ret;
|
||||
RETURN ret;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
|
||||
-- Exercise the public and the proxied function
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car', ARRAY[]::text[], 'miles');
|
||||
32
client/test/0.3.0/sql/90_permissions_test.sql
Normal file
32
client/test/0.3.0/sql/90_permissions_test.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
-- Use regular user role
|
||||
SET ROLE test_regular_user;
|
||||
|
||||
-- Add to the search path the schema
|
||||
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||
|
||||
-- Exercise the public function
|
||||
-- it is public, it shall work
|
||||
SELECT cdb_geocode_admin0_polygon('Spain');
|
||||
SELECT cdb_geocode_admin1_polygon('California');
|
||||
SELECT cdb_geocode_admin1_polygon('California', 'United States');
|
||||
SELECT cdb_geocode_namedplace_point('Elx');
|
||||
SELECT cdb_geocode_namedplace_point('Elx', 'Valencia');
|
||||
SELECT cdb_geocode_namedplace_point('Elx', 'Valencia', 'Spain');
|
||||
SELECT cdb_geocode_postalcode_polygon('03204', 'Spain');
|
||||
SELECT cdb_geocode_postalcode_point('03204', 'Spain');
|
||||
SELECT cdb_geocode_ipaddress_point('8.8.8.8');
|
||||
SELECT cdb_geocode_street_point('one street, 1');
|
||||
SELECT cdb_route_point_to_point('POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
|
||||
-- Check the regular user has no permissions on private functions
|
||||
SELECT _cdb_geocode_admin0_polygon('evil_user', 'evil_orgname', 'Hell');
|
||||
SELECT _cdb_geocode_admin1_polygon('evil_user', 'evil_orgname', 'Hell');
|
||||
SELECT _cdb_geocode_admin1_polygon('evil_user', 'evil_orgname', 'Sheol', 'Hell');
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol');
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol', 'Hell');
|
||||
SELECT _cdb_geocode_namedplace_point('evil_user', 'evil_orgname', 'Sheol', 'Hell', 'Ugly world');
|
||||
SELECT _cdb_geocode_postalcode_polygon('evil_user', 'evil_orgname', '66666', 'Hell');
|
||||
SELECT _cdb_geocode_postalcode_point('evil_user', 'evil_orgname', '66666', 'Hell');
|
||||
SELECT _cdb_geocode_ipaddress_point('evil_user', 'evil_orgname', '8.8.8.8');
|
||||
SELECT _cdb_geocode_street_point('evil_user', 'evil_orgname', 'one street, 1');
|
||||
SELECT _cdb_route_point_to_point('evil_user', 'evil_orgname', 'POINT(-87.81406 41.89308)'::geometry,'POINT(-87.79209 41.86138)'::geometry, 'car');
|
||||
@@ -269,7 +269,7 @@ UPDATE {tablename} SET the_geom = cdb_geocode_ipaddress_point('102.23.34.1')
|
||||
```
|
||||
## Street-level geocoder
|
||||
|
||||
This function provides a street-level geocoding service. This service uses the street level geocoder defined for the user (currently, only the Here geocoder is available).
|
||||
This function provides a street-level geocoding service. This service uses the street level geocoder defined for the user.
|
||||
|
||||
**This service is subject to quota limitations, and extra fees may apply.** Please view our [terms and conditions](https://cartodb.com/terms/)
|
||||
|
||||
|
||||
36
scripts/create_extension_in_db.sh
Executable file
36
scripts/create_extension_in_db.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
TARGET_DB=$1
|
||||
ADMIN_PGUSER="postgres"
|
||||
PGUSER=${2:-${ADMIN_PGUSER}}
|
||||
PYTHON_LIBRARY_NAME='cartodb_services'
|
||||
|
||||
function usage {
|
||||
echo "Usage: ${0} <dbname> [dbuser]"
|
||||
}
|
||||
|
||||
[[ -z $TARGET_DB ]] && echo "Missing DB parameter" && usage && exit 1
|
||||
|
||||
python -c "import ${PYTHON_LIBRARY_NAME}"
|
||||
if [[ $? != 0 ]]
|
||||
then
|
||||
echo "Missing ${PYTHON_LIBRARY_NAME} python library"
|
||||
echo "Trying to install.."
|
||||
cd server/lib/python/cartodb_services && sudo python setup.py install
|
||||
python -c "import ${PYTHON_LIBRARY_NAME}" 2> /dev/null
|
||||
if [[ $? != 0 ]]
|
||||
then
|
||||
echo "There are some problems with python library. Debug manually"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
CREATE_EXTENSION_COMMAND="CREATE EXTENSION IF NOT EXISTS"
|
||||
|
||||
CDB_GEOCODER_EXTENSION_CREATE="${CREATE_EXTENSION_COMMAND} cdb_geocoder"
|
||||
CDB_DATASERVICES_SERVER_CREATE="${CREATE_EXTENSION_COMMAND} cdb_dataservices_server"
|
||||
|
||||
echo "* Creating extension cdb_geocoder"
|
||||
psql -U ${PGUSER} -d ${TARGET_DB} -c "${CDB_GEOCODER_EXTENSION_CREATE}"
|
||||
echo "* Creating extension cdb_dataservices_server"
|
||||
psql -U ${ADMIN_PGUSER} -d ${TARGET_DB} -c "${CDB_DATASERVICES_SERVER_CREATE}"
|
||||
@@ -15,14 +15,17 @@ DATA = $(NEW_EXTENSION_ARTIFACT) \
|
||||
cdb_dataservices_server--0.1.0.sql \
|
||||
cdb_dataservices_server--0.2.0.sql \
|
||||
cdb_dataservices_server--0.3.0.sql \
|
||||
cdb_dataservices_server--0.4.0.sql \
|
||||
cdb_dataservices_server--0.1.0--0.0.1.sql \
|
||||
cdb_dataservices_server--0.0.1--0.1.0.sql \
|
||||
cdb_dataservices_server--0.2.0--0.1.0.sql \
|
||||
cdb_dataservices_server--0.1.0--0.2.0.sql \
|
||||
cdb_dataservices_server--0.2.0--0.3.0.sql \
|
||||
cdb_dataservices_server--0.3.0--0.2.0.sql \
|
||||
cdb_dataservices_server--0.3.0--0.4.0.sql \
|
||||
cdb_dataservices_server--0.4.0--0.3.0.sql
|
||||
cdb_dataservices_server--0.2.0--0.1.0.sql \
|
||||
cdb_dataservices_server--0.1.0--0.2.0.sql \
|
||||
cdb_dataservices_server--0.2.0--0.3.0.sql \
|
||||
cdb_dataservices_server--0.3.0--0.2.0.sql \
|
||||
cdb_dataservices_server--0.3.0--0.4.0.sql \
|
||||
cdb_dataservices_server--0.4.0--0.3.0.sql \
|
||||
cdb_dataservices_server--0.5.0--0.4.0.sql \
|
||||
cdb_dataservices_server--0.4.0--0.5.0.sql
|
||||
|
||||
REGRESS = $(notdir $(basename $(wildcard test/$(EXTVERSION)/sql/*test.sql)))
|
||||
TEST_DIR = test/$(EXTVERSION)
|
||||
|
||||
157
server/extension/cdb_dataservices_server--0.4.0--0.5.0.sql
Normal file
157
server/extension/cdb_dataservices_server--0.4.0--0.5.0.sql
Normal file
@@ -0,0 +1,157 @@
|
||||
ALTER TYPE cdb_dataservices_server._redis_conf_params ADD ATTRIBUTE redis_host text;
|
||||
ALTER TYPE cdb_dataservices_server._redis_conf_params ADD ATTRIBUTE redis_port int;
|
||||
ALTER TYPE cdb_dataservices_server._redis_conf_params DROP ATTRIBUTE IF EXISTS sentinel_host;
|
||||
ALTER TYPE cdb_dataservices_server._redis_conf_params DROP ATTRIBUTE IF EXISTS sentinel_port;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_redis_conf_v2(config_key text)
|
||||
RETURNS cdb_dataservices_server._redis_conf_params AS $$
|
||||
conf_query = "SELECT cartodb.CDB_Conf_GetConf('{0}') as conf".format(config_key)
|
||||
conf = plpy.execute(conf_query)[0]['conf']
|
||||
if conf is None:
|
||||
plpy.error("There is no redis configuration defined")
|
||||
else:
|
||||
import json
|
||||
params = json.loads(conf)
|
||||
redis_conf_params = {
|
||||
"redis_host": params['redis_host'],
|
||||
"redis_port": params['redis_port'],
|
||||
"timeout": params['timeout'],
|
||||
"redis_db": params['redis_db']
|
||||
}
|
||||
if "sentinel_master_id" in params:
|
||||
redis_conf_params["sentinel_master_id"] = params["sentinel_master_id"]
|
||||
else:
|
||||
redis_conf_params["sentinel_master_id"] = None
|
||||
|
||||
return redis_conf_params
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
-- Get the connection to redis from cache or create a new one
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._connect_to_redis(user_id text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "redis_connection_{0}".format(user_id)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
from cartodb_services.tools import RedisConnection
|
||||
metadata_config_params = plpy.execute("""select c.sentinel_master_id, c.redis_host,
|
||||
c.redis_port, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metadata_config') c;""")[0]
|
||||
metrics_config_params = plpy.execute("""select c.sentinel_master_id, c.redis_host,
|
||||
c.redis_port, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metrics_config') c;""")[0]
|
||||
redis_metadata_connection = RedisConnection(metadata_config_params['sentinel_master_id'],
|
||||
metadata_config_params['redis_host'],
|
||||
metadata_config_params['redis_port'],
|
||||
timeout=metadata_config_params['timeout'],
|
||||
redis_db=metadata_config_params['redis_db']).redis_connection()
|
||||
redis_metrics_connection = RedisConnection(metrics_config_params['sentinel_master_id'],
|
||||
metrics_config_params['redis_host'],
|
||||
metrics_config_params['redis_port'],
|
||||
timeout=metrics_config_params['timeout'],
|
||||
redis_db=metrics_config_params['redis_db']).redis_connection()
|
||||
GD[cache_key] = {
|
||||
'redis_metadata_connection': redis_metadata_connection,
|
||||
'redis_metrics_connection': redis_metrics_connection,
|
||||
}
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Mapzen routing integration
|
||||
|
||||
CREATE TYPE cdb_dataservices_server.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
duration integer
|
||||
);
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import RoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
mapzen_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('mapzen_conf') as mapzen_conf", 1)[0]['mapzen_conf']
|
||||
if not mapzen_conf_json:
|
||||
mapzen_app_key = None
|
||||
else:
|
||||
mapzen_conf = json.loads(mapzen_conf_json)
|
||||
mapzen_app_key = mapzen_conf['routing_app_key']
|
||||
routing_config = RoutingConfig(redis_conn, username, orgname, mapzen_app_key)
|
||||
GD[cache_key] = routing_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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 $$
|
||||
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
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
|
||||
try:
|
||||
client = MapzenRouting(user_routing_config.mapzen_app_key)
|
||||
|
||||
orig_lat = plpy.execute("SELECT ST_Y('%s') AS lat" % origin)[0]['lat']
|
||||
orig_lon = plpy.execute("SELECT ST_X('%s') AS lon" % origin)[0]['lon']
|
||||
origin_coordinates = Coordinate(orig_lon, orig_lat)
|
||||
dest_lat = plpy.execute("SELECT ST_Y('%s') AS lat" % destination)[0]['lat']
|
||||
dest_lon = plpy.execute("SELECT ST_X('%s') AS lon" % destination)[0]['lon']
|
||||
dest_coordinates = Coordinate(dest_lon, dest_lat)
|
||||
|
||||
resp = client.calculate_route_point_to_point(origin_coordinates, dest_coordinates, mode, options, units)
|
||||
|
||||
if resp:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
quota_service.increment_success_geocoder_use()
|
||||
return [shape_linestring, resp.length, resp.duration]
|
||||
else:
|
||||
quota_service.increment_empty_geocoder_use()
|
||||
except BaseException as e:
|
||||
import sys, traceback
|
||||
type_, value_, traceback_ = sys.exc_info()
|
||||
quota_service.increment_failed_geocoder_use()
|
||||
error_msg = 'There was an error trying to obtain route using mapzen provider: {0}'.format(e)
|
||||
plpy.notice(traceback.format_tb(traceback_))
|
||||
plpy.error(error_msg)
|
||||
finally:
|
||||
quota_service.increment_total_geocoder_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
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 $$
|
||||
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)]
|
||||
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_point_to_point($1, $2, $3, $4, $5, $6, $7) as route;", ["text", "text", "geometry(Point, 4326)", "geometry(Point, 4326)", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, origin, destination, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
$$ LANGUAGE plpythonu;
|
||||
61
server/extension/cdb_dataservices_server--0.5.0--0.4.0.sql
Normal file
61
server/extension/cdb_dataservices_server--0.5.0--0.4.0.sql
Normal file
@@ -0,0 +1,61 @@
|
||||
ALTER TYPE cdb_dataservices_server._redis_conf_params DROP ATTRIBUTE IF EXISTS redis_host,
|
||||
DROP ATTRIBUTE IF EXISTS redis_port,
|
||||
ADD ATTRIBUTE sentinel_host text,
|
||||
ADD ATTRIBUTE sentinel_port int;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_redis_conf_v2(config_key text)
|
||||
RETURNS cdb_dataservices_server._redis_conf_params AS $$
|
||||
conf_query = "SELECT cartodb.CDB_Conf_GetConf('{0}') as conf".format(config_key)
|
||||
conf = plpy.execute(conf_query)[0]['conf']
|
||||
if conf is None:
|
||||
plpy.error("There is no redis configuration defined")
|
||||
else:
|
||||
import json
|
||||
params = json.loads(conf)
|
||||
return {
|
||||
"sentinel_host": params['sentinel_host'],
|
||||
"sentinel_port": params['sentinel_port'],
|
||||
"sentinel_master_id": params['sentinel_master_id'],
|
||||
"timeout": params['timeout'],
|
||||
"redis_db": params['redis_db']
|
||||
}
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
-- Get the connection to redis from cache or create a new one
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._connect_to_redis(user_id text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "redis_connection_{0}".format(user_id)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
from cartodb_services.tools import RedisConnection
|
||||
metadata_config_params = plpy.execute("""select c.sentinel_host, c.sentinel_port,
|
||||
c.sentinel_master_id, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metadata_config') c;""")[0]
|
||||
metrics_config_params = plpy.execute("""select c.sentinel_host, c.sentinel_port,
|
||||
c.sentinel_master_id, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metrics_config') c;""")[0]
|
||||
redis_metadata_connection = RedisConnection(metadata_config_params['sentinel_host'],
|
||||
metadata_config_params['sentinel_port'],
|
||||
metadata_config_params['sentinel_master_id'],
|
||||
timeout=metadata_config_params['timeout'],
|
||||
redis_db=metadata_config_params['redis_db']).redis_connection()
|
||||
redis_metrics_connection = RedisConnection(metrics_config_params['sentinel_host'],
|
||||
metrics_config_params['sentinel_port'],
|
||||
metrics_config_params['sentinel_master_id'],
|
||||
timeout=metrics_config_params['timeout'],
|
||||
redis_db=metrics_config_params['redis_db']).redis_connection()
|
||||
GD[cache_key] = {
|
||||
'redis_metadata_connection': redis_metadata_connection,
|
||||
'redis_metrics_connection': redis_metrics_connection,
|
||||
}
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Mapzen integration
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_route_point_to_point(TEXT, TEXT, geometry(Point, 4326), geometry(Point, 4326), TEXT, text[], text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_mapzen_route_point_to_point(TEXT, TEXT, geometry(Point, 4326), geometry(Point, 4326), TEXT, text[], text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._get_routing_config(text, text);
|
||||
DROP TYPE IF EXISTS cdb_dataservices_server.simple_route;
|
||||
1013
server/extension/cdb_dataservices_server--0.5.0.sql
Normal file
1013
server/extension/cdb_dataservices_server--0.5.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.4.0'
|
||||
default_version = '0.5.0'
|
||||
requires = 'plpythonu, postgis, cdb_geocoder'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_server
|
||||
|
||||
1
server/extension/sql/0.5.0/00_header.sql
Symbolic link
1
server/extension/sql/0.5.0/00_header.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/00_header.sql
|
||||
55
server/extension/sql/0.5.0/100_routing_helper.sql
Normal file
55
server/extension/sql/0.5.0/100_routing_helper.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
CREATE TYPE cdb_dataservices_server.simple_route AS (
|
||||
shape geometry(LineString,4326),
|
||||
length real,
|
||||
duration integer
|
||||
);
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_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 $$
|
||||
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
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
|
||||
try:
|
||||
client = MapzenRouting(user_routing_config.mapzen_app_key)
|
||||
|
||||
orig_lat = plpy.execute("SELECT ST_Y('%s') AS lat" % origin)[0]['lat']
|
||||
orig_lon = plpy.execute("SELECT ST_X('%s') AS lon" % origin)[0]['lon']
|
||||
origin_coordinates = Coordinate(orig_lon, orig_lat)
|
||||
dest_lat = plpy.execute("SELECT ST_Y('%s') AS lat" % destination)[0]['lat']
|
||||
dest_lon = plpy.execute("SELECT ST_X('%s') AS lon" % destination)[0]['lon']
|
||||
dest_coordinates = Coordinate(dest_lon, dest_lat)
|
||||
|
||||
resp = client.calculate_route_point_to_point(origin_coordinates, dest_coordinates, mode, options, units)
|
||||
|
||||
if resp:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
quota_service.increment_success_geocoder_use()
|
||||
return [shape_linestring, resp.length, resp.duration]
|
||||
else:
|
||||
quota_service.increment_empty_geocoder_use()
|
||||
except BaseException as e:
|
||||
import sys, traceback
|
||||
type_, value_, traceback_ = sys.exc_info()
|
||||
quota_service.increment_failed_geocoder_use()
|
||||
error_msg = 'There was an error trying to obtain route using mapzen provider: {0}'.format(e)
|
||||
plpy.notice(traceback.format_tb(traceback_))
|
||||
plpy.error(error_msg)
|
||||
finally:
|
||||
quota_service.increment_total_geocoder_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
18
server/extension/sql/0.5.0/105_route_point_to_point.sql
Normal file
18
server/extension/sql/0.5.0/105_route_point_to_point.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
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 $$
|
||||
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)]
|
||||
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_point_to_point($1, $2, $3, $4, $5, $6, $7) as route;", ["text", "text", "geometry(Point, 4326)", "geometry(Point, 4326)", "text", "text[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, origin, destination, mode, options, units])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
$$ LANGUAGE plpythonu;
|
||||
62
server/extension/sql/0.5.0/10_redis_helper.sql
Normal file
62
server/extension/sql/0.5.0/10_redis_helper.sql
Normal file
@@ -0,0 +1,62 @@
|
||||
CREATE TYPE cdb_dataservices_server._redis_conf_params AS (
|
||||
sentinel_master_id text,
|
||||
redis_host text,
|
||||
redis_port int,
|
||||
redis_db text,
|
||||
timeout float
|
||||
);
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_redis_conf_v2(config_key text)
|
||||
RETURNS cdb_dataservices_server._redis_conf_params AS $$
|
||||
conf_query = "SELECT cartodb.CDB_Conf_GetConf('{0}') as conf".format(config_key)
|
||||
conf = plpy.execute(conf_query)[0]['conf']
|
||||
if conf is None:
|
||||
plpy.error("There is no redis configuration defined")
|
||||
else:
|
||||
import json
|
||||
params = json.loads(conf)
|
||||
redis_conf_params = {
|
||||
"redis_host": params['redis_host'],
|
||||
"redis_port": params['redis_port'],
|
||||
"timeout": params['timeout'],
|
||||
"redis_db": params['redis_db']
|
||||
}
|
||||
if "sentinel_master_id" in params:
|
||||
redis_conf_params["sentinel_master_id"] = params["sentinel_master_id"]
|
||||
else:
|
||||
redis_conf_params["sentinel_master_id"] = None
|
||||
|
||||
return redis_conf_params
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
-- Get the connection to redis from cache or create a new one
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._connect_to_redis(user_id text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "redis_connection_{0}".format(user_id)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
from cartodb_services.tools import RedisConnection
|
||||
metadata_config_params = plpy.execute("""select c.sentinel_master_id, c.redis_host,
|
||||
c.redis_port, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metadata_config') c;""")[0]
|
||||
metrics_config_params = plpy.execute("""select c.sentinel_master_id, c.redis_host,
|
||||
c.redis_port, c.timeout, c.redis_db
|
||||
from cdb_dataservices_server._get_redis_conf_v2('redis_metrics_config') c;""")[0]
|
||||
redis_metadata_connection = RedisConnection(metadata_config_params['sentinel_master_id'],
|
||||
metadata_config_params['redis_host'],
|
||||
metadata_config_params['redis_port'],
|
||||
timeout=metadata_config_params['timeout'],
|
||||
redis_db=metadata_config_params['redis_db']).redis_connection()
|
||||
redis_metrics_connection = RedisConnection(metrics_config_params['sentinel_master_id'],
|
||||
metrics_config_params['redis_host'],
|
||||
metrics_config_params['redis_port'],
|
||||
timeout=metrics_config_params['timeout'],
|
||||
redis_db=metrics_config_params['redis_db']).redis_connection()
|
||||
GD[cache_key] = {
|
||||
'redis_metadata_connection': redis_metadata_connection,
|
||||
'redis_metrics_connection': redis_metrics_connection,
|
||||
}
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
75
server/extension/sql/0.5.0/15_config_helper.sql
Normal file
75
server/extension/sql/0.5.0/15_config_helper.sql
Normal file
@@ -0,0 +1,75 @@
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_geocoder_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_geocoder_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import GeocoderConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
heremaps_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('heremaps_conf') as heremaps_conf", 1)[0]['heremaps_conf']
|
||||
if not heremaps_conf_json:
|
||||
heremaps_app_id = None
|
||||
heremaps_app_code = None
|
||||
else:
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
heremaps_app_id = heremaps_conf['app_id']
|
||||
heremaps_app_code = heremaps_conf['app_code']
|
||||
geocoder_config = GeocoderConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = geocoder_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_isolines_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_isolines_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import IsolinesRoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
heremaps_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('heremaps_conf') as heremaps_conf", 1)[0]['heremaps_conf']
|
||||
if not heremaps_conf_json:
|
||||
heremaps_app_id = None
|
||||
heremaps_app_code = None
|
||||
else:
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
heremaps_app_id = heremaps_conf['app_id']
|
||||
heremaps_app_code = heremaps_conf['app_code']
|
||||
isolines_routing_config = IsolinesRoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = isolines_routing_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import RoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
mapzen_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('mapzen_conf') as mapzen_conf", 1)[0]['mapzen_conf']
|
||||
if not mapzen_conf_json:
|
||||
mapzen_app_key = None
|
||||
else:
|
||||
mapzen_conf = json.loads(mapzen_conf_json)
|
||||
mapzen_app_key = mapzen_conf['routing_app_key']
|
||||
routing_config = RoutingConfig(redis_conn, username, orgname, mapzen_app_key)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = routing_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
1
server/extension/sql/0.5.0/20_geocode_street.sql
Symbolic link
1
server/extension/sql/0.5.0/20_geocode_street.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/20_geocode_street.sql
|
||||
1
server/extension/sql/0.5.0/30_admin0.sql
Symbolic link
1
server/extension/sql/0.5.0/30_admin0.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/30_admin0.sql
|
||||
1
server/extension/sql/0.5.0/40_admin1.sql
Symbolic link
1
server/extension/sql/0.5.0/40_admin1.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/40_admin1.sql
|
||||
1
server/extension/sql/0.5.0/50_namedplaces.sql
Symbolic link
1
server/extension/sql/0.5.0/50_namedplaces.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/50_namedplaces.sql
|
||||
1
server/extension/sql/0.5.0/60_postalcodes.sql
Symbolic link
1
server/extension/sql/0.5.0/60_postalcodes.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/60_postalcodes.sql
|
||||
1
server/extension/sql/0.5.0/70_ips.sql
Symbolic link
1
server/extension/sql/0.5.0/70_ips.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/70_ips.sql
|
||||
1
server/extension/sql/0.5.0/80_isolines_helper.sql
Symbolic link
1
server/extension/sql/0.5.0/80_isolines_helper.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/80_isolines_helper.sql
|
||||
1
server/extension/sql/0.5.0/85_isodistance.sql
Symbolic link
1
server/extension/sql/0.5.0/85_isodistance.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/85_isodistance.sql
|
||||
1
server/extension/sql/0.5.0/90_isochrone.sql
Symbolic link
1
server/extension/sql/0.5.0/90_isochrone.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../0.4.0/90_isochrone.sql
|
||||
15
server/extension/sql/0.5.0/999_geocoder_server_user.sql
Normal file
15
server/extension/sql/0.5.0/999_geocoder_server_user.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT *
|
||||
FROM pg_catalog.pg_user
|
||||
WHERE usename = 'geocoder_api') THEN
|
||||
|
||||
CREATE USER geocoder_api;
|
||||
END IF;
|
||||
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_dataservices_server TO geocoder_api;
|
||||
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO geocoder_api;
|
||||
GRANT USAGE ON SCHEMA cdb_dataservices_server TO geocoder_api;
|
||||
GRANT USAGE ON SCHEMA public TO geocoder_api;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO geocoder_api;
|
||||
END$$;
|
||||
42
server/extension/test/0.5.0/expected/00_install_test.out
Normal file
42
server/extension/test/0.5.0/expected/00_install_test.out
Normal file
@@ -0,0 +1,42 @@
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION schema_triggers;
|
||||
CREATE EXTENSION plpythonu;
|
||||
CREATE EXTENSION cartodb;
|
||||
CREATE EXTENSION cdb_geocoder;
|
||||
-- Install the extension
|
||||
CREATE EXTENSION cdb_dataservices_server;
|
||||
-- Mock the redis server connection to point to this very test db
|
||||
SELECT cartodb.cdb_conf_setconf('redis_metrics_config', '{"redis_host": "localhost", "redis_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"app_key": "dummy_key"}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- Mock the varnish invalidation function
|
||||
-- (used by cdb_geocoder tests)
|
||||
CREATE OR REPLACE FUNCTION public.cdb_invalidate_varnish(table_name text) RETURNS void AS $$
|
||||
BEGIN
|
||||
RETURN;
|
||||
END
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
-- Set user quota
|
||||
SELECT cartodb.CDB_SetUserQuotaInBytes(0);
|
||||
cdb_setuserquotainbytes
|
||||
-------------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
1
server/extension/test/0.5.0/expected/20_street_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/20_street_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/20_street_test.out
|
||||
1
server/extension/test/0.5.0/expected/30_admin0_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/30_admin0_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/30_admin0_test.out
|
||||
1
server/extension/test/0.5.0/expected/40_admin1_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/40_admin1_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/40_admin1_test.out
|
||||
1
server/extension/test/0.5.0/expected/50_namedplaces_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/50_namedplaces_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/50_namedplaces_test.out
|
||||
1
server/extension/test/0.5.0/expected/60_postalcodes_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/60_postalcodes_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/60_postalcodes_test.out
|
||||
1
server/extension/test/0.5.0/expected/70_ips_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/70_ips_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/70_ips_test.out
|
||||
1
server/extension/test/0.5.0/expected/85_isodistance_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/85_isodistance_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/85_isodistance_test.out
|
||||
1
server/extension/test/0.5.0/expected/90_isochrone_test.out
Symbolic link
1
server/extension/test/0.5.0/expected/90_isochrone_test.out
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/expected/90_isochrone_test.out
|
||||
@@ -0,0 +1,12 @@
|
||||
-- Check for routing point to point signatures
|
||||
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 = 'cdb_route_point_to_point'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, geometry, text, text[], text');
|
||||
exists
|
||||
--------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_dataservices_server FROM geocoder_api;
|
||||
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA public FROM geocoder_api;
|
||||
REVOKE USAGE ON SCHEMA cdb_dataservices_server FROM geocoder_api;
|
||||
REVOKE USAGE ON SCHEMA public FROM geocoder_api;
|
||||
REVOKE SELECT ON ALL TABLES IN SCHEMA public FROM geocoder_api;
|
||||
26
server/extension/test/0.5.0/sql/00_install_test.sql
Normal file
26
server/extension/test/0.5.0/sql/00_install_test.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION schema_triggers;
|
||||
CREATE EXTENSION plpythonu;
|
||||
CREATE EXTENSION cartodb;
|
||||
CREATE EXTENSION cdb_geocoder;
|
||||
|
||||
-- Install the extension
|
||||
CREATE EXTENSION cdb_dataservices_server;
|
||||
|
||||
-- Mock the redis server connection to point to this very test db
|
||||
SELECT cartodb.cdb_conf_setconf('redis_metrics_config', '{"redis_host": "localhost", "redis_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localhost", "redis_port": 26379, "sentinel_master_id": "mymaster", "timeout": 0.1, "redis_db": 5}');
|
||||
SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"app_key": "dummy_key"}');
|
||||
|
||||
-- Mock the varnish invalidation function
|
||||
-- (used by cdb_geocoder tests)
|
||||
CREATE OR REPLACE FUNCTION public.cdb_invalidate_varnish(table_name text) RETURNS void AS $$
|
||||
BEGIN
|
||||
RETURN;
|
||||
END
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
-- Set user quota
|
||||
SELECT cartodb.CDB_SetUserQuotaInBytes(0);
|
||||
1
server/extension/test/0.5.0/sql/20_street_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/20_street_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/20_street_test.sql
|
||||
1
server/extension/test/0.5.0/sql/30_admin0_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/30_admin0_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/30_admin0_test.sql
|
||||
1
server/extension/test/0.5.0/sql/40_admin1_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/40_admin1_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/40_admin1_test.sql
|
||||
1
server/extension/test/0.5.0/sql/50_namedplaces_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/50_namedplaces_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/50_namedplaces_test.sql
|
||||
1
server/extension/test/0.5.0/sql/60_postalcodes_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/60_postalcodes_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/60_postalcodes_test.sql
|
||||
1
server/extension/test/0.5.0/sql/70_ips_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/70_ips_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/70_ips_test.sql
|
||||
1
server/extension/test/0.5.0/sql/85_isodistance_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/85_isodistance_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/85_isodistance_test.sql
|
||||
1
server/extension/test/0.5.0/sql/90_isochrone_test.sql
Symbolic link
1
server/extension/test/0.5.0/sql/90_isochrone_test.sql
Symbolic link
@@ -0,0 +1 @@
|
||||
../../0.4.0/sql/90_isochrone_test.sql
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Check for routing point to point signatures
|
||||
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 = 'cdb_route_point_to_point'
|
||||
AND oidvectortypes(p.proargtypes) = 'text, text, geometry, geometry, text, text[], text');
|
||||
@@ -0,0 +1,5 @@
|
||||
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_dataservices_server FROM geocoder_api;
|
||||
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA public FROM geocoder_api;
|
||||
REVOKE USAGE ON SCHEMA cdb_dataservices_server FROM geocoder_api;
|
||||
REVOKE USAGE ON SCHEMA public FROM geocoder_api;
|
||||
REVOKE SELECT ON ALL TABLES IN SCHEMA public FROM geocoder_api;
|
||||
@@ -0,0 +1 @@
|
||||
from routing import MapzenRouting, MapzenRoutingResponse
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
|
||||
|
||||
class WrongParams(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr('Wrong parameters passed: ' + json.dumps(self.value))
|
||||
|
||||
|
||||
class MalformedResult(Exception):
|
||||
def __str__(self):
|
||||
return repr('Result structure is malformed')
|
||||
|
||||
|
||||
class TimeoutException(Exception):
|
||||
def __str__(self):
|
||||
return repr('Timeout requesting to mapzen server')
|
||||
@@ -0,0 +1,47 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
from exceptions import TimeoutException
|
||||
|
||||
DEFAULT_RETRY_TIMEOUT = 60
|
||||
|
||||
|
||||
def qps_retry(f):
|
||||
def wrapped_f(*args, **kw):
|
||||
return QPSService().call(f, *args, **kw)
|
||||
return wrapped_f
|
||||
|
||||
|
||||
class QPSService:
|
||||
|
||||
def __init__(self, queries_per_second=10,
|
||||
retry_timeout=DEFAULT_RETRY_TIMEOUT):
|
||||
self._queries_per_second = queries_per_second
|
||||
self._retry_timeout = retry_timeout
|
||||
|
||||
def call(self, fn, *args, **kwargs):
|
||||
start_time = datetime.now()
|
||||
attempt_number = 1
|
||||
while True:
|
||||
try:
|
||||
return fn(*args, **kwargs)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'response') and e.response.status_code == 429:
|
||||
self.retry(start_time, attempt_number)
|
||||
else:
|
||||
raise e
|
||||
attempt_number += 1
|
||||
|
||||
def retry(self, first_request_time, retry_count):
|
||||
elapsed = datetime.now() - first_request_time
|
||||
if elapsed.seconds > self._retry_timeout:
|
||||
raise TimeoutException()
|
||||
|
||||
# inverse qps * (1.5 ^ i) is an increased sleep time of 1.5x per
|
||||
# iteration.
|
||||
delay = (1.0/self._queries_per_second) * 1.5 ** retry_count
|
||||
|
||||
# https://www.awsarchitectureblog.com/2015/03/backoff.html
|
||||
# https://github.com/googlemaps/google-maps-services-python/blob/master/googlemaps/client.py#L193
|
||||
sleep_time = delay * (random.random() + 0.5)
|
||||
|
||||
time.sleep(sleep_time)
|
||||
@@ -0,0 +1,119 @@
|
||||
import requests
|
||||
import json
|
||||
import re
|
||||
|
||||
from exceptions import WrongParams, MalformedResult
|
||||
from qps import qps_retry
|
||||
from cartodb_services.tools import Coordinate, PolyLine
|
||||
|
||||
|
||||
class MapzenRouting:
|
||||
'A Mapzen Routing wrapper for python'
|
||||
|
||||
PRODUCTION_ROUTING_BASE_URL = 'https://valhalla.mapzen.com/route'
|
||||
|
||||
ACCEPTED_MODES = {
|
||||
"walk": "pedestrian",
|
||||
"car": "auto",
|
||||
"public_transport": "bus",
|
||||
"bicycle": "bicycle"
|
||||
}
|
||||
|
||||
AUTO_SHORTEST = 'auto_shortest'
|
||||
|
||||
OPTIONAL_PARAMS = [
|
||||
'mode_type',
|
||||
]
|
||||
|
||||
METRICS_UNITS = 'kilometers'
|
||||
IMPERIAL_UNITS = 'miles'
|
||||
|
||||
def __init__(self, app_key, base_url=PRODUCTION_ROUTING_BASE_URL):
|
||||
self._app_key = app_key
|
||||
self._url = base_url
|
||||
|
||||
@qps_retry
|
||||
def calculate_route_point_to_point(self, origin, destination, mode,
|
||||
options=[], units=METRICS_UNITS):
|
||||
parsed_options = self.__parse_options(options)
|
||||
mode_param = self.__parse_mode_param(mode, parsed_options)
|
||||
directions = self.__parse_directions(origin, destination)
|
||||
json_request_params = self.__parse_json_parameters(directions,
|
||||
mode_param,
|
||||
units)
|
||||
request_params = self.__parse_request_parameters(json_request_params)
|
||||
response = requests.get(self._url, params=request_params)
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self.__parse_routing_response(response.text)
|
||||
else:
|
||||
response.raise_for_status()
|
||||
|
||||
def __parse_options(self, options):
|
||||
return dict(option.split('=') for option in options)
|
||||
|
||||
def __parse_request_parameters(self, json_request):
|
||||
request_options = {"json": json_request}
|
||||
request_options.update({'api_key': self._app_key})
|
||||
|
||||
return request_options
|
||||
|
||||
def __parse_json_parameters(self, directions, mode, units):
|
||||
json_options = directions
|
||||
json_options.update({'costing': self.ACCEPTED_MODES[mode]})
|
||||
json_options.update({"directions_options": {'units': units,
|
||||
'narrative': False}})
|
||||
|
||||
return json.dumps(json_options)
|
||||
|
||||
def __parse_directions(self, origin, destination):
|
||||
return {"locations": [
|
||||
{"lon": origin.longitude, "lat": origin.latitude},
|
||||
{"lon": destination.longitude, "lat": destination.latitude}
|
||||
]}
|
||||
|
||||
def __parse_routing_response(self, response):
|
||||
try:
|
||||
parsed_json_response = json.loads(response)
|
||||
legs = parsed_json_response['trip']['legs'][0]
|
||||
shape = PolyLine().decode(legs['shape'])
|
||||
length = legs['summary']['length']
|
||||
duration = legs['summary']['time']
|
||||
routing_response = MapzenRoutingResponse(shape, length, duration)
|
||||
|
||||
return routing_response
|
||||
except IndexError:
|
||||
return []
|
||||
except KeyError:
|
||||
raise MalformedResult()
|
||||
|
||||
def __parse_mode_param(self, mode, options):
|
||||
if mode in self.ACCEPTED_MODES:
|
||||
mode_source = self.ACCEPTED_MODES[mode]
|
||||
else:
|
||||
raise WrongParams("{0} is not an accepted mode type".format(mode))
|
||||
|
||||
if mode == self.ACCEPTED_MODES['car'] and 'mode_type' in options and \
|
||||
options['mode_type'] == 'shortest':
|
||||
mode = self.AUTO_SHORTEST
|
||||
|
||||
return mode
|
||||
|
||||
|
||||
class MapzenRoutingResponse:
|
||||
|
||||
def __init__(self, shape, length, duration):
|
||||
self._shape = shape
|
||||
self._length = length
|
||||
self._duration = duration
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self._shape
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
return self._length
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
return self._duration
|
||||
@@ -0,0 +1,16 @@
|
||||
import plpy
|
||||
|
||||
|
||||
def polyline_to_linestring(polyline):
|
||||
"""Convert a Mapzen polyline shape to a PostGIS multipolygon"""
|
||||
coordinates = []
|
||||
for point in polyline:
|
||||
# Divide by 10 because mapzen uses one more decimal than the
|
||||
# google standard (https://mapzen.com/documentation/turn-by-turn/decoding/)
|
||||
coordinates.append("%s %s" % (point[1]/10, point[0]/10))
|
||||
wkt_coordinates = ','.join(coordinates)
|
||||
|
||||
sql = "SELECT ST_GeomFromText('LINESTRING({0})', 4326) as geom".format(wkt_coordinates)
|
||||
geometry = plpy.execute(sql, 1)[0]['geom']
|
||||
|
||||
return geometry
|
||||
@@ -1,3 +1,3 @@
|
||||
from config import GeocoderConfig, IsolinesRoutingConfig, InternalGeocoderConfig, ConfigException
|
||||
from config import GeocoderConfig, IsolinesRoutingConfig, InternalGeocoderConfig, RoutingConfig, ConfigException
|
||||
from quota import QuotaService
|
||||
from user import UserMetricsService
|
||||
|
||||
@@ -27,6 +27,27 @@ class ServiceConfig(object):
|
||||
def organization(self):
|
||||
return self._orgname
|
||||
|
||||
class RoutingConfig(ServiceConfig):
|
||||
|
||||
ROUTING_CONFIG_KEYS = ['username', 'orgname', 'mapzen_app_key']
|
||||
MAPZEN_APP_KEY = 'mapzen_app_key'
|
||||
USERNAME_KEY = 'username'
|
||||
ORGNAME_KEY = 'orgname'
|
||||
|
||||
def __init__(self, redis_connection, username, orgname=None,
|
||||
mapzen_app_key=None):
|
||||
super(RoutingConfig, self).__init__(redis_connection, username,
|
||||
orgname)
|
||||
self._mapzen_app_key = mapzen_app_key
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
return 'routing_mapzen'
|
||||
|
||||
@property
|
||||
def mapzen_app_key(self):
|
||||
return self._mapzen_app_key
|
||||
|
||||
|
||||
class IsolinesRoutingConfig(ServiceConfig):
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
from redis_tools import RedisConnection
|
||||
from coordinates import Coordinate
|
||||
from polyline import PolyLine
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class Coordinate:
|
||||
"""Class that represents a generic form of coordinates to be used
|
||||
by the services """
|
||||
|
||||
def __init__(self, longitude, latitude):
|
||||
self._longitude = longitude
|
||||
self._latitude = latitude
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
return self._latitude
|
||||
|
||||
@property
|
||||
def longitude(self):
|
||||
return self._longitude
|
||||
|
||||
def to_json(self):
|
||||
return "{{\"lon\": {0},\"lat\": {1}}}".format(self._longitude,
|
||||
self._latitude)
|
||||
@@ -0,0 +1,51 @@
|
||||
from itertools import tee, izip
|
||||
from math import trunc
|
||||
|
||||
|
||||
class PolyLine:
|
||||
""" Polyline decoder https://developers.google.com/maps/documentation/utilities/polylinealgorithm?csw=1 """
|
||||
|
||||
def decode(self, data):
|
||||
coordinates = []
|
||||
chunks = self._extract_chunks(data)
|
||||
for chunk in chunks:
|
||||
coordinate = self._process_chunk(chunk)
|
||||
coordinate /= 1e5
|
||||
print coordinate
|
||||
if len(coordinates) > 1:
|
||||
# We have to sum the previous with the offset in this chunk
|
||||
coordinate += coordinates[-2]
|
||||
coordinates.append(round(coordinate, 5))
|
||||
|
||||
print coordinates
|
||||
|
||||
return zip(coordinates, coordinates[1:])[::2]
|
||||
|
||||
def _extract_chunks(self, data):
|
||||
chunks, chunk = [], []
|
||||
for character in data:
|
||||
byte = ord(character) - 63
|
||||
if byte & 0x20 > 0:
|
||||
byte &= 0x1F
|
||||
chunk.append(byte)
|
||||
else:
|
||||
chunk.append(byte)
|
||||
chunks.append(chunk)
|
||||
chunk = []
|
||||
|
||||
return chunks
|
||||
|
||||
def _process_chunk(self, chunk):
|
||||
coordinate = self._get_coordinate(chunk)
|
||||
# Check if the coordinate is negative
|
||||
if coordinate & 0x1:
|
||||
return ~(coordinate >> 1)
|
||||
else:
|
||||
return coordinate >> 1
|
||||
|
||||
def _get_coordinate(self, chunk):
|
||||
coordinate = 0
|
||||
for i, c in enumerate(chunk):
|
||||
coordinate |= c << (i * 5)
|
||||
|
||||
return coordinate
|
||||
@@ -1,16 +1,16 @@
|
||||
from redis.sentinel import Sentinel
|
||||
from redis import StrictRedis
|
||||
|
||||
|
||||
class RedisConnection:
|
||||
|
||||
REDIS_DEFAULT_USER_DB = 5
|
||||
REDIS_DEFAULT_TIMEOUT = 2 #seconds
|
||||
REDIS_SENTINEL_DEFAULT_PORT = 26379
|
||||
|
||||
def __init__(self, sentinel_host, sentinel_port, sentinel_master_id,
|
||||
def __init__(self, sentinel_master_id, redis_host, redis_port,
|
||||
redis_db=REDIS_DEFAULT_USER_DB, **kwargs):
|
||||
self.sentinel_host = sentinel_host
|
||||
self.sentinel_port = sentinel_port
|
||||
self.redis_host = redis_host
|
||||
self.redis_port = redis_port
|
||||
self.sentinel_master_id = sentinel_master_id
|
||||
self.timeout = kwargs['timeout'] if 'timeout' in kwargs else self.REDIS_DEFAULT_TIMEOUT
|
||||
self.redis_db = redis_db
|
||||
@@ -19,11 +19,14 @@ class RedisConnection:
|
||||
return self.__create_redis_connection()
|
||||
|
||||
def __create_redis_connection(self):
|
||||
sentinel = Sentinel([(self.sentinel_host,
|
||||
self.REDIS_SENTINEL_DEFAULT_PORT)],
|
||||
socket_timeout=self.timeout)
|
||||
return sentinel.master_for(
|
||||
self.sentinel_master_id,
|
||||
socket_timeout=self.timeout,
|
||||
db=self.redis_db
|
||||
)
|
||||
if self.sentinel_master_id == None:
|
||||
return StrictRedis(host=self.redis_host, port=self.redis_port, db=self.redis_db)
|
||||
else:
|
||||
sentinel = Sentinel([(self.redis_host,
|
||||
self.redis_port)],
|
||||
socket_timeout=self.timeout)
|
||||
return sentinel.master_for(
|
||||
self.sentinel_master_id,
|
||||
socket_timeout=self.timeout,
|
||||
db=self.redis_db
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
||||
setup(
|
||||
name='cartodb_services',
|
||||
|
||||
version='0.2.0',
|
||||
version='0.3.1',
|
||||
|
||||
description='CartoDB Services API Python Library',
|
||||
|
||||
|
||||
@@ -148,7 +148,6 @@ class HereMapsRoutingIsolineTestCase(unittest.TestCase):
|
||||
u'32.9699707,0.9462833'])
|
||||
|
||||
def test_calculate_isochrone_with_valid_params(self, req_mock):
|
||||
print self.isoline_url
|
||||
url = "{0}?start=geo%2133.0%2C1.0&mode=shortest%3Bcar".format(self.isoline_url)
|
||||
req_mock.register_uri('GET', url, text=self.GOOD_RESPONSE)
|
||||
response = self.routing.calculate_isochrone('geo!33.0,1.0', 'car',
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import unittest
|
||||
import requests_mock
|
||||
import re
|
||||
from nose.tools import assert_raises
|
||||
from urlparse import urlparse, parse_qs
|
||||
|
||||
from cartodb_services.mapzen import MapzenRouting, MapzenRoutingResponse
|
||||
from cartodb_services.mapzen.exceptions import WrongParams
|
||||
from cartodb_services.tools import Coordinate
|
||||
|
||||
requests_mock.Mocker.TEST_PREFIX = 'test_'
|
||||
|
||||
|
||||
@requests_mock.Mocker()
|
||||
class MapzenRoutingTestCase(unittest.TestCase):
|
||||
|
||||
GOOD_SHAPE = [(38.5, -120.2), (43.2, -126.4)]
|
||||
|
||||
GOOD_RESPONSE = """{{
|
||||
"id": "ethervoid-route",
|
||||
"trip": {{
|
||||
"status": 0,
|
||||
"status_message": "Found route between points",
|
||||
"legs": [
|
||||
{{
|
||||
"shape": "_p~iF~ps|U_~t[~|yd@",
|
||||
"summary": {{
|
||||
"length": 444.59,
|
||||
"time": 16969
|
||||
}}
|
||||
}}
|
||||
],
|
||||
"units": "kilometers",
|
||||
"summary": {{
|
||||
"length": 444.59,
|
||||
"time": 16969
|
||||
}},
|
||||
"locations": [
|
||||
{{
|
||||
"lon": -120.2,
|
||||
"lat": 38.5,
|
||||
"type": "break"
|
||||
}},
|
||||
{{
|
||||
"lon": -126.4,
|
||||
"lat": 43.2,
|
||||
"type": "break"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}}""".format(GOOD_SHAPE)
|
||||
|
||||
MALFORMED_RESPONSE = """{"manolo": "escobar"}"""
|
||||
|
||||
def setUp(self):
|
||||
self.routing = MapzenRouting('api_key')
|
||||
self.url = MapzenRouting.PRODUCTION_ROUTING_BASE_URL
|
||||
|
||||
def test_calculate_simple_routing_with_valid_params(self, req_mock):
|
||||
req_mock.register_uri('GET', requests_mock.ANY,
|
||||
text=self.GOOD_RESPONSE)
|
||||
origin = Coordinate('-120.2', '38.5')
|
||||
destination = Coordinate('-126.4', '43.2')
|
||||
response = self.routing.calculate_route_point_to_point(origin,
|
||||
destination,
|
||||
'car')
|
||||
|
||||
self.assertEqual(response.shape, self.GOOD_SHAPE)
|
||||
self.assertEqual(response.length, 444.59)
|
||||
self.assertEqual(response.duration, 16969)
|
||||
|
||||
def test_uknown_mode_raise_exception(self, req_mock):
|
||||
req_mock.register_uri('GET', requests_mock.ANY,
|
||||
text=self.GOOD_RESPONSE)
|
||||
origin = Coordinate('-120.2', '38.5')
|
||||
destination = Coordinate('-126.4', '43.2')
|
||||
|
||||
assert_raises(WrongParams,
|
||||
self.routing.calculate_route_point_to_point,
|
||||
origin, destination, 'unknown')
|
||||
39
server/lib/python/cartodb_services/test/test_polyline.py
Normal file
39
server/lib/python/cartodb_services/test/test_polyline.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from cartodb_services.tools import PolyLine
|
||||
from unittest import TestCase
|
||||
|
||||
|
||||
class TestPolyline(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.polyline = PolyLine()
|
||||
|
||||
def test_should_decode_a_chunk_correctly(self):
|
||||
decoded_polyline = self.polyline.decode('`~oia@`~oia@')
|
||||
original_value = [(-179.98321, -179.98321)]
|
||||
|
||||
assert decoded_polyline == original_value
|
||||
|
||||
def test_should_decode_polyline_correctly(self):
|
||||
original_polyline_1 = [(38.5, -120.2),
|
||||
(40.7, -120.95),
|
||||
(43.252, -126.453)]
|
||||
decoded_polyline_1 = self.polyline.decode('_p~iF~ps|U_ulLnnqC_mqNvxq`@')
|
||||
|
||||
assert decoded_polyline_1 == original_polyline_1
|
||||
|
||||
original_polyline_2 = [(17.95783,-5.58105),
|
||||
(15.79225,2.90039),
|
||||
(7.60211,-10.76660)]
|
||||
decoded_polyline_2 = self.polyline.decode('mkrlBp`aa@z}eL_pwr@js~p@tilrA')
|
||||
|
||||
assert decoded_polyline_2 == original_polyline_2
|
||||
|
||||
original_polyline_3 = [(62.75473,-157.14844),
|
||||
(65.07213,169.80469) ,
|
||||
(48.92250,158.55469),
|
||||
(44.33957,-150.46875)]
|
||||
decoded_polyline_3 = self.polyline.decode('ax_~Jv`d~\wrcMa`qj}@dfqaBngtcAhb~Zncc}y@')
|
||||
|
||||
assert decoded_polyline_3 == original_polyline_3
|
||||
|
||||
|
||||
34
test/integration/test_routing_functions.py
Normal file
34
test/integration/test_routing_functions.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from unittest import TestCase
|
||||
from nose.tools import assert_raises
|
||||
from nose.tools import assert_not_equal, assert_equal
|
||||
from ..helpers.integration_test_helper import IntegrationTestHelper
|
||||
|
||||
|
||||
class TestRoutingFunctions(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.env_variables = IntegrationTestHelper.get_environment_variables()
|
||||
self.sql_api_url = "https://{0}.{1}/api/v2/sql".format(
|
||||
self.env_variables['username'],
|
||||
self.env_variables['host'],
|
||||
self.env_variables['api_key']
|
||||
)
|
||||
|
||||
def test_if_select_with_routing_point_to_point_is_ok(self):
|
||||
query = "SELECT duration, length, shape as the_geom " \
|
||||
"FROM cdb_route_point_to_point('POINT(-3.70237112 40.41706163)'::geometry, " \
|
||||
"'POINT(-3.69909883 40.41236875)'::geometry, 'car', " \
|
||||
"ARRAY['mode_type=shortest']::text[])&api_key={0}".format(
|
||||
self.env_variables['api_key'])
|
||||
routing = IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
assert_not_equal(routing['the_geom'], None)
|
||||
|
||||
def test_if_select_with_routing_point_to_point_without_api_key_raise_error(self):
|
||||
query = "SELECT duration, length, shape as the_geom " \
|
||||
"FROM cdb_route_point_to_point('POINT(-3.70237112 40.41706163)'::geometry, " \
|
||||
"'POINT(-3.69909883 40.41236875)'::geometry, 'car', " \
|
||||
"ARRAY['mode_type=shortest']::text[])"
|
||||
try:
|
||||
IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
except Exception as e:
|
||||
assert_equal(e.message[0], "The api_key must be provided")
|
||||
Reference in New Issue
Block a user