Compare commits
19 Commits
0.4.0-serv
...
0.5.0-serv
| 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
|
.DS_Store
|
||||||
*.pyc
|
*.pyc
|
||||||
|
cartodb_services.egg-info/
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
|||||||
@@ -13,10 +13,13 @@ NEW_EXTENSION_ARTIFACT = $(EXTENSION)--$(EXTVERSION).sql
|
|||||||
DATA = $(NEW_EXTENSION_ARTIFACT) \
|
DATA = $(NEW_EXTENSION_ARTIFACT) \
|
||||||
cdb_dataservices_client--0.0.1.sql \
|
cdb_dataservices_client--0.0.1.sql \
|
||||||
cdb_dataservices_client--0.1.0.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.1.0--0.0.1.sql \
|
||||||
cdb_dataservices_client--0.0.1--0.1.0.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.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)))
|
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'
|
comment = 'CartoDB dataservices client API extension'
|
||||||
default_version = '0.2.0'
|
default_version = '0.3.0'
|
||||||
requires = 'plproxy, cartodb'
|
requires = 'plproxy, cartodb'
|
||||||
superuser = true
|
superuser = true
|
||||||
schema = cdb_dataservices_client
|
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']
|
@function_signature['return_type']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def multi_field
|
||||||
|
@function_signature['multi_field']
|
||||||
|
end
|
||||||
|
|
||||||
def multi_row
|
def multi_row
|
||||||
@function_signature['multi_row']
|
@function_signature['multi_row']
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ BEGIN
|
|||||||
<% if multi_row %>
|
<% if multi_row %>
|
||||||
RETURN QUERY
|
RETURN QUERY
|
||||||
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>);
|
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 %>
|
<% else %>
|
||||||
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
|
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(username, orgname, <%= params %>) INTO ret;
|
||||||
RETURN 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 %>)
|
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (username text, organization_name text, <%= params_with_type_and_default %>)
|
||||||
RETURNS <%= return_type %> AS $$
|
RETURNS <%= return_type %> AS $$
|
||||||
CONNECT <%= DATASERVICES_CLIENT_SCHEMA %>._server_conn_str();
|
CONNECT <%= DATASERVICES_CLIENT_SCHEMA %>._server_conn_str();
|
||||||
<% if multi_row %>
|
<% if multi_field %>
|
||||||
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
|
SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
|
||||||
<% else %>
|
<% else %>
|
||||||
SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (username, organization_name, <%= params %>);
|
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
|
## 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/)
|
**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.1.0.sql \
|
||||||
cdb_dataservices_server--0.2.0.sql \
|
cdb_dataservices_server--0.2.0.sql \
|
||||||
cdb_dataservices_server--0.3.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.1.0--0.0.1.sql \
|
||||||
cdb_dataservices_server--0.0.1--0.1.0.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.2.0--0.1.0.sql \
|
||||||
cdb_dataservices_server--0.1.0--0.2.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.2.0--0.3.0.sql \
|
||||||
cdb_dataservices_server--0.3.0--0.2.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.3.0--0.4.0.sql \
|
||||||
cdb_dataservices_server--0.4.0--0.3.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)))
|
REGRESS = $(notdir $(basename $(wildcard test/$(EXTVERSION)/sql/*test.sql)))
|
||||||
TEST_DIR = test/$(EXTVERSION)
|
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'
|
comment = 'CartoDB dataservices server extension'
|
||||||
default_version = '0.4.0'
|
default_version = '0.5.0'
|
||||||
requires = 'plpythonu, postgis, cdb_geocoder'
|
requires = 'plpythonu, postgis, cdb_geocoder'
|
||||||
superuser = true
|
superuser = true
|
||||||
schema = cdb_dataservices_server
|
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 quota import QuotaService
|
||||||
from user import UserMetricsService
|
from user import UserMetricsService
|
||||||
|
|||||||
@@ -27,6 +27,27 @@ class ServiceConfig(object):
|
|||||||
def organization(self):
|
def organization(self):
|
||||||
return self._orgname
|
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):
|
class IsolinesRoutingConfig(ServiceConfig):
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
from redis_tools import RedisConnection
|
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.sentinel import Sentinel
|
||||||
|
from redis import StrictRedis
|
||||||
|
|
||||||
|
|
||||||
class RedisConnection:
|
class RedisConnection:
|
||||||
|
|
||||||
REDIS_DEFAULT_USER_DB = 5
|
REDIS_DEFAULT_USER_DB = 5
|
||||||
REDIS_DEFAULT_TIMEOUT = 2 #seconds
|
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):
|
redis_db=REDIS_DEFAULT_USER_DB, **kwargs):
|
||||||
self.sentinel_host = sentinel_host
|
self.redis_host = redis_host
|
||||||
self.sentinel_port = sentinel_port
|
self.redis_port = redis_port
|
||||||
self.sentinel_master_id = sentinel_master_id
|
self.sentinel_master_id = sentinel_master_id
|
||||||
self.timeout = kwargs['timeout'] if 'timeout' in kwargs else self.REDIS_DEFAULT_TIMEOUT
|
self.timeout = kwargs['timeout'] if 'timeout' in kwargs else self.REDIS_DEFAULT_TIMEOUT
|
||||||
self.redis_db = redis_db
|
self.redis_db = redis_db
|
||||||
@@ -19,11 +19,14 @@ class RedisConnection:
|
|||||||
return self.__create_redis_connection()
|
return self.__create_redis_connection()
|
||||||
|
|
||||||
def __create_redis_connection(self):
|
def __create_redis_connection(self):
|
||||||
sentinel = Sentinel([(self.sentinel_host,
|
if self.sentinel_master_id == None:
|
||||||
self.REDIS_SENTINEL_DEFAULT_PORT)],
|
return StrictRedis(host=self.redis_host, port=self.redis_port, db=self.redis_db)
|
||||||
socket_timeout=self.timeout)
|
else:
|
||||||
return sentinel.master_for(
|
sentinel = Sentinel([(self.redis_host,
|
||||||
self.sentinel_master_id,
|
self.redis_port)],
|
||||||
socket_timeout=self.timeout,
|
socket_timeout=self.timeout)
|
||||||
db=self.redis_db
|
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(
|
setup(
|
||||||
name='cartodb_services',
|
name='cartodb_services',
|
||||||
|
|
||||||
version='0.2.0',
|
version='0.3.1',
|
||||||
|
|
||||||
description='CartoDB Services API Python Library',
|
description='CartoDB Services API Python Library',
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ class HereMapsRoutingIsolineTestCase(unittest.TestCase):
|
|||||||
u'32.9699707,0.9462833'])
|
u'32.9699707,0.9462833'])
|
||||||
|
|
||||||
def test_calculate_isochrone_with_valid_params(self, req_mock):
|
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)
|
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)
|
req_mock.register_uri('GET', url, text=self.GOOD_RESPONSE)
|
||||||
response = self.routing.calculate_isochrone('geo!33.0,1.0', 'car',
|
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